package no.ntnu.item.csv.cryptoutil; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import no.ntnu.item.cryptoutil.Cryptoutil; import org.junit.Assert; import org.junit.Test; public class CryptoutilTest { @Test public void testNormalHashing() throws Exception { byte[] test = { 50, 100, 34, 56, 78 }; byte[] res = Cryptoutil.hash(test, 0); Assert.assertEquals(Cryptoutil.HASH_LENGTH / 8, res.length); MessageDigest md = MessageDigest.getInstance(Cryptoutil.HASH_ALGORITHM); md.update(test); byte[] tmp = md.digest(); md.reset(); md.update(tmp); Assert.assertArrayEquals(md.digest(), res); } @Test public void testTruncatedHashing() throws Exception { byte[] test = { 50, 100, 34, 56, 78 }; byte[] res = Cryptoutil.hash(test, 16); Assert.assertEquals(16, res.length); MessageDigest md = MessageDigest.getInstance(Cryptoutil.HASH_ALGORITHM); md.update(test); byte[] tmp = md.digest(); md.reset(); md.update(tmp); byte[] res2 = md.digest(); byte[] trunc = new byte[16]; for (int i = 0; i < trunc.length; i++) { trunc[i] = res2[i]; } Assert.assertArrayEquals(trunc, res); } @Test public void testNonTruncatedNHashing() throws Exception { byte[] msg = { 50, 100, 34, 56, 78, 12, 56, 13, 16, 68, 44, 45, 76, 45, 34, 12 }; byte[] store = msg; byte[] tmp = store; MessageDigest md = MessageDigest.getInstance(Cryptoutil.HASH_ALGORITHM); for (int i = 1; i < 15; i++) { md.reset(); md.update(store); tmp = md.digest(); md.reset(); md.update(tmp); tmp = md.digest(); Assert.assertArrayEquals(tmp, Cryptoutil.nHash(msg, i, 0)); store = tmp; } } @Test public void testTruncatedNHashing() throws Exception { byte[] msg = { 50, 100, 34, 56, 78, 12, 56, 13, 16, 68, 44, 45, 76, 45, 34, 12 }; byte[] store; byte[] truncated; int truncate_to; for (int k = 2; k < 33; k = k * 2) { truncate_to = k; truncated = new byte[truncate_to]; store = msg; MessageDigest md = MessageDigest .getInstance(Cryptoutil.HASH_ALGORITHM); for (int i = 1; i < 5; i++) { md.reset(); md.update(store); store = md.digest(); md.reset(); md.update(store); store = md.digest(); for (int j = 0; j < truncate_to; j++) { truncated[j] = store[j]; } store = truncated; byte[] tmp = Cryptoutil.nHash(msg, i, truncate_to); Assert.assertEquals(truncate_to, tmp.length); Assert.assertArrayEquals(store, tmp); } } } @Test public void testSigning() { KeyPair pair = Cryptoutil.generateAsymmetricKeys(); byte[] msg = { 50, 100, 34, 56, 78, 12, 56, 13, 16, 68, 44, 45, 76, 45, 34, 12 }; byte[] hashed = Cryptoutil.hash(msg, -1); byte[] sign = Cryptoutil.signature(hashed, pair.getPrivate()); Assert.assertTrue(Cryptoutil.signature_valid(sign, hashed, pair.getPublic())); KeyPair pair2 = Cryptoutil.generateAsymmetricKeys(); Assert.assertFalse(Cryptoutil.signature_valid(sign, hashed, pair2.getPublic())); } @Test public void testRSAKeyGeneration() { int TEST_AMOUNT = 15; // We need keys to be of a static size //TODO: Figure out why // PrivateExponent.length is sometimes 129 for (int i = 0; i < TEST_AMOUNT; i++) { KeyPair pair = Cryptoutil.generateAsymmetricKeys(); RSAPrivateKey priv = (RSAPrivateKey) pair.getPrivate(); RSAPublicKey pub = (RSAPublicKey) pair.getPublic(); Assert.assertEquals(Cryptoutil.ASYM_SIZE / 8 + 1, priv.getModulus() .toByteArray().length); Assert.assertEquals(Cryptoutil.ASYM_SIZE / 8 + 1, pub.getModulus() .toByteArray().length); byte[] privExp = priv.getPrivateExponent().toByteArray(); if (privExp.length == Cryptoutil.ASYM_SIZE / 8 + 1) { Assert.assertEquals(0, privExp[0]); } Assert.assertEquals(3, pub.getPublicExponent().toByteArray().length); } } @Test public void testRSASerialization() { KeyPair pair = Cryptoutil.generateAsymmetricKeys(); RSAPrivateKey rsaPriv = (RSAPrivateKey) pair.getPrivate(); RSAPublicKey rsaPub = (RSAPublicKey) pair.getPublic(); byte[] b_priv = Cryptoutil.serializePrivateKey(rsaPriv); byte[] b_pub = Cryptoutil.serializePublicKey(rsaPub); RSAPrivateKey serPriv = (RSAPrivateKey) Cryptoutil .createRSAPrivateKey(b_priv); RSAPublicKey serPub = (RSAPublicKey) Cryptoutil .createRSAPublicKey(b_pub); Assert.assertArrayEquals(rsaPriv.getModulus().toByteArray(), serPriv .getModulus().toByteArray()); Assert.assertArrayEquals(rsaPub.getModulus().toByteArray(), serPub .getModulus().toByteArray()); Assert.assertArrayEquals(rsaPriv.getModulus().toByteArray(), serPub .getModulus().toByteArray()); Assert.assertArrayEquals(rsaPub.getModulus().toByteArray(), serPriv .getModulus().toByteArray()); Assert.assertArrayEquals(rsaPriv.getPrivateExponent().toByteArray(), serPriv.getPrivateExponent().toByteArray()); Assert.assertArrayEquals(rsaPub.getPublicExponent().toByteArray(), serPub.getPublicExponent().toByteArray()); // Test a signature to be safe byte[] msg = new String("Hello World 110011").getBytes(); byte[] sign1 = Cryptoutil.signature(msg, rsaPriv); byte[] sign2 = Cryptoutil.signature(msg, serPriv); Assert.assertTrue(Cryptoutil.signature_valid(sign1, msg, serPub)); Assert.assertTrue(Cryptoutil.signature_valid(sign1, msg, rsaPub)); Assert.assertTrue(Cryptoutil.signature_valid(sign2, msg, serPub)); Assert.assertTrue(Cryptoutil.signature_valid(sign2, msg, rsaPub)); } @Test public void testThatRSASerializationWillWork() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { // Does not test our functionality, just checking that this is possible byte[] msg = new String("Hello World").getBytes(); KeyPair pair = Cryptoutil.generateAsymmetricKeys(); RSAPrivateKey priv = (RSAPrivateKey) pair.getPrivate(); RSAPublicKey pub = (RSAPublicKey) pair.getPublic(); byte[] sign = Cryptoutil.signature(msg, priv); byte[] mod = priv.getModulus().toByteArray(); byte[] priv_b = priv.getPrivateExponent().toByteArray(); byte[] pub_b = pub.getPublicExponent().toByteArray(); KeyFactory fact = KeyFactory.getInstance("RSA"); BigInteger modulus = new BigInteger(1, mod); BigInteger privateExponent = new BigInteger(1, priv_b); RSAPrivateKeySpec privks = new RSAPrivateKeySpec(modulus, privateExponent); RSAPrivateKey rsapriv = (RSAPrivateKey) fact.generatePrivate(privks); BigInteger publicExponent = new BigInteger(1, pub_b); RSAPublicKeySpec pubks = new RSAPublicKeySpec(modulus, publicExponent); RSAPublicKey rsapub = (RSAPublicKey) fact.generatePublic(pubks); boolean works = Cryptoutil.signature_valid(sign, msg, rsapub); Assert.assertTrue(works); byte[] sign2 = Cryptoutil.signature(msg, rsapriv); boolean works_r = Cryptoutil.signature_valid(sign2, msg, pub); Assert.assertTrue(works_r); } }