forked from I2P_Developers/i2p.i2p
* Crypto:
- Use java.security.MessageDigest instead of bundled GNU SHA-256 code if available, which it should always be. 5 to 20% faster on Oracle JVM; 40 to 60% on Harmony; 5 to 15% on JamVM; 20x (!) on GIJ. - Use java.security.MessageDigest instead of bundled Bitzi SHA-1 code if available on non-Oracle JVMs, which it should always be. Not faster on Oracle JVM; 30 to 60% faster on Harmony; 15 to 20% on JamVM; 10-15x (!) on GIJ.
This commit is contained in:
@ -24,7 +24,6 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -401,7 +400,7 @@ public class MetaInfo
|
||||
****/
|
||||
|
||||
private boolean fast_checkPiece(int piece, byte[] bs, int off, int length) {
|
||||
SHA1 sha1 = new SHA1();
|
||||
MessageDigest sha1 = SHA1.getInstance();
|
||||
|
||||
sha1.update(bs, off, length);
|
||||
byte[] hash = sha1.digest();
|
||||
@ -519,18 +518,11 @@ public class MetaInfo
|
||||
}
|
||||
byte[] infoBytes = BEncoder.bencode(info);
|
||||
//_log.debug("info bencoded: [" + Base64.encode(infoBytes, true) + "]");
|
||||
try
|
||||
{
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA");
|
||||
MessageDigest digest = SHA1.getInstance();
|
||||
byte hash[] = digest.digest(infoBytes);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("info hash: " + I2PSnarkUtil.toHex(hash));
|
||||
return hash;
|
||||
}
|
||||
catch(NoSuchAlgorithmException nsa)
|
||||
{
|
||||
throw new InternalError(nsa.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 0.8.5 */
|
||||
|
@ -23,6 +23,7 @@ package org.klomp.snark;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -165,7 +166,7 @@ public class Storage
|
||||
*/
|
||||
private byte[] fast_digestCreate() throws IOException {
|
||||
// Calculate piece_hashes
|
||||
SHA1 digest = new SHA1();
|
||||
MessageDigest digest = SHA1.getInstance();
|
||||
|
||||
byte[] piece_hashes = new byte[20 * pieces];
|
||||
|
||||
|
@ -32,6 +32,7 @@ package net.i2p.crypto;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Hash;
|
||||
@ -228,25 +229,25 @@ public class DSAEngine {
|
||||
|
||||
/** @return hash SHA-1 hash, NOT a SHA-256 hash */
|
||||
public SHA1Hash calculateHash(InputStream in) {
|
||||
SHA1 digest = new SHA1();
|
||||
MessageDigest digest = SHA1.getInstance();
|
||||
byte buf[] = new byte[64];
|
||||
int read = 0;
|
||||
try {
|
||||
while ( (read = in.read(buf)) != -1) {
|
||||
digest.engineUpdate(buf, 0, read);
|
||||
digest.update(buf, 0, read);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Unable to hash the stream", ioe);
|
||||
return null;
|
||||
}
|
||||
return new SHA1Hash(digest.engineDigest());
|
||||
return new SHA1Hash(digest.digest());
|
||||
}
|
||||
|
||||
/** @return hash SHA-1 hash, NOT a SHA-256 hash */
|
||||
public static SHA1Hash calculateHash(byte[] source, int offset, int len) {
|
||||
SHA1 h = new SHA1();
|
||||
h.engineUpdate(source, offset, len);
|
||||
MessageDigest h = SHA1.getInstance();
|
||||
h.update(source, offset, len);
|
||||
byte digested[] = h.digest();
|
||||
return new SHA1Hash(digested);
|
||||
}
|
||||
|
@ -15,10 +15,17 @@ package net.i2p.crypto;
|
||||
* put("MessageDigest.SHA-1", "com.bitzi.util.SHA1");
|
||||
*/
|
||||
//package com.bitzi.util;
|
||||
|
||||
import java.security.DigestException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import net.i2p.data.Base64;
|
||||
|
||||
/**
|
||||
* NOTE: As of 0.8.7, use getInstance() instead of new SHA1(), which will
|
||||
* return the JVM's MessageDigest if it is faster.
|
||||
*
|
||||
* <p>The FIPS PUB 180-2 standard specifies four secure hash algorithms (SHA-1,
|
||||
* SHA-256, SHA-384 and SHA-512) for computing a condensed representation of
|
||||
* electronic data (message). When a message of any length < 2^^64 bits (for
|
||||
@ -85,8 +92,27 @@ public final class SHA1 extends MessageDigest implements Cloneable {
|
||||
*/
|
||||
private int hA, hB, hC, hD, hE;
|
||||
|
||||
private static final boolean _useBitzi;
|
||||
static {
|
||||
// oddly, Bitzi is faster than Oracle - see test results below
|
||||
boolean useBitzi = true;
|
||||
String vendor = System.getProperty("java.vendor");
|
||||
if (vendor.startsWith("Apache") || // Harmony
|
||||
vendor.startsWith("GNU Classpath") || // JamVM
|
||||
vendor.startsWith("Free Software Foundation")) { // gij
|
||||
try {
|
||||
MessageDigest.getInstance("SHA-1");
|
||||
useBitzi = false;
|
||||
} catch (NoSuchAlgorithmException e) {}
|
||||
}
|
||||
//if (useBitzi)
|
||||
// System.out.println("INFO: Using Bitzi SHA-1");
|
||||
_useBitzi = useBitzi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SHA1 object with default initial state.
|
||||
* NOTE: Use getInstance() to get the fastest implementation.
|
||||
*/
|
||||
public SHA1() {
|
||||
super("SHA-1");
|
||||
@ -94,6 +120,19 @@ public final class SHA1 extends MessageDigest implements Cloneable {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fastest digest, either new SHA1() or MessageDigest.getInstance("SHA-1")
|
||||
* @since 0.8.7
|
||||
*/
|
||||
public static MessageDigest getInstance() {
|
||||
if (!_useBitzi) {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException e) {}
|
||||
}
|
||||
return new SHA1();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this object.
|
||||
*/
|
||||
@ -699,4 +738,63 @@ public final class SHA1 extends MessageDigest implements Cloneable {
|
||||
hD += d;
|
||||
hC += /* c= */ (c << 30) | (c >>> 2);
|
||||
}
|
||||
|
||||
private static final int RUNS = 100000;
|
||||
|
||||
/**
|
||||
* Test the GNU and the JVM's implementations for speed
|
||||
*
|
||||
* Results: 2011-05 eeepc Atom
|
||||
* <pre>
|
||||
* JVM strlen GNU ms JVM ms
|
||||
* Oracle 387 1406 2357
|
||||
* Oracle 40 522 475
|
||||
* Harmony 387 5504 3474
|
||||
* Harmony 40 4396 1593
|
||||
* JamVM 387 25578 21966
|
||||
* JamVM 40 5380 4195
|
||||
* gij 387 47225 3501
|
||||
* gij 40 9861 919
|
||||
* </pre>
|
||||
*
|
||||
* @since 0.8.7
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (args.length <= 0) {
|
||||
System.err.println("Usage: SHA1 string");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] data = args[0].getBytes();
|
||||
SHA1 gnu = new SHA1();
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < RUNS; i++) {
|
||||
gnu.update(data, 0, data.length);
|
||||
byte[] sha = gnu.digest();
|
||||
if (i == 0)
|
||||
System.out.println("SHA1 [" + args[0] + "] = [" + Base64.encode(sha) + "]");
|
||||
gnu.reset();
|
||||
}
|
||||
long time = System.currentTimeMillis() - start;
|
||||
System.out.println("Time for " + RUNS + " SHA-256 computations:");
|
||||
System.out.println("GNU time (ms): " + time);
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
MessageDigest md;
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
System.err.println("Fatal: " + e);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < RUNS; i++) {
|
||||
md.reset();
|
||||
byte[] sha = md.digest(data);
|
||||
if (i == 0)
|
||||
System.out.println("SHA1 [" + args[0] + "] = [" + Base64.encode(sha) + "]");
|
||||
}
|
||||
time = System.currentTimeMillis() - start;
|
||||
|
||||
System.out.println("JVM time (ms): " + time);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package net.i2p.crypto;
|
||||
|
||||
import gnu.crypto.hash.Sha256Standalone;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
@ -9,14 +11,29 @@ import net.i2p.data.Base64;
|
||||
import net.i2p.data.Hash;
|
||||
|
||||
/**
|
||||
* Defines a wrapper for SHA-256 operation. All the good stuff occurs
|
||||
* in the GNU-Crypto {@link gnu.crypto.hash.Sha256Standalone}
|
||||
* Defines a wrapper for SHA-256 operation.
|
||||
*
|
||||
* As of release 0.8.7, uses java.security.MessageDigest by default.
|
||||
* If that is unavailable, it uses
|
||||
* GNU-Crypto {@link gnu.crypto.hash.Sha256Standalone}
|
||||
*/
|
||||
public final class SHA256Generator {
|
||||
private final LinkedBlockingQueue<Sha256Standalone> _digestsGnu;
|
||||
private final LinkedBlockingQueue<MessageDigest> _digests;
|
||||
|
||||
private static final boolean _useGnu;
|
||||
static {
|
||||
boolean useGnu = false;
|
||||
try {
|
||||
MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
useGnu = true;
|
||||
System.out.println("INFO: Using GNU SHA-256");
|
||||
}
|
||||
_useGnu = useGnu;
|
||||
}
|
||||
|
||||
public SHA256Generator(I2PAppContext context) {
|
||||
_digestsGnu = new LinkedBlockingQueue(32);
|
||||
_digests = new LinkedBlockingQueue(32);
|
||||
}
|
||||
|
||||
public static final SHA256Generator getInstance() {
|
||||
@ -36,10 +53,10 @@ public final class SHA256Generator {
|
||||
* Calculate the hash and cache the result.
|
||||
*/
|
||||
public final Hash calculateHash(byte[] source, int start, int len) {
|
||||
Sha256Standalone digest = acquireGnu();
|
||||
MessageDigest digest = acquire();
|
||||
digest.update(source, start, len);
|
||||
byte rv[] = digest.digest();
|
||||
releaseGnu(digest);
|
||||
release(digest);
|
||||
//return new Hash(rv);
|
||||
return Hash.create(rv);
|
||||
}
|
||||
@ -47,31 +64,121 @@ public final class SHA256Generator {
|
||||
/**
|
||||
* Use this if you only need the data, not a Hash object.
|
||||
* Does not cache.
|
||||
* @param out needs 32 bytes starting at outOffset
|
||||
*/
|
||||
public final void calculateHash(byte[] source, int start, int len, byte out[], int outOffset) {
|
||||
Sha256Standalone digest = acquireGnu();
|
||||
MessageDigest digest = acquire();
|
||||
digest.update(source, start, len);
|
||||
byte rv[] = digest.digest();
|
||||
releaseGnu(digest);
|
||||
release(digest);
|
||||
System.arraycopy(rv, 0, out, outOffset, rv.length);
|
||||
}
|
||||
|
||||
private Sha256Standalone acquireGnu() {
|
||||
Sha256Standalone rv = _digestsGnu.poll();
|
||||
private MessageDigest acquire() {
|
||||
MessageDigest rv = _digests.poll();
|
||||
if (rv != null)
|
||||
rv.reset();
|
||||
else
|
||||
rv = new Sha256Standalone();
|
||||
rv = getDigestInstance();
|
||||
return rv;
|
||||
}
|
||||
|
||||
private void releaseGnu(Sha256Standalone digest) {
|
||||
_digestsGnu.offer(digest);
|
||||
private void release(MessageDigest digest) {
|
||||
_digests.offer(digest);
|
||||
}
|
||||
|
||||
private static MessageDigest getDigestInstance() {
|
||||
if (!_useGnu) {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {}
|
||||
}
|
||||
return new GnuMessageDigest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to make Sha256Standalone a MessageDigest
|
||||
* @since 0.8.7
|
||||
*/
|
||||
private static class GnuMessageDigest extends MessageDigest {
|
||||
private final Sha256Standalone _gnu;
|
||||
|
||||
protected GnuMessageDigest() {
|
||||
super("SHA-256");
|
||||
_gnu = new Sha256Standalone();
|
||||
}
|
||||
|
||||
protected byte[] engineDigest() {
|
||||
return _gnu.digest();
|
||||
}
|
||||
|
||||
protected void engineReset() {
|
||||
_gnu.reset();
|
||||
}
|
||||
|
||||
protected void engineUpdate(byte input) {
|
||||
_gnu.update(input);
|
||||
}
|
||||
|
||||
protected void engineUpdate(byte[] input, int offset, int len) {
|
||||
_gnu.update(input, offset, len);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int RUNS = 100000;
|
||||
|
||||
/**
|
||||
* Test the GNU and the JVM's implementations for speed
|
||||
*
|
||||
* Results: 2011-05 eeepc Atom
|
||||
* <pre>
|
||||
* JVM strlen GNU ms JVM ms
|
||||
* Oracle 387 3861 3565
|
||||
* Oracle 40 825 635
|
||||
* Harmony 387 8082 5158
|
||||
* Harmony 40 4137 1753
|
||||
* JamVM 387 36301 34100
|
||||
* JamVM 40 7022 6016
|
||||
* gij 387 125833 4342
|
||||
* gij 40 22417 988
|
||||
* </pre>
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
for (int i = 0; i < args.length; i++)
|
||||
System.out.println("SHA256 [" + args[i] + "] = [" + Base64.encode(ctx.sha().calculateHash(args[i].getBytes()).getData()) + "]");
|
||||
if (args.length <= 0) {
|
||||
System.err.println("Usage: SHA256Generator string");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] data = args[0].getBytes();
|
||||
Sha256Standalone gnu = new Sha256Standalone();
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < RUNS; i++) {
|
||||
gnu.update(data, 0, data.length);
|
||||
byte[] sha = gnu.digest();
|
||||
if (i == 0)
|
||||
System.out.println("SHA256 [" + args[0] + "] = [" + Base64.encode(sha) + "]");
|
||||
gnu.reset();
|
||||
}
|
||||
long time = System.currentTimeMillis() - start;
|
||||
System.out.println("Time for " + RUNS + " SHA-256 computations:");
|
||||
System.out.println("GNU time (ms): " + time);
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
MessageDigest md;
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
System.err.println("Fatal: " + e);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < RUNS; i++) {
|
||||
md.reset();
|
||||
byte[] sha = md.digest(data);
|
||||
if (i == 0)
|
||||
System.out.println("SHA256 [" + args[0] + "] = [" + Base64.encode(sha) + "]");
|
||||
}
|
||||
time = System.currentTimeMillis() - start;
|
||||
|
||||
System.out.println("JVM time (ms): " + time);
|
||||
}
|
||||
}
|
||||
|
11
history.txt
11
history.txt
@ -1,3 +1,14 @@
|
||||
2011-06-01 zzz
|
||||
* Crypto:
|
||||
- Use java.security.MessageDigest instead of bundled GNU SHA-256 code
|
||||
if available, which it should always be.
|
||||
5 to 20% faster on Oracle JVM; 40 to 60% on Harmony;
|
||||
5 to 15% on JamVM; 20x (!) on GIJ.
|
||||
- Use java.security.MessageDigest instead of bundled Bitzi SHA-1 code
|
||||
if available on non-Oracle JVMs, which it should always be.
|
||||
Not faster on Oracle JVM; 30 to 60% faster on Harmony;
|
||||
15 to 20% on JamVM; 10-15x (!) on GIJ.
|
||||
|
||||
2011-06-01 sponge
|
||||
* ConfigClients stopClient stubbed out.
|
||||
|
||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 14;
|
||||
public final static long BUILD = 15;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
Reference in New Issue
Block a user