forked from I2P_Developers/i2p.i2p
reduce object churn in ElG decrypt
This commit is contained in:
@@ -57,6 +57,9 @@ public class ElGamalEngine {
|
|||||||
private final I2PAppContext _context;
|
private final I2PAppContext _context;
|
||||||
private final YKGenerator _ykgen;
|
private final YKGenerator _ykgen;
|
||||||
|
|
||||||
|
private static final BigInteger ELGPM1 = CryptoConstants.elgp.subtract(BigInteger.ONE);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ElGamal engine should only be constructed and accessed through the
|
* The ElGamal engine should only be constructed and accessed through the
|
||||||
* application context. This constructor should only be used by the
|
* application context. This constructor should only be used by the
|
||||||
@@ -171,10 +174,11 @@ public class ElGamalEngine {
|
|||||||
if (_log.shouldLog(Log.WARN)) _log.warn("Took too long to encrypt ElGamal block (" + diff + "ms)");
|
if (_log.shouldLog(Log.WARN)) _log.warn("Took too long to encrypt ElGamal block (" + diff + "ms)");
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.statManager().addRateData("crypto.elGamal.encrypt", diff, 0);
|
_context.statManager().addRateData("crypto.elGamal.encrypt", diff);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Decrypt the data
|
/** Decrypt the data
|
||||||
* @param encrypted encrypted data, must be exactly 514 bytes
|
* @param encrypted encrypted data, must be exactly 514 bytes
|
||||||
* Contains the two-part encrypted data starting at bytes 0 and 257.
|
* Contains the two-part encrypted data starting at bytes 0 and 257.
|
||||||
@@ -184,26 +188,26 @@ public class ElGamalEngine {
|
|||||||
* @return unencrypted data or null on failure
|
* @return unencrypted data or null on failure
|
||||||
*/
|
*/
|
||||||
public byte[] decrypt(byte encrypted[], PrivateKey privateKey) {
|
public byte[] decrypt(byte encrypted[], PrivateKey privateKey) {
|
||||||
// actually it must be exactly 514 bytes or the arraycopy below will AIOOBE
|
if ((encrypted == null) || (encrypted.length != 514))
|
||||||
if ((encrypted == null) || (encrypted.length > 514))
|
throw new IllegalArgumentException("Data to decrypt must be exactly 514 bytes");
|
||||||
throw new IllegalArgumentException("Data to decrypt must be <= 514 bytes at the moment");
|
|
||||||
long start = _context.clock().now();
|
long start = _context.clock().now();
|
||||||
|
|
||||||
byte[] ybytes = new byte[257];
|
|
||||||
byte[] dbytes = new byte[257];
|
|
||||||
System.arraycopy(encrypted, 0, ybytes, 0, 257);
|
|
||||||
System.arraycopy(encrypted, 257, dbytes, 0, 257);
|
|
||||||
BigInteger y = new NativeBigInteger(1, ybytes);
|
|
||||||
BigInteger d = new NativeBigInteger(1, dbytes);
|
|
||||||
BigInteger a = new NativeBigInteger(1, privateKey.getData());
|
BigInteger a = new NativeBigInteger(1, privateKey.getData());
|
||||||
BigInteger y1p = CryptoConstants.elgp.subtract(BigInteger.ONE).subtract(a);
|
BigInteger y1p = ELGPM1.subtract(a);
|
||||||
|
// we use this buf first for Y, then for D, then for the hash
|
||||||
|
byte[] buf = SimpleByteCache.acquire(257);
|
||||||
|
System.arraycopy(encrypted, 0, buf, 0, 257);
|
||||||
|
BigInteger y = new NativeBigInteger(1, buf);
|
||||||
BigInteger ya = y.modPow(y1p, CryptoConstants.elgp);
|
BigInteger ya = y.modPow(y1p, CryptoConstants.elgp);
|
||||||
|
System.arraycopy(encrypted, 257, buf, 0, 257);
|
||||||
|
BigInteger d = new NativeBigInteger(1, buf);
|
||||||
BigInteger m = ya.multiply(d);
|
BigInteger m = ya.multiply(d);
|
||||||
m = m.mod(CryptoConstants.elgp);
|
m = m.mod(CryptoConstants.elgp);
|
||||||
byte val[] = m.toByteArray();
|
byte val[] = m.toByteArray();
|
||||||
int i = 0;
|
int i;
|
||||||
for (i = 0; i < val.length; i++)
|
for (i = 0; i < val.length; i++) {
|
||||||
if (val[i] != (byte) 0x00) break;
|
if (val[i] != (byte) 0x00) break;
|
||||||
|
}
|
||||||
|
|
||||||
int payloadLen = val.length - i - 1 - Hash.HASH_LENGTH;
|
int payloadLen = val.length - i - 1 - Hash.HASH_LENGTH;
|
||||||
if (payloadLen < 0) {
|
if (payloadLen < 0) {
|
||||||
@@ -220,10 +224,10 @@ public class ElGamalEngine {
|
|||||||
byte rv[] = new byte[payloadLen];
|
byte rv[] = new byte[payloadLen];
|
||||||
System.arraycopy(val, i + 1 + Hash.HASH_LENGTH, rv, 0, rv.length);
|
System.arraycopy(val, i + 1 + Hash.HASH_LENGTH, rv, 0, rv.length);
|
||||||
|
|
||||||
byte[] calcHash = SimpleByteCache.acquire(Hash.HASH_LENGTH);
|
// we reuse buf here for the calculated hash
|
||||||
_context.sha().calculateHash(rv, 0, payloadLen, calcHash, 0);
|
_context.sha().calculateHash(rv, 0, payloadLen, buf, 0);
|
||||||
boolean ok = DataHelper.eq(calcHash, 0, val, i + 1, Hash.HASH_LENGTH);
|
boolean ok = DataHelper.eq(buf, 0, val, i + 1, Hash.HASH_LENGTH);
|
||||||
SimpleByteCache.release(calcHash);
|
SimpleByteCache.release(buf);
|
||||||
|
|
||||||
long end = _context.clock().now();
|
long end = _context.clock().now();
|
||||||
|
|
||||||
@@ -233,7 +237,7 @@ public class ElGamalEngine {
|
|||||||
_log.warn("Took too long to decrypt and verify ElGamal block (" + diff + "ms)");
|
_log.warn("Took too long to decrypt and verify ElGamal block (" + diff + "ms)");
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.statManager().addRateData("crypto.elGamal.decrypt", diff, 0);
|
_context.statManager().addRateData("crypto.elGamal.decrypt", diff);
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
//_log.debug("Hash matches: " + DataHelper.toString(hash.getData(), hash.getData().length));
|
//_log.debug("Hash matches: " + DataHelper.toString(hash.getData(), hash.getData().length));
|
||||||
|
Reference in New Issue
Block a user