/* * @(#)SHA1Test.java 1.9 2004-04-22 * This file was freely contributed to the LimeWire project and is covered * by its existing GPL licence, but it may be used individually as a public * domain implementation of a published algorithm (see below for references). * It was also freely contributed to the Bitzi public domain sources. * @author Philippe Verdy */ /* * Sun may wish to change the following package name, if integrating this * class in the Sun JCE Security Provider for Java 1.5 (code-named Tiger). */ package com.limegroup.gnutella.security; import java.io.File; import java.io.FileInputStream; import java.security.MessageDigest; import junit.framework.Test; import com.limegroup.gnutella.util.BaseTestCase; import com.limegroup.gnutella.util.CommonUtils; public class SHA1Test extends BaseTestCase { private static final SHA1 hash = new SHA1(); public SHA1Test(String name) { super(name); } public static Test suite() { return buildTestSuite(SHA1Test.class); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public void testBasic() throws Exception { // http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf tst(1, 1, "abc", "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D"); tst(1, 2, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84983E44 1C3BD26e BAAE4AA1 F95129E5 E54670F1"); tst(1, 3, 1000000, "a", "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"); // See also http://csrc.ncsl.nist.gov/cryptval/shs/sha1-vectors.zip } public void testRate() throws Exception { final int ITERATIONS = 16000; final int BLOCKSIZE = 65536; byte[] input = new byte[BLOCKSIZE]; for (int i = BLOCKSIZE; --i >= 0; ) input[i] = (byte)i; long t0 = System.currentTimeMillis(); for (int i = ITERATIONS; --i >= 0; ); long t1 = System.currentTimeMillis(); for (int i = ITERATIONS; --i >= 0; ) hash.engineUpdate(input, 0, BLOCKSIZE); long t2 = System.currentTimeMillis(); hash.engineReset(); double rate = 1000.0 * ITERATIONS * BLOCKSIZE / ((t2 - t1) - (t1 - t0)); double limeRate = rate; //System.out.println("Our rate = " + // (float)(rate * 8) + " bits/s = " + // (float)(rate / (1024 * 1024)) + " Megabytes/s"); // Java 1.5 beta-b32c, on Athlon XP 1800+: 47.62 Megabytes/s. MessageDigest md = MessageDigest.getInstance("SHA"); t0 = System.currentTimeMillis(); for (int i = ITERATIONS; --i >= 0; ); t1 = System.currentTimeMillis(); for (int i = ITERATIONS; --i >= 0; ) md.update(input, 0, BLOCKSIZE); t2 = System.currentTimeMillis(); md.reset(); rate = 1000.0 * ITERATIONS * BLOCKSIZE / ((t2 - t1) - (t1 - t0)); //System.out.println("JCE rate = " + // (float)(rate * 8) + " bits/s = " + // (float)(rate / (1024 * 1024)) + " Megabytes/s"); // Java 1.5 beta-b32c, on Athlon XP 1800+: 22.78 Megabytes/s. assertGreaterThan(rate, limeRate); } public void testFiles() throws Exception { String dirString = "com/limegroup/gnutella"; File testDir = CommonUtils.getResourceFile(dirString); assertTrue(testDir.isDirectory()); int tested = testDirectory(testDir); assertGreaterThan("didn't test enough", 10, tested); } public int testDirectory(File dir) throws Exception { int tested = 0; File[] files = dir.listFiles(); for(int i = 0; i < files.length; i++) { File f = files[i]; if(f.isDirectory()) tested += testDirectory(f); else if(f.isFile() && f.exists()) { byte[] old = createSHA1(f, true); byte[] now = createSHA1(f, false); assertEquals(old, now); tested++; } } return tested; } private static byte[] createSHA1(final File file, boolean digest) throws Exception { FileInputStream fis = new FileInputStream(file); // we can only calculate SHA1 for now MessageDigest md = null; if(digest) md = MessageDigest.getInstance("SHA"); else md = new SHA1(); try { byte[] buffer = new byte[16384]; int read; while ((read=fis.read(buffer))!=-1) md.update(buffer,0,read); } finally { fis.close(); } return md.digest(); } private static final void tst(final int set, final int vector, final String source, final String expect) { // System.out.print("Set " + set + ", vector# " + vector + ": "); byte[] input = new byte[source.length()]; for (int i = 0; i < input.length; i++) input[i] = (byte)source.charAt(i); hash.engineUpdate(input, 0, input.length); tstResult(expect); } private static final void tst(final int set, final int vector, final int times, final String source, final String expect) { // System.out.print("Set " + set + ", vector# " + vector + ": "); byte[] input = new byte[source.length()]; for (int i = 0; i < input.length; i++) input[i] = (byte)source.charAt(i); for (int i = 0; i < times; i++) hash.engineUpdate(input, 0, input.length); tstResult(expect); } private static final void tstResult(final String expect) { final String result = toHex(hash.engineDigest()); assertEquals(expect.toUpperCase(), result); } private static final String toHex(final byte[] bytes) { StringBuffer buf = new StringBuffer(bytes.length * 2); for (int i = 0; i < bytes.length; i++) { if ((i & 3) == 0 && i != 0) buf.append(' '); buf.append(HEX.charAt((bytes[i] >> 4) & 0xF)) .append(HEX.charAt( bytes[i] & 0xF)); } return buf.toString(); } private static final String HEX = "0123456789ABCDEF"; }