// Copyright (c) 2014 Tom Zhou<iwebpp@gmail.com>
package com.iwebpp.crypto.tests;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import com.iwebpp.crypto.TweetNacl;
import static com.iwebpp.crypto.TweetNacl.Box.nonceLength;
public final class TweetNaclTest {
private static final String TAG = "TweetNaclTest";
private boolean testBox() throws UnsupportedEncodingException {
// keypair A
byte [] ska = new byte[32]; for (int i = 0; i < 32; i ++) ska[i] = 0;
TweetNacl.Box.KeyPair ka = TweetNacl.Box.keyPair_fromSecretKey(ska);
String skat = "";
for (int i = 0; i < ka.getSecretKey().length; i ++)
skat += " "+ka.getSecretKey()[i];
Log.d(TAG, "skat: "+skat);
String pkat = "";
for (int i = 0; i < ka.getPublicKey().length; i ++)
pkat += " "+ka.getPublicKey()[i];
Log.d(TAG, "pkat: "+pkat);
// keypair B
byte [] skb = new byte[32]; for (int i = 0; i < 32; i ++) skb[i] = 1;
TweetNacl.Box.KeyPair kb = TweetNacl.Box.keyPair_fromSecretKey(skb);
String skbt = "";
for (int i = 0; i < kb.getSecretKey().length; i ++)
skbt += " "+kb.getSecretKey()[i];
Log.d(TAG, "skbt: "+skbt);
String pkbt = "";
for (int i = 0; i < kb.getPublicKey().length; i ++)
pkbt += " "+kb.getPublicKey()[i];
Log.d(TAG, "pkbt: "+pkbt);
// peer A -> B
TweetNacl.Box pab = new TweetNacl.Box(kb.getPublicKey(), ka.getSecretKey(), 0);
// peer B -> A
TweetNacl.Box pba = new TweetNacl.Box(ka.getPublicKey(), kb.getSecretKey(), 0);
// messages
String m0 = "Helloword, Am Tom ...";
// cipher A -> B
byte [] cab = pab.box(m0.getBytes("utf-8"));
String cabt = "";
for (int i = 0; i < cab.length; i ++)
cabt += " "+cab[i];
Log.d(TAG, "cabt: "+cabt);
byte [] mba = pba.open(cab);
String mbat = "";
for (int i = 0; i < mba.length; i ++)
mbat += " "+mba[i];
Log.d(TAG, "mbat: "+mbat);
String nm0 = new String(mba, "utf-8");
if (nm0.equals(m0)) {
Log.d(TAG, "box/open string success @" + m0);
} else {
Log.e(TAG, "box/open string failed @" + m0 + " / " + nm0);
}
// cipher B -> A
byte [] b0 = new byte[6];
Log.d(TAG, "box@" + System.currentTimeMillis());
byte [] cba = pba.box(b0);
byte [] mab = pab.open(cba);
Log.d(TAG, "open@" + System.currentTimeMillis());
if (b0.length == mab.length) {
int rc = 0;
for (int i = 0; i < b0.length; i ++)
if (!(b0[i] == mab[i])) {
rc = -1;
Log.e(TAG, "box/open binary failed @" + b0[i] + " / " + mab[i]);
}
if (rc == 0)
Log.d(TAG, "box/open binary success @" + b0);
} else {
Log.e(TAG, "box/open binary failed @" + b0 + " / " + mab);
}
return true;
}
private boolean testBoxNonce() throws UnsupportedEncodingException {
// explicit nonce
byte [] theNonce = new byte[nonceLength];
com.iwebpp.crypto.TweetNacl.randombytes(theNonce, nonceLength);
String theNoncet = "";
for (int i = 0; i < theNonce.length; i ++)
theNoncet += " "+theNonce[i];
Log.d(TAG, "BoxNonce: "+theNoncet);
// keypair A
byte [] ska = new byte[32]; for (int i = 0; i < 32; i ++) ska[i] = 0;
TweetNacl.Box.KeyPair ka = TweetNacl.Box.keyPair_fromSecretKey(ska);
String skat = "";
for (int i = 0; i < ka.getSecretKey().length; i ++)
skat += " "+ka.getSecretKey()[i];
Log.d(TAG, "skat: "+skat);
String pkat = "";
for (int i = 0; i < ka.getPublicKey().length; i ++)
pkat += " "+ka.getPublicKey()[i];
Log.d(TAG, "pkat: "+pkat);
// keypair B
byte [] skb = new byte[32]; for (int i = 0; i < 32; i ++) skb[i] = 1;
TweetNacl.Box.KeyPair kb = TweetNacl.Box.keyPair_fromSecretKey(skb);
String skbt = "";
for (int i = 0; i < kb.getSecretKey().length; i ++)
skbt += " "+kb.getSecretKey()[i];
Log.d(TAG, "skbt: "+skbt);
String pkbt = "";
for (int i = 0; i < kb.getPublicKey().length; i ++)
pkbt += " "+kb.getPublicKey()[i];
Log.d(TAG, "pkbt: "+pkbt);
// peer A -> B
TweetNacl.Box pab = new TweetNacl.Box(kb.getPublicKey(), ka.getSecretKey());
// peer B -> A
TweetNacl.Box pba = new TweetNacl.Box(ka.getPublicKey(), kb.getSecretKey());
// messages
String m0 = "Helloword, Am Tom ...";
// cipher A -> B
byte [] cab = pab.box(m0.getBytes("utf-8"), theNonce);
String cabt = "";
for (int i = 0; i < cab.length; i ++)
cabt += " "+cab[i];
Log.d(TAG, "cabt: "+cabt);
byte [] mba = pba.open(cab, theNonce);
String mbat = "";
for (int i = 0; i < mba.length; i ++)
mbat += " "+mba[i];
Log.d(TAG, "mbat: "+mbat);
String nm0 = new String(mba, "utf-8");
if (nm0.equals(m0)) {
Log.d(TAG, "box/open string success (with nonce) @" + m0);
} else {
Log.e(TAG, "box/open string failed @ (with nonce)" + m0 + " / " + nm0);
}
// cipher B -> A
byte [] b0 = new byte[6];
Log.d(TAG, "box@" + System.currentTimeMillis());
byte [] cba = pba.box(b0, theNonce);
byte [] mab = pab.open(cba, theNonce);
Log.d(TAG, "open@" + System.currentTimeMillis());
if (b0.length == mab.length) {
int rc = 0;
for (int i = 0; i < b0.length; i ++)
if (!(b0[i] == mab[i])) {
rc = -1;
Log.e(TAG, "box/open binary failed (with nonce) @" + b0[i] + " / " + mab[i]);
}
if (rc == 0)
Log.d(TAG, "box/open binary success (with nonce) @" + b0);
} else {
Log.e(TAG, "box/open binary failed (with nonce) @" + b0 + " / " + mab);
}
return true;
}
private boolean testSecretBox() throws UnsupportedEncodingException {
// shared key
byte [] shk = new byte[TweetNacl.SecretBox.keyLength];
for (int i = 0; i < shk.length; i ++)
shk[i] = 0x66;
// peer A -> B
TweetNacl.SecretBox pab = new TweetNacl.SecretBox(shk, 0);
// peer B -> A
TweetNacl.SecretBox pba = new TweetNacl.SecretBox(shk, 0);
// messages
String m0 = "Helloword, Am Tom ...";
// cipher A -> B
Log.d(TAG, "stress on secret box@"+m0);
for (int t = 0; t < 19; t ++, m0 += m0) {
byte [] mb0 = m0.getBytes("utf-8");
Log.d(TAG, "\n\n\tstress/"+(mb0.length/1000.0) +"kB: " + t + " times");
/*String mb0t = "mb0/"+mb0.length + ": ";
for (int i = 0; i < mb0.length; i ++)
mb0t += " "+mb0[i];
Log.d(TAG, mb0t);
*/
Log.d(TAG, "secret box ...@" + System.currentTimeMillis());
byte [] cab = pab.box(mb0);
Log.d(TAG, "... secret box@" + System.currentTimeMillis());
/*String cabt = "cab/"+cab.length + ": ";
for (int i = 0; i < cab.length; i ++)
cabt += " "+cab[i];
Log.d(TAG, cabt);
*/
Log.d(TAG, "\nsecret box open ...@" + System.currentTimeMillis());
byte [] mba = pba.open(cab);
Log.d(TAG, "... secret box open@" + System.currentTimeMillis());
/*
String mbat = "mba/"+mba.length + ": ";
for (int i = 0; i < mba.length; i ++)
mbat += " "+mba[i];
Log.d(TAG, mbat);
*/
String nm0 = new String(mba, "utf-8");
if (nm0.equals(m0)) {
Log.d(TAG, "\tsecret box/open succes");
} else {
Log.e(TAG, "\tsecret box/open failed @" + m0 + " / " + nm0);
return false;
}
}
return true;
}
private boolean testSecretBoxNonce() throws UnsupportedEncodingException {
// shared key plus explicit nonce
// explicit nonce
byte [] theNonce = new byte[nonceLength];
com.iwebpp.crypto.TweetNacl.randombytes(theNonce, nonceLength);
String theNoncet = "";
for (int i = 0; i < theNonce.length; i ++)
theNoncet += " "+theNonce[i];
Log.d(TAG, "SecretBoxNonce: "+theNoncet);
byte [] shk = new byte[TweetNacl.SecretBox.keyLength];
for (int i = 0; i < shk.length; i ++)
shk[i] = 0x66;
// peer A -> B
TweetNacl.SecretBox pab = new TweetNacl.SecretBox(shk);
// peer B -> A
TweetNacl.SecretBox pba = new TweetNacl.SecretBox(shk);
// messages
String m0 = "Helloword, Am Tom ...";
// cipher A -> B
Log.d(TAG, "stress on secret box with explicit nonce@"+m0);
for (int t = 0; t < 19; t ++, m0 += m0) {
byte [] mb0 = m0.getBytes("utf-8");
Log.d(TAG, "\n\n\tstress/"+(mb0.length/1000.0) +"kB: " + t + " times");
/*String mb0t = "mb0/"+mb0.length + ": ";
for (int i = 0; i < mb0.length; i ++)
mb0t += " "+mb0[i];
Log.d(TAG, mb0t);
*/
Log.d(TAG, "secret box ...@" + System.currentTimeMillis());
byte [] cab = pab.box(mb0, theNonce);
Log.d(TAG, "... secret box@" + System.currentTimeMillis());
/*String cabt = "cab/"+cab.length + ": ";
for (int i = 0; i < cab.length; i ++)
cabt += " "+cab[i];
Log.d(TAG, cabt);
*/
Log.d(TAG, "\nsecret box open ...@" + System.currentTimeMillis());
byte [] mba = pba.open(cab, theNonce);
Log.d(TAG, "... secret box open@" + System.currentTimeMillis());
/*
String mbat = "mba/"+mba.length + ": ";
for (int i = 0; i < mba.length; i ++)
mbat += " "+mba[i];
Log.d(TAG, mbat);
*/
String nm0 = new String(mba, "utf-8");
if (nm0.equals(m0)) {
Log.d(TAG, "\tsecret box/open success (with nonce)");
} else {
Log.e(TAG, "\tsecret box/open failed (with nonce) @" + m0 + " / " + nm0);
return false;
}
}
return true;
}
private boolean testSign() throws UnsupportedEncodingException {
// keypair A
TweetNacl.Signature.KeyPair ka = TweetNacl.Signature.keyPair();
// keypair B
TweetNacl.Signature.KeyPair kb = TweetNacl.Signature.keyPair();
// peer A -> B
TweetNacl.Signature pab = new TweetNacl.Signature(kb.getPublicKey(), ka.getSecretKey());
// peer B -> A
TweetNacl.Signature pba = new TweetNacl.Signature(ka.getPublicKey(), kb.getSecretKey());
// messages
String m0 = "Helloword, Am Tom ...";
// signature A -> B
Log.d(TAG, "\nsign...@" + System.currentTimeMillis());
byte [] sab = pab.sign(m0.getBytes("utf-8"));
Log.d(TAG, "...sign@" + System.currentTimeMillis());
String sgt = "sign@"+m0 + ": ";
for (int i = 0; i < TweetNacl.Signature.signatureLength; i ++)
sgt += " "+sab[i];
Log.d(TAG, sgt);
Log.d(TAG, "verify...@" + System.currentTimeMillis());
byte [] oba = pba.open(sab);
Log.d(TAG, "...verify@" + System.currentTimeMillis());
if (oba == null) {
Log.e(TAG, "verify failed @" + m0);
} else {
String nm0 = new String(oba, "utf-8");
if (nm0.equals(m0)) {
Log.d(TAG, "sign success @" + m0);
} else {
Log.e(TAG, "sign failed @" + m0 + " / " + nm0);
}
}
// keypair C
byte [] seed = new byte[TweetNacl.Signature.seedLength]; for (int i = 0; i < seed.length; i ++) seed[i] = 0x66;
TweetNacl.Signature.KeyPair kc = TweetNacl.Signature.keyPair_fromSeed(seed);
String skct = "";
for (int i = 0; i < kc.getSecretKey().length; i ++)
skct += " "+kc.getSecretKey()[i];
Log.d(TAG, "skct: "+skct);
String pkct = "";
for (int i = 0; i < kc.getPublicKey().length; i ++)
pkct += " "+kc.getPublicKey()[i];
Log.d(TAG, "pkct: "+pkct);
// self-signed
TweetNacl.Signature pcc = new TweetNacl.Signature(kc.getPublicKey(), kc.getSecretKey());
Log.d(TAG, "\nself-sign...@" + System.currentTimeMillis());
byte [] scc = pcc.sign(m0.getBytes("utf-8"));
Log.d(TAG, "...self-sign@" + System.currentTimeMillis());
String ssc = "self-sign@"+m0 + ": ";
for (int i = 0; i < TweetNacl.Signature.signatureLength; i ++)
ssc += " "+scc[i];
Log.d(TAG, ssc);
Log.d(TAG, "self-verify...@" + System.currentTimeMillis());
byte [] occ = pcc.open(scc);
Log.d(TAG, "...self-verify@" + System.currentTimeMillis());
if (occ == null) {
Log.e(TAG, "self-verify failed @" + m0);
} else {
String nm0 = new String(occ, "utf-8");
if (nm0.equals(m0)) {
Log.d(TAG, "self-sign success @" + m0);
} else {
Log.e(TAG, "self-sign failed @" + m0 + " / " + nm0);
}
}
return true;
}
/*
* SHA-512
* */
private boolean testHash() throws UnsupportedEncodingException {
String m0 = "Helloword, Am Tom ...";
byte [] b0 = m0.getBytes("utf-8");
Log.d(TAG, "\nsha512...@" + System.currentTimeMillis());
byte [] hash = TweetNacl.Hash.sha512(b0);
Log.d(TAG, "...sha512@" + System.currentTimeMillis());
String hst = "sha512@"+m0 + "/"+b0.length + ": ";
for (int i = 0; i < hash.length; i ++)
hst += " "+hash[i];
Log.d(TAG, hst);
return true;
}
/*
* bench test using tweetnacl.c, tweetnacl.js result
* */
private boolean testBench() {
return true;
}
public void start() {
(new Thread(new Runnable() {
public void run() {
Log.d(TAG, "start test");
try {
testSecretBox();
testSecretBoxNonce();
testBox();
testBoxNonce();
testHash();
testSign();
///testBench();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
})).start();
}
public static void main(String[] args) {
TweetNaclTest t = new TweetNaclTest();
t.start();
}
}