package io.eguan.hash;
/*
* #%L
* Project eguan
* %%
* Copyright (C) 2012 - 2017 Oodrive
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import io.eguan.hash.ByteBufferDigest;
import io.eguan.hash.HashAlgorithm;
import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.google.protobuf.ByteString;
/**
* Unit tests for {@link ByteBufferDigest}.
*
* @author oodrive
* @author llambert
*
*/
public class TestByteBufferDigest {
private static final String TEXT = "The quick brown fox jumps over the lazy dog !";
private static final ByteBuffer REF;
static {
final byte[] text = TEXT.getBytes();
REF = ByteBuffer.allocateDirect(text.length);
REF.put(text);
Assert.assertEquals(REF.capacity(), REF.position());
}
/** Reference of full hash for MD5 */
private static final byte[] MD5_REF_FULL = new byte[] { 64, -127, 66, -23, 71, 121, -19, 64, 73, 56, -47, 51, -110,
60, -75, -47, -84, 12 };
/** Reference of partial hash for MD5 */
private static final byte[] MD5_REF_PART = new byte[] { 64, -108, -110, -108, 102, -84, 69, 102, 10, 82, -29, 66,
-65, 50, -69, 20, 35, -61 };
/** Reference of full hash for Tiger */
private static final byte[] TIGER_REF_FULL = new byte[] { 65, 0, -87, -75, -118, 21, 39, -117, -21, -13, -19, 112,
-104, 23, 54, -78, -84, 63, -16, -96, 122, 18, -30, 7, 14, -96 };
/** Reference of partial hash for Tiger */
private static final byte[] TIGER_REF_PART = new byte[] { 65, -35, -11, -35, 111, -10, 88, 15, 14, 122, 4, -113,
-40, 83, -16, 123, 55, 107, -63, 53, 39, 98, 32, -117, -91, 102 };
/** Reference of full hash for SHA-1 */
private static final byte[] SHA1_REF_FULL = new byte[] { 66, 7, -63, 118, 27, -20, 23, -31, -107, -53, -115, -115,
-74, -70, 74, 53, 106, -10, -28, -106, 70, 118 };
/** Reference of partial hash for SHA-1 */
private static final byte[] SHA1_REF_PART = new byte[] { 66, 55, -61, -62, -118, 57, 93, 84, -18, -87, 55, 64, -79,
23, 67, -127, 95, 90, 118, 111, 84, -46 };
/** Reference of full hash for SHA-256 */
private static final byte[] SHA256_REF_FULL = new byte[] { 67, -48, 25, 72, -106, 97, 117, 105, -1, -39, 66, -87,
8, 9, 81, -6, -26, -93, 4, 8, -10, -73, 118, -5, 119, 115, -32, -2, 1, 23, -59, -95, -116, 47 };
/** Reference of partial hash for SHA-256 */
private static final byte[] SHA256_REF_PART = new byte[] { 67, 41, 126, 72, -7, 107, -38, -42, -44, -112, 23, -85,
13, -14, 74, 9, -94, 11, -83, -14, 11, -107, -61, 18, -90, 53, -108, -8, 90, 48, 44, -118, -84, -96 };
/** Reference of full hash for SHA-512 */
private static final byte[] SHA512_REF_FULL = new byte[] { 68, -116, -64, -49, -12, -66, 106, -43, 53, 100, 90,
121, -33, 16, -107, -61, 67, 35, 77, -8, 45, 44, -10, -41, -66, -40, 106, -117, 101, -43, 12, -46, 82, -41,
-51, 65, -68, -94, 0, 52, 1, -20, 76, -119, 112, -110, -44, -95, -66, 12, -76, -64, 37, -126, 7, -42, -36,
32, 41, 25, 39, 50, -54, 85, -70, 21 };
/** Reference of partial hash for SHA-512 */
private static final byte[] SHA512_REF_PART = new byte[] { 68, -123, -2, -48, 115, -39, -11, 113, -41, 72, 94, -29,
-24, -59, -100, 34, -128, -86, -33, 12, 68, 91, -93, 75, -8, -45, 73, -78, -5, -11, 45, -48, 36, 74, 40,
117, -119, -43, -15, 63, -36, 112, 32, -94, -67, -5, -35, -75, -107, 17, -11, -22, 21, -71, -11, -110, -47,
-57, -65, 11, -6, 28, 56, 12, -112, 76 };
/**
* Prepare buffer.
*/
@Before
public void rewind() {
REF.clear();
}
@Test
public void testMD5() throws NoSuchAlgorithmException, IllegalArgumentException {
// Check digest len
Assert.assertEquals(HashAlgorithm.MD5.getStandardDigestLength(), MD5_REF_FULL.length - 2);
Assert.assertEquals(HashAlgorithm.MD5.getPersistedDigestLength(), MD5_REF_FULL.length);
{ // Full digest
final byte[] md5Full = ByteBufferDigest.digest(HashAlgorithm.MD5, REF);
Assert.assertTrue(Arrays.equals(MD5_REF_FULL, md5Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, md5Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
}
{ // Full digest - ByteString
final byte[] md5Full = ByteBufferDigest.digest(HashAlgorithm.MD5, ByteString.copyFrom(REF));
REF.clear();
Assert.assertTrue(Arrays.equals(MD5_REF_FULL, md5Full));
Assert.assertTrue(ByteBufferDigest.match(ByteString.copyFrom(REF), md5Full));
REF.clear();
}
{// Partial digest
REF.position(3).limit(7);
final byte[] md5Part = ByteBufferDigest.digest(HashAlgorithm.MD5, REF);
Assert.assertTrue(Arrays.equals(MD5_REF_PART, md5Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, md5Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
}
}
@Test
public void testMD5Check() throws NoSuchAlgorithmException {
// Truncate reference
final byte[] truncated = Arrays.copyOf(MD5_REF_FULL, 7);
Assert.assertFalse(HashAlgorithm.MD5.checkHash(truncated));
// Break trailer
final byte[] trailer = Arrays.copyOf(MD5_REF_FULL, MD5_REF_FULL.length);
trailer[trailer.length - 1]++;
Assert.assertFalse(HashAlgorithm.MD5.checkHash(trailer));
// Change algo
final byte[] algo = Arrays.copyOf(MD5_REF_FULL, MD5_REF_FULL.length);
algo[0]++;
Assert.assertFalse(HashAlgorithm.MD5.checkHash(algo));
// Change version
final byte[] version = Arrays.copyOf(MD5_REF_FULL, MD5_REF_FULL.length);
version[0] |= 0xC0;
Assert.assertFalse(HashAlgorithm.MD5.checkHash(version));
}
@Test
public void testTiger() throws NoSuchAlgorithmException, IllegalArgumentException {
// Check digest len
Assert.assertEquals(HashAlgorithm.TIGER.getStandardDigestLength(), TIGER_REF_FULL.length - 2);
Assert.assertEquals(HashAlgorithm.TIGER.getPersistedDigestLength(), TIGER_REF_FULL.length);
{ // Full digest
final byte[] tigerFull = ByteBufferDigest.digest(HashAlgorithm.TIGER, REF);
Assert.assertTrue(Arrays.equals(TIGER_REF_FULL, tigerFull));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, tigerFull));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
}
{ // Full digest - ByteString
final byte[] tigerFull = ByteBufferDigest.digest(HashAlgorithm.TIGER, ByteString.copyFrom(REF));
REF.clear();
Assert.assertTrue(Arrays.equals(TIGER_REF_FULL, tigerFull));
Assert.assertTrue(ByteBufferDigest.match(ByteString.copyFrom(REF), tigerFull));
REF.clear();
}
{// Partial digest
REF.position(3).limit(7);
final byte[] tigerPart = ByteBufferDigest.digest(HashAlgorithm.TIGER, REF);
Assert.assertTrue(Arrays.equals(TIGER_REF_PART, tigerPart));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, tigerPart));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
}
}
@Test
public void testTigerCheck() throws NoSuchAlgorithmException {
// Truncate reference
final byte[] truncated = Arrays.copyOf(TIGER_REF_FULL, 7);
Assert.assertFalse(HashAlgorithm.TIGER.checkHash(truncated));
// Break trailer
final byte[] trailer = Arrays.copyOf(TIGER_REF_FULL, TIGER_REF_FULL.length);
trailer[trailer.length - 1]++;
Assert.assertFalse(HashAlgorithm.TIGER.checkHash(trailer));
// Change algo
final byte[] algo = Arrays.copyOf(TIGER_REF_FULL, TIGER_REF_FULL.length);
algo[0]++;
Assert.assertFalse(HashAlgorithm.TIGER.checkHash(algo));
// Change version
final byte[] version = Arrays.copyOf(TIGER_REF_FULL, TIGER_REF_FULL.length);
version[0] |= 0xC0;
Assert.assertFalse(HashAlgorithm.TIGER.checkHash(version));
}
@Test
public void testSHA1() throws NoSuchAlgorithmException, IllegalArgumentException {
// Check digest len
Assert.assertEquals(HashAlgorithm.SHA1.getStandardDigestLength(), SHA1_REF_FULL.length - 2);
Assert.assertEquals(HashAlgorithm.SHA1.getPersistedDigestLength(), SHA1_REF_FULL.length);
{ // Full digest
final byte[] sha1Full = ByteBufferDigest.digest(HashAlgorithm.SHA1, REF);
Assert.assertTrue(Arrays.equals(SHA1_REF_FULL, sha1Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, sha1Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
}
{ // Full digest - ByteString
final byte[] sha1Full = ByteBufferDigest.digest(HashAlgorithm.SHA1, ByteString.copyFrom(REF));
REF.clear();
Assert.assertTrue(Arrays.equals(SHA1_REF_FULL, sha1Full));
Assert.assertTrue(ByteBufferDigest.match(ByteString.copyFrom(REF), sha1Full));
REF.clear();
}
{// Partial digest
REF.position(3).limit(7);
final byte[] sha1Part = ByteBufferDigest.digest(HashAlgorithm.SHA1, REF);
Assert.assertTrue(Arrays.equals(SHA1_REF_PART, sha1Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, sha1Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
}
}
@Test
public void testSHA1Check() throws NoSuchAlgorithmException {
// Truncate reference
final byte[] truncated = Arrays.copyOf(SHA1_REF_FULL, 7);
Assert.assertFalse(HashAlgorithm.SHA1.checkHash(truncated));
// Break trailer
final byte[] trailer = Arrays.copyOf(SHA1_REF_FULL, SHA1_REF_FULL.length);
trailer[trailer.length - 1]++;
Assert.assertFalse(HashAlgorithm.SHA1.checkHash(trailer));
// Change algo
final byte[] algo = Arrays.copyOf(SHA1_REF_FULL, SHA1_REF_FULL.length);
algo[0]++;
Assert.assertFalse(HashAlgorithm.SHA1.checkHash(algo));
// Change version
final byte[] version = Arrays.copyOf(SHA1_REF_FULL, SHA1_REF_FULL.length);
version[0] |= 0xC0;
Assert.assertFalse(HashAlgorithm.SHA1.checkHash(version));
}
@Test
public void testSHA256() throws NoSuchAlgorithmException, IllegalArgumentException {
// Check digest len
Assert.assertEquals(HashAlgorithm.SHA256.getStandardDigestLength(), SHA256_REF_FULL.length - 2);
Assert.assertEquals(HashAlgorithm.SHA256.getPersistedDigestLength(), SHA256_REF_FULL.length);
{ // Full digest
final byte[] sha256Full = ByteBufferDigest.digest(HashAlgorithm.SHA256, REF);
Assert.assertTrue(Arrays.equals(SHA256_REF_FULL, sha256Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, sha256Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
}
{ // Full digest - ByteString
final byte[] sha256Full = ByteBufferDigest.digest(HashAlgorithm.SHA256, ByteString.copyFrom(REF));
REF.clear();
Assert.assertTrue(Arrays.equals(SHA256_REF_FULL, sha256Full));
Assert.assertTrue(ByteBufferDigest.match(ByteString.copyFrom(REF), sha256Full));
REF.clear();
}
{// Partial digest
REF.position(3).limit(7);
final byte[] sha256Part = ByteBufferDigest.digest(HashAlgorithm.SHA256, REF);
Assert.assertTrue(Arrays.equals(SHA256_REF_PART, sha256Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, sha256Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
}
}
@Test
public void testSHA256Check() throws NoSuchAlgorithmException {
// Truncate reference
final byte[] truncated = Arrays.copyOf(SHA256_REF_FULL, 7);
Assert.assertFalse(HashAlgorithm.SHA256.checkHash(truncated));
// Break trailer
final byte[] trailer = Arrays.copyOf(SHA256_REF_FULL, SHA256_REF_FULL.length);
trailer[trailer.length - 1]++;
Assert.assertFalse(HashAlgorithm.SHA256.checkHash(trailer));
// Change algo
final byte[] algo = Arrays.copyOf(SHA256_REF_FULL, SHA256_REF_FULL.length);
algo[0]++;
Assert.assertFalse(HashAlgorithm.SHA256.checkHash(algo));
// Change version
final byte[] version = Arrays.copyOf(SHA256_REF_FULL, SHA256_REF_FULL.length);
version[0] |= 0xC0;
Assert.assertFalse(HashAlgorithm.SHA256.checkHash(version));
}
@Test
public void testSHA512() throws NoSuchAlgorithmException, IllegalArgumentException {
// Check digest len
Assert.assertEquals(HashAlgorithm.SHA512.getStandardDigestLength(), SHA512_REF_FULL.length - 2);
Assert.assertEquals(HashAlgorithm.SHA512.getPersistedDigestLength(), SHA512_REF_FULL.length);
{ // Full digest
final byte[] sha512Full = ByteBufferDigest.digest(HashAlgorithm.SHA512, REF);
Assert.assertTrue(Arrays.equals(SHA512_REF_FULL, sha512Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, sha512Full));
Assert.assertEquals(0, REF.position());
Assert.assertEquals(REF.capacity(), REF.limit());
}
{ // Full digest - ByteString
final byte[] sha512Full = ByteBufferDigest.digest(HashAlgorithm.SHA512, ByteString.copyFrom(REF));
REF.clear();
Assert.assertTrue(Arrays.equals(SHA512_REF_FULL, sha512Full));
Assert.assertTrue(ByteBufferDigest.match(ByteString.copyFrom(REF), sha512Full));
REF.clear();
}
{// Partial digest
REF.position(3).limit(7);
final byte[] sha512Part = ByteBufferDigest.digest(HashAlgorithm.SHA512, REF);
Assert.assertTrue(Arrays.equals(SHA512_REF_PART, sha512Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
Assert.assertTrue(ByteBufferDigest.match(REF, sha512Part));
Assert.assertEquals(3, REF.position());
Assert.assertEquals(7, REF.limit());
}
}
@Test
public void testSHA512Check() throws NoSuchAlgorithmException {
// Truncate reference
final byte[] truncated = Arrays.copyOf(SHA512_REF_FULL, 7);
Assert.assertFalse(HashAlgorithm.SHA512.checkHash(truncated));
// Break trailer
final byte[] trailer = Arrays.copyOf(SHA512_REF_FULL, SHA512_REF_FULL.length);
trailer[trailer.length - 1]++;
Assert.assertFalse(HashAlgorithm.SHA512.checkHash(trailer));
// Change algo
final byte[] algo = Arrays.copyOf(SHA512_REF_FULL, SHA512_REF_FULL.length);
algo[0]++;
Assert.assertFalse(HashAlgorithm.SHA512.checkHash(algo));
// Change version
final byte[] version = Arrays.copyOf(SHA512_REF_FULL, SHA512_REF_FULL.length);
version[0] |= 0xC0;
Assert.assertFalse(HashAlgorithm.SHA512.checkHash(version));
}
@Test(expected = IllegalArgumentException.class)
public void testByteBufferCheckTruncate() throws NoSuchAlgorithmException {
// Truncate reference
final byte[] truncated = Arrays.copyOf(MD5_REF_FULL, 7);
ByteBufferDigest.match(REF, truncated);
}
@Test(expected = IllegalArgumentException.class)
public void testByteBufferCheckBreadkTrailer() throws NoSuchAlgorithmException {
// Break trailer
final byte[] trailer = Arrays.copyOf(MD5_REF_FULL, MD5_REF_FULL.length);
trailer[trailer.length - 1]++;
ByteBufferDigest.match(REF, trailer);
}
@Test(expected = IllegalArgumentException.class)
public void testByteBufferCheckChangeAlgo() throws NoSuchAlgorithmException {
// Change algo
final byte[] algo = Arrays.copyOf(MD5_REF_FULL, MD5_REF_FULL.length);
algo[0]++;
ByteBufferDigest.match(REF, algo);
}
@Test(expected = NoSuchAlgorithmException.class)
public void testByteBufferCheckChangeVersion() throws NoSuchAlgorithmException {
// Change version
final byte[] version = Arrays.copyOf(MD5_REF_FULL, MD5_REF_FULL.length);
version[0] |= 0xC0;
ByteBufferDigest.match(REF, version);
}
@Test
public void testMD5Hash() throws NoSuchAlgorithmException {
Assert.assertEquals(HashAlgorithm.MD5, HashAlgorithm.getHashHashAlgorithm(new byte[] { 0x40 }));
}
@Test
public void testTigerHash() throws NoSuchAlgorithmException {
Assert.assertEquals(HashAlgorithm.TIGER, HashAlgorithm.getHashHashAlgorithm(new byte[] { 0x41 }));
}
@Test
public void testSHA1Hash() throws NoSuchAlgorithmException {
Assert.assertEquals(HashAlgorithm.SHA1, HashAlgorithm.getHashHashAlgorithm(new byte[] { 0x42 }));
}
@Test
public void testSHA256Hash() throws NoSuchAlgorithmException {
Assert.assertEquals(HashAlgorithm.SHA256, HashAlgorithm.getHashHashAlgorithm(new byte[] { 0x43 }));
}
@Test
public void testSHA512Hash() throws NoSuchAlgorithmException {
Assert.assertEquals(HashAlgorithm.SHA512, HashAlgorithm.getHashHashAlgorithm(new byte[] { 0x44 }));
}
@Test(expected = NoSuchAlgorithmException.class)
public void testHashErrAlgo() throws NoSuchAlgorithmException {
HashAlgorithm.getHashHashAlgorithm(new byte[] { (byte) 0x45 });
}
@Test(expected = NoSuchAlgorithmException.class)
public void testHashErrVersion() throws NoSuchAlgorithmException {
HashAlgorithm.getHashHashAlgorithm(new byte[] { (byte) 0xC1 });
}
}