/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.crypt; import static org.junit.Assert.*; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Security; import javax.crypto.spec.IvParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import freenet.support.Fields; public class MessageAuthCodeTest{ static private final MACType[] types = MACType.values(); static private final byte[][] keys = { Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), Hex.decode("e69dae0aab9f91c03a325dcc9436fa903ef49901c8e11c000430d90ad45e7603")}; static private final byte[] hmacMessage; static{ byte[] temp = null; try { temp = "Hi There".getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new Error(e); } hmacMessage = temp; } static private byte[][] messages = { hmacMessage, hmacMessage, hmacMessage, Hex.decode("66f75c0e0c7a406586")}; static private final IvParameterSpec[] IVs = { null, null, null, new IvParameterSpec(Hex.decode("166450152e2394835606a9d1dd2cdc8b"))}; static private final byte[][] trueMacs = { Hex.decode("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"), Hex.decode("afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7" + "f4af152e8b2fa9cb6"), Hex.decode("87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a70" + "2038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"), Hex.decode("2924f51b9c2eff5df09db61dd03a9ca1")}; static private final byte[][] falseMacs = { Hex.decode("4bb5e21dd13001ed5faccfcfdaf8a854881dc200c9833da726e9376c2e32cff7"), Hex.decode("4bb5e21dd13001ed5faccfcfdaf8a854881dc200c9833da726e9376c2e32cff7faea9ea9076ede7" + "f4af152e8b2fa9cb6"), Hex.decode("4bb5e21dd13001ed5faccfcfdaf8a854881dc200c9833da726e9376c2e32cff7faea9ea9076ede7" + "2038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"), Hex.decode("881dc200c9833da726e9376c2e32cff7")}; static{ Security.addProvider(new BouncyCastleProvider()); } @Test public void testAddByte() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } for (int j = 0; j < messages[i].length; j++){ mac.addByte(messages[i][j]); } assertArrayEquals("MACType: "+types[i].name(), Fields.copyToArray(mac.genMac()), trueMacs[i]); } } @Test @SuppressWarnings("null") public void testAddByteNullInput() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } boolean throwNull = false; Byte nullByte = null; try{ mac.addByte(nullByte); }catch(NullPointerException e){ throwNull = true; } assertTrue("MACType: "+types[i].name(), throwNull); } } @Test public void testAddBytesByteBuffer() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } ByteBuffer byteBuffer = ByteBuffer.wrap(messages[i]); mac.addBytes(byteBuffer); assertArrayEquals("MACType: "+types[i].name(), mac.genMac().array(), trueMacs[i]); } } @Test (expected = IllegalArgumentException.class) public void testAddBytesByteBufferNullInput() throws InvalidKeyException { int i = 0; MessageAuthCode mac; mac = new MessageAuthCode(types[i], keys[i]); ByteBuffer byteBuffer = null; mac.addBytes(byteBuffer); } @Test public void testAddBytesByteArrayIntInt() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } mac.addBytes(messages[i], 0, messages[i].length/2); mac.addBytes(messages[i], messages[i].length/2, messages[i].length-messages[i].length/2); assertArrayEquals("MACType: "+types[i].name(), mac.genMac().array(), trueMacs[i]); } } @Test public void testAddBytesByteArrayIntIntNullInput() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } boolean throwNull = false; byte[] nullArray = null; try{ mac.addBytes(nullArray, 0, messages[i].length); }catch(NullPointerException e){ throwNull = true; } assertTrue("MACType: "+types[i].name(), throwNull); } } @Test public void testAddBytesByteArrayIntIntOffsetOutOfBounds() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } boolean throwNull = false; try{ mac.addBytes(messages[i], -3, messages[i].length-3); }catch(IllegalArgumentException e){ throwNull = true; } assertTrue("MACType: "+types[i].name(), throwNull); } } @Test public void testAddBytesByteArrayIntIntLengthOutOfBounds() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } boolean throwNull = false; try{ mac.addBytes(messages[i], 0, messages[i].length+3); }catch(IllegalArgumentException e){ throwNull = true; } assertTrue("MACType: "+types[i].name(), throwNull); } } @Test //tests .genMac() and .addBytes(byte[]...] as well public void testGetMacByteArrayArray() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } byte[] result = mac.genMac(messages[i]).array(); assertTrue("MACType: "+types[i].name(), MessageAuthCode.verify(result, trueMacs[i])); } } @Test public void testGetMacByteArrayArrayReset() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } mac.addBytes(messages[i]); byte[] result = mac.genMac(messages[i]).array(); assertArrayEquals("MACType: "+types[i].name(), result, trueMacs[i]); } } @Test public void testGetMacByteArrayArrayNullInput() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } boolean throwNull = false; byte[] nullArray = null; try{ mac.genMac(nullArray); }catch(NullPointerException e){ throwNull = true; } assertTrue("MACType: "+types[i].name(), throwNull); } } @Test (expected = NullPointerException.class) public void testGetMacByteArrayArrayNullMatrixElementInput() throws InvalidKeyException, InvalidAlgorithmParameterException { MessageAuthCode mac = new MessageAuthCode(types[3], keys[3], IVs[3]); byte[][] nullMatrix = {messages[3], null}; mac.genMac(nullMatrix); } @Test public void testVerify() { assertTrue(MessageAuthCode.verify(trueMacs[3], trueMacs[3])); } @Test public void testVerifyFalse() { assertFalse(MessageAuthCode.verify(trueMacs[3], falseMacs[3])); } @Test public void testVerifyNullInput1() { byte[] nullArray = null; assertFalse(MessageAuthCode.verify(nullArray, trueMacs[3])); } @Test public void testVerifyNullInput2() { byte[] nullArray = null; assertFalse(MessageAuthCode.verify(trueMacs[1], nullArray)); } @Test public void testVerifyData() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ System.out.println(types[i].name()); MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } assertTrue("MACType: "+types[i].name(), mac.verifyData(trueMacs[i], messages[i])); } } @Test public void testVerifyDataFalse() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } assertFalse("MACType: "+types[i].name(), mac.verifyData(falseMacs[i], messages[i])); } } @Test public void testVerifyDataNullInput1() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } byte[] nullArray = null; assertFalse("MACType: "+types[i].name(), mac.verifyData(nullArray, messages[i])); } } @Test public void testVerifyDataNullInput2() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } boolean throwNull = false; byte[] nullArray = null; try{ mac.verifyData(trueMacs[i], nullArray); }catch(NullPointerException e){ throwNull = true; } assertTrue("MACType: "+types[i].name(), throwNull); } } @Test public void testGetKey() throws InvalidKeyException, InvalidAlgorithmParameterException { for(int i = 0; i < types.length; i++){ MessageAuthCode mac; if(types[i].ivlen != -1){ mac = new MessageAuthCode(types[i], keys[i], IVs[i]); } else{ mac = new MessageAuthCode(types[i], keys[i]); } assertArrayEquals("MACType: "+types[i].name(), mac.getKey().getEncoded(), keys[i]); } } @Test public void testGetIV() throws InvalidKeyException, InvalidAlgorithmParameterException { MessageAuthCode mac = new MessageAuthCode(types[3], keys[3], IVs[3]); assertArrayEquals(mac.getIv().getIV(), IVs[3].getIV()); } @Test (expected = UnsupportedTypeException.class) public void testGetIVUnsupportedTypeException() throws InvalidKeyException { MessageAuthCode mac = new MessageAuthCode(types[0], keys[0]); mac.getIv(); } @Test public void testSetIVIvParameterSpec() throws InvalidKeyException, InvalidAlgorithmParameterException { MessageAuthCode mac = new MessageAuthCode(types[3], keys[3], IVs[3]); mac.genIV(); mac.setIV(IVs[3]); assertArrayEquals(IVs[3].getIV(), mac.getIv().getIV()); } @Test (expected = IllegalArgumentException.class) public void testSetIVIvParameterSpecNullInput() throws InvalidKeyException, InvalidAlgorithmParameterException { IvParameterSpec nullInput = null; MessageAuthCode mac = new MessageAuthCode(types[3], keys[3], IVs[3]); mac.setIV(nullInput); } @Test (expected = UnsupportedTypeException.class) public void testSetIVIvParameterSpecUnsupportedTypeException() throws InvalidKeyException, InvalidAlgorithmParameterException { MessageAuthCode mac = new MessageAuthCode(types[0], keys[0]); mac.setIV(IVs[1]); } @Test public void testGenIV() throws InvalidKeyException, InvalidAlgorithmParameterException { MessageAuthCode mac = new MessageAuthCode(types[3], keys[3], IVs[3]); assertNotNull(mac.genIV()); } @Test public void testGenIVLength() throws InvalidKeyException, InvalidAlgorithmParameterException { MessageAuthCode mac = new MessageAuthCode(types[3], keys[3], IVs[3]); assertEquals(mac.genIV().getIV().length, types[3].ivlen); } @Test (expected = UnsupportedTypeException.class) public void testGenIVUnsupportedTypeException() throws InvalidKeyException { MessageAuthCode mac = new MessageAuthCode(types[0], keys[0]); mac.genIV(); } }