Skip to content

Commit

Permalink
Merge 5b19b1b into 3ab9ce4
Browse files Browse the repository at this point in the history
  • Loading branch information
behrangsa committed Dec 3, 2019
2 parents 3ab9ce4 + 5b19b1b commit 108ab04
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 54 deletions.
39 changes: 39 additions & 0 deletions src/main/java/org/apache/commons/codec/digest/DigestUtils.java
Expand Up @@ -20,9 +20,11 @@
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

Expand Down Expand Up @@ -99,6 +101,20 @@ public static byte[] digest(final MessageDigest messageDigest, final File data)
return updateDigest(messageDigest, data).digest();
}

/**
* Reads through a RandomAccessFile using non-blocking-io (NIO) and returns the digest for the data
*
* @param messageDigest The MessageDigest to use (e.g. MD5)
* @param data Data to digest
* @return the digest
* @throws IOException On error reading from the stream
* @since 1.14
*/
public static byte[] digest(final MessageDigest messageDigest, final RandomAccessFile data) throws IOException {
data.seek(0);
return updateDigest(messageDigest, data).digest();
}

/**
* Reads through an InputStream and returns the digest for the data
*
Expand Down Expand Up @@ -1207,6 +1223,29 @@ public static MessageDigest updateDigest(final MessageDigest digest, final File
}
}

/**
* Reads through a RandomAccessFile and updates the digest for the data
* using non-blocking-io (NIO)
*
* @param digest The MessageDigest to use (e.g. MD5)
* @param data Data to digest
* @return the digest
* @throws IOException On error reading from the stream
* @since 1.14
*/
public static MessageDigest updateDigest(final MessageDigest digest, final RandomAccessFile data) throws IOException {
final FileChannel channel = data.getChannel();
final ByteBuffer buffer = ByteBuffer.allocate(STREAM_BUFFER_LENGTH);

while (channel.read(buffer) > 0) {
buffer.flip();
digest.update(buffer);
buffer.clear();
}

return digest;
}

/**
* Reads through an InputStream and updates the digest for the data
*
Expand Down
126 changes: 72 additions & 54 deletions src/test/java/org/apache/commons/codec/digest/DigestUtilsTest.java
Expand Up @@ -24,6 +24,7 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Random;
Expand All @@ -39,14 +40,17 @@

/**
* Tests DigestUtils methods.
*
*/
public class DigestUtilsTest {

private final byte[] testData = new byte[1024 * 1024];

private File testFile;

private File testRandomAccessFile;

private RandomAccessFile testRandomAccessFileWrapper;

private void assumeJava8() {
Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
}
Expand All @@ -63,23 +67,37 @@ File getTestFile() {
return testFile;
}

RandomAccessFile getTestRandomAccessFile() {
return testRandomAccessFileWrapper;
}

@Before
public void setUp() throws Exception {
new Random().nextBytes(testData);
testFile = File.createTempFile(DigestUtilsTest.class.getName(), ".dat");
try (final FileOutputStream fos = new FileOutputStream(testFile)) {
fos.write(testData);
}

testRandomAccessFile = File.createTempFile(DigestUtilsTest.class.getName(), ".dat");
try (final FileOutputStream fos = new FileOutputStream(testRandomAccessFile)) {
fos.write(testData);
}
testRandomAccessFileWrapper = new RandomAccessFile(testRandomAccessFile, "rw");
}

@After
public void tearDown() {
if (!testFile.delete()) {
testFile.deleteOnExit();
}

if (!testRandomAccessFile.delete()) {
testRandomAccessFile.deleteOnExit();
}
}

@Test(expected=IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testInternalNoSuchAlgorithmException() {
DigestUtils.getDigest("Bogus Bogus");
}
Expand All @@ -98,16 +116,16 @@ public void testMd2Hex() throws IOException {
assertEquals("4e8ddff3650292ab5a4108c3aa47940b", DigestUtils.md2Hex("abcdefghijklmnopqrstuvwxyz"));

assertEquals(
"da33def2a42df13975352846c30338cd",
DigestUtils.md2Hex("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789"));
"da33def2a42df13975352846c30338cd",
DigestUtils.md2Hex("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789"));

assertEquals(
"d5976f79d83d3a0dc9806c3c66f3efd8",
DigestUtils.md2Hex("1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890"));
"d5976f79d83d3a0dc9806c3c66f3efd8",
DigestUtils.md2Hex("1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890"));

assertEquals(DigestUtils.md2Hex(testData),
DigestUtils.md2Hex(new ByteArrayInputStream(testData)));
}
}

/**
* An MD2 hash converted to hex should always be 32 characters.
Expand Down Expand Up @@ -151,16 +169,16 @@ public void testMd5Hex() throws IOException {
assertEquals("c3fcd3d76192e4007dfb496cca67e13b", DigestUtils.md5Hex("abcdefghijklmnopqrstuvwxyz"));

assertEquals(
"d174ab98d277d9f5a5611c2c9f419d9f",
DigestUtils.md5Hex("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789"));
"d174ab98d277d9f5a5611c2c9f419d9f",
DigestUtils.md5Hex("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789"));

assertEquals(
"57edf4a22be3c955ac49da2e2107b67a",
DigestUtils.md5Hex("1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890"));
"57edf4a22be3c955ac49da2e2107b67a",
DigestUtils.md5Hex("1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890"));

assertEquals(DigestUtils.md5Hex(testData),
DigestUtils.md5Hex(new ByteArrayInputStream(testData)));
}
}

/**
* An MD5 hash converted to hex should always be 32 characters.
Expand Down Expand Up @@ -198,14 +216,14 @@ public void testSha1Hex() throws IOException {
assertEquals("a9993e364706816aba3e25717850c26c9cd0d89d", DigestUtils.sha1Hex(getBytesUtf8("abc")));

assertEquals(
"84983e441c3bd26ebaae4aa1f95129e5e54670f1",
DigestUtils.sha1Hex("abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq"));
"84983e441c3bd26ebaae4aa1f95129e5e54670f1",
DigestUtils.sha1Hex("abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq"));
assertEquals(DigestUtils.sha1Hex(testData),
DigestUtils.sha1Hex(new ByteArrayInputStream(testData)));
}

@Test
public void testSha1UpdateWithByteArray(){
public void testSha1UpdateWithByteArray() {
final String d1 = "C'est un homme qui rentre dans un café, et plouf";
final String d2 = "C'est un homme, c'est qu'une tête, on lui offre un cadeau: 'oh... encore un chapeau!'";

Expand All @@ -223,7 +241,7 @@ public void testSha1UpdateWithByteArray(){
}

@Test
public void testSha1UpdateWithByteBuffer(){
public void testSha1UpdateWithByteBuffer() {
final String d1 = "C'est un homme qui rentre dans un café, et plouf";
final String d2 = "C'est un homme, c'est qu'une tête, on lui offre un cadeau: 'oh... encore un chapeau!'";

Expand All @@ -241,7 +259,7 @@ public void testSha1UpdateWithByteBuffer(){
}

@Test
public void testSha1UpdateWithString(){
public void testSha1UpdateWithString() {
final String d1 = "C'est un homme qui rentre dans un café, et plouf";
final String d2 = "C'est un homme, c'est qu'une tête, on lui offre un cadeau: 'oh... encore un chapeau!'";

Expand Down Expand Up @@ -271,48 +289,48 @@ public void testSha224() {

@Test
public void testSha256() throws IOException {
// Examples from FIPS 180-2
assertEquals("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
DigestUtils.sha256Hex("abc"));
assertEquals("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
DigestUtils.sha256Hex(getBytesUtf8("abc")));
assertEquals("248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
DigestUtils.sha256Hex("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"));
// Examples from FIPS 180-2
assertEquals("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
DigestUtils.sha256Hex("abc"));
assertEquals("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
DigestUtils.sha256Hex(getBytesUtf8("abc")));
assertEquals("248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
DigestUtils.sha256Hex("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"));

assertEquals(DigestUtils.sha256Hex(testData),
DigestUtils.sha256Hex(new ByteArrayInputStream(testData)));
assertEquals(DigestUtils.sha256Hex(testData),
DigestUtils.sha256Hex(new ByteArrayInputStream(testData)));
}

@Test
public void testSha384() throws IOException {
// Examples from FIPS 180-2
assertEquals("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" +
"8086072ba1e7cc2358baeca134c825a7",
DigestUtils.sha384Hex("abc"));
assertEquals("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" +
"8086072ba1e7cc2358baeca134c825a7",
DigestUtils.sha384Hex(getBytesUtf8("abc")));
assertEquals("09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712" +
"fcc7c71a557e2db966c3e9fa91746039",
DigestUtils.sha384Hex("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"));
assertEquals(DigestUtils.sha384Hex(testData),
DigestUtils.sha384Hex(new ByteArrayInputStream(testData)));
// Examples from FIPS 180-2
assertEquals("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" +
"8086072ba1e7cc2358baeca134c825a7",
DigestUtils.sha384Hex("abc"));
assertEquals("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" +
"8086072ba1e7cc2358baeca134c825a7",
DigestUtils.sha384Hex(getBytesUtf8("abc")));
assertEquals("09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712" +
"fcc7c71a557e2db966c3e9fa91746039",
DigestUtils.sha384Hex("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"));
assertEquals(DigestUtils.sha384Hex(testData),
DigestUtils.sha384Hex(new ByteArrayInputStream(testData)));
}

@Test
public void testSha512() {
// Examples from FIPS 180-2
assertEquals("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
DigestUtils.sha512Hex("abc"));
assertEquals("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
DigestUtils.sha512Hex(getBytesUtf8("abc")));
assertEquals("8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
DigestUtils.sha512Hex("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"));
// Examples from FIPS 180-2
assertEquals("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
DigestUtils.sha512Hex("abc"));
assertEquals("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
DigestUtils.sha512Hex(getBytesUtf8("abc")));
assertEquals("8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
DigestUtils.sha512Hex("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"));
}

@Test
Expand Down Expand Up @@ -414,15 +432,15 @@ public void testShaHex() throws IOException {
assertEquals("a9993e364706816aba3e25717850c26c9cd0d89d", DigestUtils.shaHex(getBytesUtf8("abc")));

assertEquals(
"84983e441c3bd26ebaae4aa1f95129e5e54670f1",
DigestUtils.shaHex("abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq"));
"84983e441c3bd26ebaae4aa1f95129e5e54670f1",
DigestUtils.shaHex("abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq"));
assertEquals(DigestUtils.shaHex(testData),
DigestUtils.shaHex(new ByteArrayInputStream(testData)));
}

@SuppressWarnings("deprecation") // deliberate tests of deprecated code
@Test
public void testShaUpdateWithByteArray(){
public void testShaUpdateWithByteArray() {
final String d1 = "C'est un homme qui rentre dans un café, et plouf";
final String d2 = "C'est un homme, c'est qu'une tête, on lui offre un cadeau: 'oh... encore un chapeau!'";

Expand All @@ -441,7 +459,7 @@ public void testShaUpdateWithByteArray(){

@SuppressWarnings("deprecation") // deliberate tests of deprecated code
@Test
public void testShaUpdateWithString(){
public void testShaUpdateWithString() {
final String d1 = "C'est un homme qui rentre dans un café, et plouf";
final String d2 = "C'est un homme, c'est qu'une tête, on lui offre un cadeau: 'oh... encore un chapeau!'";

Expand Down
Expand Up @@ -19,6 +19,7 @@
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
Expand Down Expand Up @@ -106,6 +107,10 @@ private File getTestFile() {
return digestUtilsTest.getTestFile();
}

private RandomAccessFile getTestRandomAccessFile() {
return digestUtilsTest.getTestRandomAccessFile();
}

@Before
public void setUp() throws Exception {
digestUtilsTest = new DigestUtilsTest();
Expand Down Expand Up @@ -151,6 +156,25 @@ public void testDigestFile() throws IOException {
Assert.assertArrayEquals(digestTestData(), DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestFile()));
}

@Test
public void testNonBlockingDigestRandomAccessFile() throws IOException {
Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));

final byte[] expected = digestTestData();

Assert.assertArrayEquals(expected,
DigestUtils.digest(
DigestUtils.getDigest(messageDigestAlgorithm), getTestRandomAccessFile()
)
);

Assert.assertArrayEquals(expected,
DigestUtils.digest(
DigestUtils.getDigest(messageDigestAlgorithm), getTestRandomAccessFile()
)
);
}

@Test
public void testDigestInputStream() throws IOException {
Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
Expand Down

0 comments on commit 108ab04

Please sign in to comment.