forked from I2P_Developers/i2p.i2p
* Crypto: Implement and then comment out an alternate
AES-256/CBC implementation using the JVM crypto libs, and tests, it isn't faster
This commit is contained in:
@ -11,6 +11,12 @@ package net.i2p.crypto;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
// for using system version
|
||||
//import java.security.GeneralSecurityException;
|
||||
//import javax.crypto.Cipher;
|
||||
//import javax.crypto.spec.IvParameterSpec;
|
||||
//import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.ByteArray;
|
||||
import net.i2p.data.DataHelper;
|
||||
@ -34,18 +40,47 @@ public class CryptixAESEngine extends AESEngine {
|
||||
|
||||
private static final ByteCache _prevCache = ByteCache.getInstance(16, 16);
|
||||
|
||||
/**** see comments for main() below
|
||||
private static final boolean USE_SYSTEM_AES;
|
||||
static {
|
||||
boolean systemOK = false;
|
||||
try {
|
||||
systemOK = Cipher.getMaxAllowedKeyLength("AES") >= 256;
|
||||
} catch (GeneralSecurityException gse) {
|
||||
// a NoSuchAlgorithmException
|
||||
} catch (NoSuchMethodError nsme) {
|
||||
// JamVM, gij
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
SecretKeySpec key = new SecretKeySpec(new byte[32], "AES");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
systemOK = true;
|
||||
} catch (GeneralSecurityException gse) {
|
||||
}
|
||||
}
|
||||
USE_SYSTEM_AES = systemOK;
|
||||
//System.out.println("Using system AES? " + systemOK);
|
||||
}
|
||||
****/
|
||||
|
||||
public CryptixAESEngine(I2PAppContext context) {
|
||||
super(context);
|
||||
//_cache = new CryptixAESKeyCache();
|
||||
}
|
||||
|
||||
/** @param length must be a multiple of 16 */
|
||||
/**
|
||||
* @param iv must be 16 bytes
|
||||
* @param length must be a multiple of 16
|
||||
*/
|
||||
@Override
|
||||
public void encrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int length) {
|
||||
encrypt(payload, payloadIndex, out, outIndex, sessionKey, iv, 0, length);
|
||||
}
|
||||
|
||||
/** @param length must be a multiple of 16 */
|
||||
/**
|
||||
* @param iv must be 16 bytes
|
||||
* @param length must be a multiple of 16
|
||||
*/
|
||||
@Override
|
||||
public void encrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int ivOffset, int length) {
|
||||
if ( (payload == null) || (out == null) || (sessionKey == null) || (iv == null) )
|
||||
@ -65,6 +100,22 @@ public class CryptixAESEngine extends AESEngine {
|
||||
return;
|
||||
}
|
||||
|
||||
/****
|
||||
if (USE_SYSTEM_AES) {
|
||||
try {
|
||||
SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES");
|
||||
IvParameterSpec ivps = new IvParameterSpec(iv, ivOffset, 16);
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, ivps, _context.random());
|
||||
cipher.doFinal(payload, payloadIndex, length, out, outIndex);
|
||||
return;
|
||||
} catch (GeneralSecurityException gse) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Java encrypt fail", gse);
|
||||
}
|
||||
}
|
||||
****/
|
||||
|
||||
int numblock = length / 16;
|
||||
|
||||
DataHelper.xor(iv, ivOffset, payload, payloadIndex, out, outIndex, 16);
|
||||
@ -79,6 +130,7 @@ public class CryptixAESEngine extends AESEngine {
|
||||
public void decrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int length) {
|
||||
decrypt(payload, payloadIndex, out, outIndex, sessionKey, iv, 0, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int ivOffset, int length) {
|
||||
if ((iv== null) || (payload == null) || (payload.length <= 0) || (sessionKey == null) )
|
||||
@ -95,6 +147,22 @@ public class CryptixAESEngine extends AESEngine {
|
||||
return ;
|
||||
}
|
||||
|
||||
/****
|
||||
if (USE_SYSTEM_AES) {
|
||||
try {
|
||||
SecretKeySpec key = new SecretKeySpec(sessionKey.getData(), "AES");
|
||||
IvParameterSpec ivps = new IvParameterSpec(iv, ivOffset, 16);
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, ivps, _context.random());
|
||||
cipher.doFinal(payload, payloadIndex, length, out, outIndex);
|
||||
return;
|
||||
} catch (GeneralSecurityException gse) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Java decrypt fail", gse);
|
||||
}
|
||||
}
|
||||
****/
|
||||
|
||||
int numblock = length / 16;
|
||||
if (length % 16 != 0) numblock++;
|
||||
|
||||
@ -167,37 +235,89 @@ public class CryptixAESEngine extends AESEngine {
|
||||
CryptixRijndael_Algorithm.blockDecrypt(payload, rv, inIndex, outIndex, sessionKey.getPreparedKey(), 16);
|
||||
}
|
||||
|
||||
/********
|
||||
/******
|
||||
private static final int MATCH_RUNS = 5000;
|
||||
private static final int TIMING_RUNS = 10000;
|
||||
******/
|
||||
|
||||
/**
|
||||
* Test results 10K timing runs.
|
||||
* July 2011 eeepc.
|
||||
* Not worth enabling System version.
|
||||
* And we can't get rid of Cryptix because AES-256 is unavailable
|
||||
* in several JVMs.
|
||||
* Make USE_SYSTEM_AES above non-final to run this.
|
||||
*<pre>
|
||||
* JVM Cryptix (ms) System (ms)
|
||||
* Sun 8662 n/a
|
||||
* OpenJDK 8616 8510
|
||||
* Harmony 14732 16986
|
||||
* JamVM 50013 761494 (!)
|
||||
* gij 51130 761693 (!)
|
||||
* jrockit 9780 n/a
|
||||
*</pre>
|
||||
*
|
||||
*/
|
||||
/*******
|
||||
public static void main(String args[]) {
|
||||
I2PAppContext ctx = new I2PAppContext();
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
try {
|
||||
boolean canTestSystem = USE_SYSTEM_AES;
|
||||
if (!canTestSystem)
|
||||
System.out.println("System AES 256 not available, testing Cryptix only");
|
||||
testEDBlock(ctx);
|
||||
testEDBlock2(ctx);
|
||||
testED(ctx);
|
||||
testED2(ctx);
|
||||
if (canTestSystem) {
|
||||
System.out.println("Start Cryptix vs. System verification run of " + MATCH_RUNS);
|
||||
for (int i = 0; i < MATCH_RUNS; i++) {
|
||||
testED(ctx, false, true);
|
||||
testED(ctx, true, false);
|
||||
}
|
||||
}
|
||||
System.out.println("Start Cryptix run of " + TIMING_RUNS);
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < TIMING_RUNS; i++) {
|
||||
testED(ctx, false, false);
|
||||
}
|
||||
System.out.println("Cryptix took " + (System.currentTimeMillis() - start));
|
||||
if (canTestSystem) {
|
||||
System.out.println("Start System run of " + TIMING_RUNS);
|
||||
start = System.currentTimeMillis();
|
||||
for (int i = 0; i < TIMING_RUNS; i++) {
|
||||
testED(ctx, true, true);
|
||||
}
|
||||
System.out.println("System took " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
//testFake(ctx);
|
||||
//testNull(ctx);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||
//try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
private static void testED(I2PAppContext ctx) {
|
||||
|
||||
private static final byte[] _iv = new byte[16];
|
||||
private static byte[] _orig = new byte[1024];
|
||||
private static byte[] _encrypted = new byte[1024];
|
||||
private static byte[] _decrypted = new byte[1024];
|
||||
|
||||
private static void testED(I2PAppContext ctx, boolean systemEnc, boolean systemDec) {
|
||||
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||
byte iv[] = new byte[16];
|
||||
byte orig[] = new byte[128];
|
||||
byte encrypted[] = new byte[128];
|
||||
byte decrypted[] = new byte[128];
|
||||
ctx.random().nextBytes(iv);
|
||||
ctx.random().nextBytes(orig);
|
||||
ctx.random().nextBytes(_iv);
|
||||
ctx.random().nextBytes(_orig);
|
||||
CryptixAESEngine aes = new CryptixAESEngine(ctx);
|
||||
aes.encrypt(orig, 0, encrypted, 0, key, iv, orig.length);
|
||||
aes.decrypt(encrypted, 0, decrypted, 0, key, iv, encrypted.length);
|
||||
if (!DataHelper.eq(decrypted,orig))
|
||||
USE_SYSTEM_AES = systemEnc;
|
||||
aes.encrypt(_orig, 0, _encrypted, 0, key, _iv, _orig.length);
|
||||
USE_SYSTEM_AES = systemDec;
|
||||
aes.decrypt(_encrypted, 0, _decrypted, 0, key, _iv, _encrypted.length);
|
||||
if (!DataHelper.eq(_decrypted,_orig))
|
||||
throw new RuntimeException("full D(E(orig)) != orig");
|
||||
else
|
||||
System.out.println("full D(E(orig)) == orig");
|
||||
//else
|
||||
// System.out.println("full D(E(orig)) == orig");
|
||||
}
|
||||
|
||||
// this verifies decryption in-place
|
||||
private static void testED2(I2PAppContext ctx) {
|
||||
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||
byte iv[] = new byte[16];
|
||||
@ -213,6 +333,7 @@ public class CryptixAESEngine extends AESEngine {
|
||||
else
|
||||
System.out.println("full D(E(orig)) == orig");
|
||||
}
|
||||
|
||||
private static void testFake(I2PAppContext ctx) {
|
||||
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||
SessionKey wrongKey = ctx.keyGenerator().generateSessionKey();
|
||||
@ -230,6 +351,7 @@ public class CryptixAESEngine extends AESEngine {
|
||||
else
|
||||
System.out.println("full D(E(orig)) != orig when we used the wrong key");
|
||||
}
|
||||
|
||||
private static void testNull(I2PAppContext ctx) {
|
||||
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||
SessionKey wrongKey = ctx.keyGenerator().generateSessionKey();
|
||||
@ -249,6 +371,7 @@ public class CryptixAESEngine extends AESEngine {
|
||||
|
||||
throw new RuntimeException("full D(E(orig)) didn't fail when we used null!");
|
||||
}
|
||||
|
||||
private static void testEDBlock(I2PAppContext ctx) {
|
||||
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||
byte iv[] = new byte[16];
|
||||
@ -265,6 +388,7 @@ public class CryptixAESEngine extends AESEngine {
|
||||
else
|
||||
System.out.println("block D(E(orig)) == orig");
|
||||
}
|
||||
|
||||
private static void testEDBlock2(I2PAppContext ctx) {
|
||||
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||
byte iv[] = new byte[16];
|
||||
|
Reference in New Issue
Block a user