From 3fbcc847aa7135a2b8e6704249bfe4271763dd37 Mon Sep 17 00:00:00 2001 From: unixninja92 Date: Tue, 8 Jul 2014 14:13:11 -0400 Subject: [PATCH] Added Policy file checks to JceLoader. Updates HashResult and HashType. Added Hash class --- src/freenet/crypt/Hash.java | 204 +++++++++++++++ src/freenet/crypt/HashResult.java | 28 ++ src/freenet/crypt/HashType.java | 25 +- src/freenet/crypt/JceLoader.java | 32 ++- test/freenet/crypt/HashTest.java | 411 ++++++++++++++++++++++++++++++ 5 files changed, 688 insertions(+), 12 deletions(-) create mode 100644 src/freenet/crypt/Hash.java create mode 100644 test/freenet/crypt/HashTest.java diff --git a/src/freenet/crypt/Hash.java b/src/freenet/crypt/Hash.java new file mode 100644 index 00000000000..16672754148 --- /dev/null +++ b/src/freenet/crypt/Hash.java @@ -0,0 +1,204 @@ +/* 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 java.nio.ByteBuffer; +import java.security.MessageDigest; + +import net.i2p.util.NativeBigInteger; +import freenet.support.HexUtil; + +/** + * The Hash class will generate the hash value of a given set of bytes and also verify that + * a hash matches a given set of bytes. The addBytes methods can be used to pass data into + * a buffer that will be used to generate a hash. Once a hash is generated, the buffer is + * cleared or reset. + * @author unixninja92 + * Suggested HashType to use: SHA256 + */ +public final class Hash{ + private final HashType type; + private MessageDigest digest; + + /** + * Creates an instance of Hash using the specified hashing algorithm. + * @param type The hashing algorithm to use. + */ + public Hash(HashType type){ + this.type = type; + digest = type.get(); + } + + /** + * Generates the hash of all the bytes in the buffer added with the + * addBytes methods. The buffer is then cleared after the hash has been + * generated. + * @return The generated hash of all the bytes added since last reset. + */ + public final byte[] genHash(){ + byte[] result = digest.digest(); + if(type == HashType.ED2K){ + //ED2K does not reset after generating a digest. Work around this issue + digest.reset(); + }else if(type == HashType.TTH){ + //TTH's .reset method is broken or isn't implemented. Work around this bug + digest = type.get(); + } + return result; + } + + /** + * Generates the hash of only the specified bytes. The buffer is cleared before + * processing the input to ensure that no extra data is included. Once the hash + * has been generated, the buffer is cleared again. + * @param input The bytes to hash + * @return The generated hash of the data + */ + public final byte[] genHash(byte[]... input) { + digest.reset(); + addBytes(input); + return genHash(); + } + + /** + * Generates the HashResult of all the bytes in the buffer added with the + * addBytes methods. The buffer is then cleared after the hash has been + * generated. + * @return The generated hash as a HashResult of all the bytes added + * since last reset. + */ + public final HashResult genHashResult() { + return new HashResult(type, genHash()); + } + + /** + * Generates the hash as a HashResult string of only the specified bytes. + * The buffer is cleared before processing the input to ensure that no + * extra data is included. Once the hash has been generated, the buffer + * is cleared again. + * @param input The bytes to hash + * @return The generated hash as a HashResult of the data + */ + public final HashResult genHashResult(byte[]... input){ + digest.reset(); + addBytes(input); + return genHashResult(); + } + + /** + * Generates the hash as a hex string of all the bytes in the buffer added + * with the addBytes methods. The buffer is then cleared after the hash + * has been generated. + * @return The generated hash as a hex string of all the bytes added since + * last reset. + */ + public final String genHexHash() { + return HexUtil.bytesToHex(genHash()); + } + + /** + * Generates the hash as a NativeBigInteger of all the bytes in the buffer + * added with the addBytes methods. The buffer is then cleared after the hash + * has been generated. + * @return The generated hash as a NativeBigInteger of all the bytes added + * since last reset. + */ + public final NativeBigInteger genNativeBigIntegerHash(){ + return new NativeBigInteger(1, genHash()); + } + + /** + * Generates the hash as a NativeBigInteger string of only the specified + * bytes. The buffer is cleared before processing the input to ensure that + * no extra data is included. Once the hash has been generated, the buffer + * is cleared again. + * @param input The bytes to hash + * @return The generated hash as a NativeBigInteger of the data + */ + public final NativeBigInteger genNativeBigIntegerHash(byte[]... data){ + digest.reset(); + addBytes(data); + return genNativeBigIntegerHash(); + } + + /** + * Adds the specified byte to the buffer of bytes to be hashed. + * @param input Byte to be added to hash + */ + public final void addByte(byte input){ + digest.update(input); + } + + /** + * Adds the specified byte arrays to the buffer of bytes to be hashed. + * @param input The byte[]s to add + */ + public final void addBytes(byte[]... input){ + for(byte[] b: input){ + digest.update(b); + } + } + + /** + * Adds the remaining bytes from a ByteBuffer to the buffer of bytes + * to be hashed. The bytes read from the ByteBuffer will be from + * input.position() to input.remaining(). Upon return, the ByteBuffer's + * .position() will be equal to .remaining() and .remaining() will + * stay unchanged. + * @param input The ByteBuffer to be hashed + */ + public final void addBytes(ByteBuffer input){ + digest.update(input); + } + + /** + * Adds the specified portion of the byte[] passed in to the buffer + * of bytes to be hashed. + * @param input The array containing bytes to be hashed + * @param offset Where the first byte to hash is + * @param len How many bytes after the offset to add to hash. + */ + public final void addBytes(byte[] input, int offset, int len){ + digest.update(input, offset, len); + } + + /** + * Generates the hash of the byte arrays provided and checks to see if that hash + * is the same as the one passed in. The buffer is cleared before processing the + * input to ensure that no extra data is included. Once the hash has been + * generated, the buffer is cleared again. + * @param hash The hash to be verified + * @param data The data to be hashed + * @return Returns true if the generated hash matches the passed in hash. + * Otherwise returns false. + */ + public final boolean verify(byte[] hash, byte[]... data){ + return MessageDigest.isEqual(hash, genHash(data)); + } + + /** + * Checks to see if the HashResults passed in are equivalent. Does a simple byte + * compare and type compare. + * @param hash1 The first hash to be compared + * @param hash2 The second hash to be compared + * @return Returns true if the hashes are the same. Otherwise returns false. + */ + public final static boolean verify(HashResult hash1, HashResult hash2){ + return hash1.equals(hash2); + } + + /** + * Generates the hash of the byte arrays provided as a HashResult and checks to + * see if that hash is the same as the one passed in. + * @param hash The HashResult to verify + * @param input The data to check against the HashResult + * @return Returns true if HashResult matches the generated HashResult of the data. + */ + public final static boolean verify(HashResult hash, byte[]... input){ + HashType type = hash.type; + Hash h = new Hash(type); + return verify(hash, new HashResult(type, h.genHash(input))); + } + +} diff --git a/src/freenet/crypt/HashResult.java b/src/freenet/crypt/HashResult.java index 896d16f06dc..f2b95589ac0 100644 --- a/src/freenet/crypt/HashResult.java +++ b/src/freenet/crypt/HashResult.java @@ -1,8 +1,12 @@ +/* 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 java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.security.MessageDigest; import java.util.Arrays; import com.db4o.ObjectContainer; @@ -145,5 +149,29 @@ public HashResult clone() { public String hashAsHex() { return HexUtil.bytesToHex(result); } + + @Override + public boolean equals(Object otherObject){ + if(!(otherObject instanceof HashResult)){ + return false; + } + + HashResult otherHash = (HashResult) otherObject; + if(type != otherHash.type){ + return false; + } + + return MessageDigest.isEqual(result, otherHash.result); + } + + @Override + public int hashCode(){ + int hash = 1; + + hash *= 31 + type.hashCode(); + hash *= 31 + result.hashCode(); + + return hash; + } } diff --git a/src/freenet/crypt/HashType.java b/src/freenet/crypt/HashType.java index 51af98094a4..29baf984117 100644 --- a/src/freenet/crypt/HashType.java +++ b/src/freenet/crypt/HashType.java @@ -1,6 +1,6 @@ -/** - * - */ +/* 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 java.security.MessageDigest; @@ -8,6 +8,8 @@ import org.bitpedia.util.TigerTree; +import freenet.support.Logger; + public enum HashType { // warning: keep in sync with Util.mdProviders! SHA1(1, 20), @@ -24,19 +26,19 @@ public enum HashType { public final String javaName; public final int hashLength; - HashType(int bitmask, int hashLength) { + private HashType(int bitmask, int hashLength) { this.bitmask = bitmask; this.javaName = super.name(); this.hashLength = hashLength; } - HashType(int bitmask, String name, int hashLength) { + private HashType(int bitmask, String name, int hashLength) { this.bitmask = bitmask; this.javaName = name; this.hashLength = hashLength; } - public MessageDigest get() throws NoSuchAlgorithmException { + public final MessageDigest get() { if(javaName == null) { if(this.name().equals("ED2K")) return new Ed2MessageDigest(); @@ -44,14 +46,19 @@ public MessageDigest get() throws NoSuchAlgorithmException { return new TigerTree(); } if(name().equals("SHA256")) { - // User the pool + // Use the pool return freenet.crypt.SHA256.getMessageDigest(); } else { - return MessageDigest.getInstance(javaName, Util.mdProviders.get(javaName)); + try { + return MessageDigest.getInstance(javaName, Util.mdProviders.get(javaName)); + } catch (NoSuchAlgorithmException e) { + Logger.error(HashType.class, "Internal error; please report:", e); + } + return null; } } - public void recycle(MessageDigest md) { + public final void recycle(MessageDigest md) { if(this.equals(SHA256)) { freenet.crypt.SHA256.returnMessageDigest(md); } // Else no pooling. diff --git a/src/freenet/crypt/JceLoader.java b/src/freenet/crypt/JceLoader.java index a497fb62789..7df7d67e712 100644 --- a/src/freenet/crypt/JceLoader.java +++ b/src/freenet/crypt/JceLoader.java @@ -6,11 +6,13 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.lang.reflect.Constructor; +import java.security.GeneralSecurityException; import java.security.Provider; import java.security.Security; import java.security.Signature; import javax.crypto.KeyAgreement; +import javax.crypto.KeyGenerator; import freenet.support.Logger; import freenet.support.io.Closer; @@ -35,9 +37,20 @@ static private boolean checkUse(String prop, String def) if (checkUse("use.NSS","false")) { try { p = (new NSSLoader()).load(checkUse("prefer.NSS")); + try{ + KeyGenerator kgen = KeyGenerator.getInstance("AES", "SunPKCS11-NSS"); + kgen.init(256); + } catch (GeneralSecurityException e) { + final String msg = "Error with SunPKCS11-NSS. " + + "Unlimited policy file not installed."; + Logger.warning(NSSLoader.class, msg, e); + System.out.println(msg); + } } catch(Throwable e) { // FIXME what about Windows/MacOSX/etc? - final String msg = "Unable to load SunPKCS11-NSScrypto provider. This is NOT fatal error, Freenet will work, but some performance degradation possible. Consider installing libnss3 package."; + final String msg = "Unable to load SunPKCS11-NSScrypto provider. " + + "This is NOT fatal error, Freenet will work, but some performance " + + "degradation possible. Consider installing libnss3 package."; Logger.warning(NSSLoader.class, msg, e); } } @@ -55,8 +68,20 @@ static private boolean checkUse(String prop, String def) } BouncyCastle = p; // optional + if (checkUse("use.SunJCE")) { + try{ + KeyGenerator kgen = KeyGenerator.getInstance("AES", "SunJCE"); + kgen.init(256); + } + catch(Throwable e) { + final String msg = "Error with SunJCE. Unlimited policy file not installed."; + Logger.warning(NSSLoader.class, msg, e); + } + SunJCE = Security.getProvider("SunJCE"); + } + else SunJCE = null; + SUN = checkUse("use.SUN") ? Security.getProvider("SUN") : null; - SunJCE = checkUse("use.SunJCE") ? Security.getProvider("SunJCE") : null; } static private class BouncyCastleLoader { private BouncyCastleLoader() {} @@ -64,7 +89,8 @@ private Provider load() throws Throwable { Provider p = Security.getProvider("BC"); if (p == null) { try { - Class c = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); + Class c = + Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); p = (Provider)c.newInstance(); Security.addProvider(p); } catch(Throwable e) { diff --git a/test/freenet/crypt/HashTest.java b/test/freenet/crypt/HashTest.java new file mode 100644 index 00000000000..df498c5161c --- /dev/null +++ b/test/freenet/crypt/HashTest.java @@ -0,0 +1,411 @@ +/* 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.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.security.MessageDigest; + +import net.i2p.util.NativeBigInteger; + +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import junit.framework.TestCase; + +public class HashTest { + static private byte[] helloWorld = "hello world".getBytes(Charset.forName("UTF-8")); + static private byte[] nullArray = null; + static private final HashType[] types = {HashType.MD5, HashType.ED2K, HashType.SHA1, + HashType.TTH, HashType.SHA256, HashType.SHA384, HashType.SHA512}; + static private final String[] trueHashes = { + "5eb63bbbe01eeed093cb22bb8f5acdc3", + "aa010fbc1d14c795d86ef98c95479d17", + "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed", + "ca1158e471d147bb714a6b1b8a537ff756f7abe1b63dc11d", + "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9", + "fdbd8e75a67f29f701a4e040385e2e23986303ea10239211af907fcbb83578b3" + + "e417cb71ce646efd0819dd8c088de1bd", + "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f" + + "989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f" + }; + static private final String[] falseHashes = { + "aa010fbc1d14c795d86ef98c95479d17", + "5eb63bbbe01eeed093cb22bb8f5acdc3", + "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee", + "2aae6c35c94fcfb415dbe95f408b9ce91ee846edb63dc11d", + "ca1158e471d147bb714a6b1b8a537ff756f7abe1b63dc11d9088f7ace2efcde9", + "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9e417cb71ce646efd0819dd8c08" + + "8de1bd", + "fdbd8e75a67f29f701a4e040385e2e23986303ea10239211af907fcbb83578b3e417cb71ce646efd0819dd8c08" + + "8de1bdd830e81f605dcf7dc5542e93ae9cd76f" + }; + + @Test + // This also tests addBytes(byte[]...) and getHash() + public void testGetHashByteArrayArray() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + byte[] abcResult = hash.genHash(helloWorld); + byte[] expectedABCResult = Hex.decode(trueHashes[i]); + assertArrayEquals("HashType: "+types[i].name(), abcResult, expectedABCResult); + } + } + + @Test + // This also tests addBytes(byte[]...) and getHash() + public void testGetHashByteArrayArrayReset() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + byte[] abcResult = hash.genHash(helloWorld); + byte[] abcResult2 = hash.genHash(helloWorld); + assertArrayEquals("HashType: "+types[i].name(), abcResult, abcResult2); + } + } + + + @Test + // This also tests addBytes(byte[]...) and getHash() + public void testGetHashByteArrayArraySameAsMessageDigest() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + MessageDigest md = types[i].get(); + byte[] mdResult = md.digest(helloWorld); + byte[] hashResult = hash.genHash(helloWorld); + assertArrayEquals("HashType: "+types[i].name(), mdResult, hashResult); + } + } + + @Test + // This also tests addBytes(byte[]...) and getHash() + public void testGetHashByteArrayArrayNullInput() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + + boolean throwNull = false; + try{ + hash.genHash(nullArray); + }catch(NullPointerException e){ + throwNull = true; + } + assertTrue("HashType: "+types[i].name(), throwNull); + } + } + + @Test + // This also tests addBytes(byte[]...) + public void testGetHashByteArrayArrayNullMatrixElementInput() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwNulls = false; + byte[][] nullMatrix = {helloWorld, null}; + try{ + hash.genHash(nullMatrix); + }catch(NullPointerException e){ + throwNulls = true; + } + assertTrue("HashType: "+types[i].name(), throwNulls); + } + } + + @Test + // tests getHashResult() as well + public void testGetHashResultHashResultByteArray() { + for(int i = 0; i < types.length; i++){ + HashResult hash2 = new HashResult(types[i], Hex.decode(trueHashes[i])); + Hash hash = new Hash(types[i]); + HashResult hash1 = hash.genHashResult(helloWorld); + assertTrue("HashType: "+types[i].name(), Hash.verify(hash1, hash2)); + } + } + + @Test + public void testGetHashHex(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + hash.addBytes(helloWorld); + String hexHash = hash.genHexHash(); + assertEquals("HashType: "+types[i].name(), trueHashes[i], hexHash); + } + } + + @Test + public void testGetNativeBigIntegerHashByteArrayArray(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + NativeBigInteger abcVector = new NativeBigInteger(1, Hex.decode(trueHashes[i])); + NativeBigInteger result = hash.genNativeBigIntegerHash(helloWorld); + assertEquals("HashType: "+types[i].name(), abcVector, result); + } + } + + @Test + public void testAddByteByte(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + + for (int j = 0; j < helloWorld.length; j++){ + hash.addByte(helloWorld[j]); + } + assertArrayEquals("HashType: "+types[i].name(), + Hex.decode(trueHashes[i]), hash.genHash()); + } + } + + @Test + @SuppressWarnings("null") + public void testAddByteByteNullInput(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwNull = false; + Byte nullByte = null; + try{ + hash.addByte(nullByte); + }catch(NullPointerException e){ + throwNull = true; + } + assertTrue("HashType: "+types[i].name(), throwNull); + } + } + + @Test + public void testAddBytesByteBuffer(){ + for(int i = 0; i < types.length; i++){ + ByteBuffer byteBuffer = ByteBuffer.wrap(helloWorld); + Hash hash = new Hash(types[i]); + hash.addBytes(byteBuffer); + assertArrayEquals("HashType: "+types[i].name(), + Hex.decode(trueHashes[i]), hash.genHash()); + } + } + + @Test + public void testAddBytesByteBufferNullInput(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwNull = false; + ByteBuffer nullBuffer = null; + try{ + hash.addBytes(nullBuffer); + }catch(NullPointerException e){ + throwNull = true; + } + assertTrue("HashType: "+types[i].name(), throwNull); + } + } + + @Test + public void testAddByteByteArrayIntInt(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + hash.addBytes(helloWorld, 0, helloWorld.length/2); + hash.addBytes(helloWorld, helloWorld.length/2, helloWorld.length-helloWorld.length/2); + assertArrayEquals("HashType: "+types[i].name(), + Hex.decode(trueHashes[i]), hash.genHash()); + } + } + + @Test + public void testAddByteByteArrayIntIntNullInput(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwNull = false; + byte[] nullArray = null; + try{ + hash.addBytes(nullArray, 0, helloWorld.length); + }catch(IllegalArgumentException e){ + throwNull = true; + } + assertTrue("HashType: "+types[i].name(), throwNull); + } + } + + @Test + public void testAddByteByteArrayIntIntOffsetOutOfBounds(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwOutOfBounds = false; + try{ + hash.addBytes(helloWorld, -3, helloWorld.length-3); + }catch(ArrayIndexOutOfBoundsException e){ + throwOutOfBounds = true; + } + assertTrue("HashType: "+types[i].name(), throwOutOfBounds); + } + } + + @Test + public void testAddByteByteArrayIntIntLengthOutOfBounds(){ + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwOutOfBounds = false; + try{ + hash.addBytes(helloWorld, 0, helloWorld.length+3); + }catch(IllegalArgumentException e){ + throwOutOfBounds = true; + } + assertTrue("HashType: "+types[i].name(), throwOutOfBounds); + } + } + + @Test + public void testVerifyByteArrayByteArray() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + assertTrue("HashType: "+types[i].name(), + hash.verify(Hex.decode(trueHashes[i]), helloWorld)); + } + } + + @Test + public void testVerifyByteArrayByteArrayFalse() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + assertFalse("HashType: "+types[i].name(), + hash.verify(Hex.decode(falseHashes[i]), helloWorld)); + } + } + + @Test + public void testVerifyByteArrayByteArrayWrongSizeMac() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + + assertFalse("HashType: "+types[i].name(), hash.verify(helloWorld, helloWorld)); + } + } + + @Test + public void testVerifyByteArrayByteArrayNullInputPos1() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwResult = false; + try{ + hash.verify(nullArray, helloWorld); + }catch(NullPointerException e){ + throwResult = true; + } + assertTrue("HashType: "+types[i].name(), throwResult); + } + } + + @Test + public void testVerifyByteArrayByteArrayNullInputPos2() { + for(int i = 0; i < types.length; i++){ + Hash hash = new Hash(types[i]); + boolean throwResult = false; + try{ + hash.verify(helloWorld, nullArray); + }catch(NullPointerException e){ + throwResult = true; + } + assertTrue("HashType: "+types[i].name(), throwResult); + } + } + + @Test + public void testVerifyHashResultByteArray() { + for(int i = 0; i < types.length; i++){ + byte[] hash1 = helloWorld; + HashResult hashResult = new HashResult(types[i], Hex.decode(trueHashes[i])); + + assertTrue("HashType: "+types[i].name(), Hash.verify(hashResult, hash1)); + } + } + + @Test + public void testVerifyHashResultByteArrayFalse() { + for(int i = 0; i < types.length; i++){ + byte[] hash1 = helloWorld; + HashResult hashResult = new HashResult(types[i], Hex.decode(falseHashes[i])); + + assertFalse("HashType: "+types[i].name(), Hash.verify(hashResult, hash1)); + } + } + + @Test + public void testVerifyHashResultByteArrayWrongSizeMac() { + for(int i = 0; i < types.length; i++){ + byte[] hash1 = helloWorld; + HashResult hashResult = new HashResult(types[i], hash1); + + assertFalse("HashType: "+types[i].name(), Hash.verify(hashResult, hash1)); + } + } + + @Test + public void testVerifyHashResultByteArrayNullInputPos1() { + for(int i = 0; i < types.length; i++){ + byte[] hashResult = Hex.decode(trueHashes[i]); + boolean throwResult = false; + HashResult nullResult = null; + try{ + Hash.verify(nullResult, hashResult); + }catch(NullPointerException e){ + throwResult = true; + } + assertTrue("HashType: "+types[i].name(), throwResult); + } + } + + @Test + public void testVerifyHashResultByteArrayNullInputPos2() { + for(int i = 0; i < types.length; i++){ + HashResult hash1 = new HashResult(types[i], Hex.decode(trueHashes[i])); + boolean throwResult = false; + try{ + Hash.verify(hash1, nullArray); + }catch(NullPointerException e){ + throwResult = true; + } + assertTrue("HashType: "+types[i].name(), throwResult); + } + } + + @Test + public void testVerifyHashResultHashResult() { + for(int i = 0; i < types.length; i++){ + HashResult hash = new HashResult(types[i], Hex.decode(trueHashes[i])); + + assertTrue("HashType: "+types[i].name(), Hash.verify(hash, hash)); + } + } + + @Test + public void testVerifyHashResultHashResultFalse() { + for(int i = 0; i < types.length; i++){ + HashResult hash1 = new HashResult(types[i], Hex.decode(trueHashes[i])); + HashResult hash2 = new HashResult(types[i], Hex.decode(falseHashes[i])); + + assertFalse("HashType: "+types[i].name(), Hash.verify(hash1, hash2)); + } + } + + @Test + public void testVerifyHashResultHashResultNullInputPos1() { + for(int i = 0; i < types.length; i++){ + HashResult hash = new HashResult(types[i], Hex.decode(trueHashes[i])); + boolean throwResult = false; + HashResult nullResult = null; + try{ + Hash.verify(nullResult, hash); + }catch(NullPointerException e){ + throwResult = true; + } + assertTrue("HashType: "+types[i].name(), throwResult); + } + } + + @Test + public void testVerifyHashResultHashResultNullInputPos2() { + for(int i = 0; i < types.length; i++){ + HashResult hash = new HashResult(types[i], Hex.decode(trueHashes[i])); + HashResult nullResult = null; + + assertFalse("HashType: "+types[i].name(), Hash.verify(hash, nullResult)); + } + } +}