* started reducing the temporary buffers created within various crypto methods , as we've
got some pretty heavy GC churn when under load. rough estimate is we allocate 5-8x as much data as we need, copying it all over the place before forwarding it (or processing it). this should cut down a few of those copies, but not enough yet. it'd be great to get that down to 2x. * lots of logging
This commit is contained in:
@ -284,7 +284,7 @@ public class I2PAppContext {
|
|||||||
* matter. Though for the crazy people out there, we do expose a way to
|
* matter. Though for the crazy people out there, we do expose a way to
|
||||||
* disable it.
|
* disable it.
|
||||||
*/
|
*/
|
||||||
public AESEngine AESEngine() {
|
public AESEngine aes() {
|
||||||
if (!_AESEngineInitialized) initializeAESEngine();
|
if (!_AESEngineInitialized) initializeAESEngine();
|
||||||
return _AESEngine;
|
return _AESEngine;
|
||||||
}
|
}
|
||||||
|
@ -37,21 +37,16 @@ public class AESEngine {
|
|||||||
|
|
||||||
/** Encrypt the payload with the session key
|
/** Encrypt the payload with the session key
|
||||||
* @param payload data to be encrypted
|
* @param payload data to be encrypted
|
||||||
|
* @param payloadIndex index into the payload to start encrypting
|
||||||
|
* @param out where to store the result
|
||||||
|
* @param outIndex where in out to start writing
|
||||||
* @param sessionKey private esession key to encrypt to
|
* @param sessionKey private esession key to encrypt to
|
||||||
* @param initializationVector IV for CBC
|
* @param iv IV for CBC
|
||||||
* @return encrypted data
|
* @param length how much data to encrypt
|
||||||
*/
|
*/
|
||||||
public byte[] encrypt(byte payload[], SessionKey sessionKey, byte initializationVector[]) {
|
public void encrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int length) {
|
||||||
if ((initializationVector == null) || (payload == null) || (sessionKey == null)
|
System.arraycopy(payload, payloadIndex, out, outIndex, length);
|
||||||
|| (initializationVector.length != 16)) return null;
|
_log.warn("Warning: AES is disabled");
|
||||||
|
|
||||||
byte cyphertext[] = null;
|
|
||||||
if ((payload.length % 16) == 0)
|
|
||||||
cyphertext = new byte[payload.length];
|
|
||||||
else
|
|
||||||
cyphertext = new byte[payload.length + (16 - (payload.length % 16))];
|
|
||||||
System.arraycopy(payload, 0, cyphertext, 0, payload.length);
|
|
||||||
return cyphertext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] safeEncrypt(byte payload[], SessionKey sessionKey, byte iv[], int paddedSize) {
|
public byte[] safeEncrypt(byte payload[], SessionKey sessionKey, byte iv[], int paddedSize) {
|
||||||
@ -72,13 +67,17 @@ public class AESEngine {
|
|||||||
_log.error("Error writing data", dfe);
|
_log.error("Error writing data", dfe);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return encrypt(baos.toByteArray(), sessionKey, iv);
|
byte orig[] = baos.toByteArray();
|
||||||
|
byte rv[] = new byte[orig.length];
|
||||||
|
encrypt(orig, 0, rv, 0, sessionKey, iv, rv.length);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] safeDecrypt(byte payload[], SessionKey sessionKey, byte iv[]) {
|
public byte[] safeDecrypt(byte payload[], SessionKey sessionKey, byte iv[]) {
|
||||||
if ((iv == null) || (payload == null) || (sessionKey == null) || (iv.length != 16)) return null;
|
if ((iv == null) || (payload == null) || (sessionKey == null) || (iv.length != 16)) return null;
|
||||||
|
|
||||||
byte decr[] = decrypt(payload, sessionKey, iv);
|
byte decr[] = new byte[payload.length];
|
||||||
|
decrypt(payload, 0, decr, 0, sessionKey, iv, payload.length);
|
||||||
if (decr == null) {
|
if (decr == null) {
|
||||||
_log.error("Error decrypting the data - payload " + payload.length + " decrypted to null");
|
_log.error("Error decrypting the data - payload " + payload.length + " decrypted to null");
|
||||||
return null;
|
return null;
|
||||||
@ -110,19 +109,19 @@ public class AESEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** decrypt the data with the session key provided
|
|
||||||
* @param cyphertext encrypted data
|
|
||||||
* @param sessionKey private session key
|
|
||||||
* @param initializationVector IV for CBC
|
|
||||||
* @return unencrypted data
|
|
||||||
*/
|
|
||||||
public byte[] decrypt(byte cyphertext[], SessionKey sessionKey, byte initializationVector[]) {
|
|
||||||
if ((initializationVector == null) || (cyphertext == null) || (sessionKey == null)
|
|
||||||
|| (initializationVector.length != 16)) return null;
|
|
||||||
|
|
||||||
byte payload[] = new byte[cyphertext.length];
|
/** Decrypt the data with the session key
|
||||||
|
* @param payload data to be decrypted
|
||||||
|
* @param payloadIndex index into the payload to start decrypting
|
||||||
|
* @param out where to store the cleartext
|
||||||
|
* @param outIndex where in out to start writing
|
||||||
|
* @param sessionKey private session key to decrypt to
|
||||||
|
* @param iv IV for CBC
|
||||||
|
* @param length how much data to decrypt
|
||||||
|
*/
|
||||||
|
public void decrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int length) {
|
||||||
|
System.arraycopy(payload, payloadIndex, out, outIndex, length);
|
||||||
_log.warn("Warning: AES is disabled");
|
_log.warn("Warning: AES is disabled");
|
||||||
return cyphertext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
@ -133,14 +132,16 @@ public class AESEngine {
|
|||||||
|
|
||||||
byte sbuf[] = new byte[16];
|
byte sbuf[] = new byte[16];
|
||||||
RandomSource.getInstance().nextBytes(sbuf);
|
RandomSource.getInstance().nextBytes(sbuf);
|
||||||
byte se[] = ctx.AESEngine().encrypt(sbuf, key, iv);
|
byte se[] = new byte[16];
|
||||||
byte sd[] = ctx.AESEngine().decrypt(se, key, iv);
|
ctx.aes().encrypt(sbuf, 0, se, 0, key, iv, sbuf.length);
|
||||||
|
byte sd[] = new byte[16];
|
||||||
|
ctx.aes().decrypt(se, 0, sd, 0, key, iv, se.length);
|
||||||
ctx.logManager().getLog(AESEngine.class).debug("Short test: " + DataHelper.eq(sd, sbuf));
|
ctx.logManager().getLog(AESEngine.class).debug("Short test: " + DataHelper.eq(sd, sbuf));
|
||||||
|
|
||||||
byte lbuf[] = new byte[1024];
|
byte lbuf[] = new byte[1024];
|
||||||
RandomSource.getInstance().nextBytes(sbuf);
|
RandomSource.getInstance().nextBytes(sbuf);
|
||||||
byte le[] = ctx.AESEngine().safeEncrypt(lbuf, key, iv, 2048);
|
byte le[] = ctx.aes().safeEncrypt(lbuf, key, iv, 2048);
|
||||||
byte ld[] = ctx.AESEngine().safeDecrypt(le, key, iv);
|
byte ld[] = ctx.aes().safeDecrypt(le, key, iv);
|
||||||
ctx.logManager().getLog(AESEngine.class).debug("Long test: " + DataHelper.eq(ld, lbuf));
|
ctx.logManager().getLog(AESEngine.class).debug("Long test: " + DataHelper.eq(ld, lbuf));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -230,22 +230,21 @@ public class AESInputStream extends FilterInputStream {
|
|||||||
_log.info(encrypted.length + " bytes makes up " + numBlocks + " blocks to decrypt normally");
|
_log.info(encrypted.length + " bytes makes up " + numBlocks + " blocks to decrypt normally");
|
||||||
}
|
}
|
||||||
|
|
||||||
byte block[] = new byte[BLOCK_SIZE];
|
|
||||||
for (int i = 0; i < numBlocks; i++) {
|
for (int i = 0; i < numBlocks; i++) {
|
||||||
System.arraycopy(encrypted, i * BLOCK_SIZE, block, 0, BLOCK_SIZE);
|
_context.aes().decrypt(encrypted, i * BLOCK_SIZE, encrypted, i * BLOCK_SIZE, _key, _lastBlock, BLOCK_SIZE);
|
||||||
byte decrypted[] = _context.AESEngine().decrypt(block, _key, _lastBlock);
|
DataHelper.xor(encrypted, i * BLOCK_SIZE, _lastBlock, 0, encrypted, i * BLOCK_SIZE, BLOCK_SIZE);
|
||||||
byte data[] = DataHelper.xor(decrypted, _lastBlock);
|
int payloadBytes = countBlockPayload(encrypted, i * BLOCK_SIZE);
|
||||||
int cleaned[] = stripPadding(data);
|
|
||||||
for (int j = 0; j < cleaned.length; j++) {
|
for (int j = 0; j < payloadBytes; j++) {
|
||||||
if (cleaned[j] <= 0) {
|
int c = encrypted[j + i * BLOCK_SIZE];
|
||||||
cleaned[j] += 256;
|
if (c <= 0)
|
||||||
//_log.error("(modified: " + cleaned[j] + ")");
|
c += 256;
|
||||||
}
|
_readyBuf.add(new Integer(c));
|
||||||
_readyBuf.add(new Integer(cleaned[j]));
|
|
||||||
}
|
}
|
||||||
_cumulativePrepared += cleaned.length;
|
_cumulativePaddingStripped += BLOCK_SIZE - payloadBytes;
|
||||||
//_log.debug("Updating last block for inputStream");
|
_cumulativePrepared += payloadBytes;
|
||||||
System.arraycopy(decrypted, 0, _lastBlock, 0, BLOCK_SIZE);
|
|
||||||
|
System.arraycopy(encrypted, i * BLOCK_SIZE, _lastBlock, 0, BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int remaining = encrypted.length % BLOCK_SIZE;
|
int remaining = encrypted.length % BLOCK_SIZE;
|
||||||
@ -263,6 +262,9 @@ public class AESInputStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* How many non-padded bytes are there in the block starting at the given
|
||||||
|
* location.
|
||||||
|
*
|
||||||
* PKCS#5 specifies the padding for the block has the # of padding bytes
|
* PKCS#5 specifies the padding for the block has the # of padding bytes
|
||||||
* located in the last byte of the block, and each of the padding bytes are
|
* located in the last byte of the block, and each of the padding bytes are
|
||||||
* equal to that value.
|
* equal to that value.
|
||||||
@ -275,31 +277,29 @@ public class AESInputStream extends FilterInputStream {
|
|||||||
*
|
*
|
||||||
* We use 16 byte blocks in this AES implementation
|
* We use 16 byte blocks in this AES implementation
|
||||||
*
|
*
|
||||||
|
* @throws IOException if the padding is invalid
|
||||||
*/
|
*/
|
||||||
private int[] stripPadding(byte data[]) throws IOException {
|
private int countBlockPayload(byte data[], int startIndex) throws IOException {
|
||||||
int numPadBytes = data[data.length - 1];
|
int numPadBytes = data[startIndex + BLOCK_SIZE - 1];
|
||||||
if ((numPadBytes >= data.length) || (numPadBytes <= 0)) {
|
if ((numPadBytes >= BLOCK_SIZE) || (numPadBytes <= 0)) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("stripPadding from block " + DataHelper.toHexString(data) + " (" + data.length + "bytes): "
|
_log.debug("countBlockPayload on block index " + startIndex
|
||||||
+ numPadBytes + " is an invalid # of pad bytes");
|
+ numPadBytes + " is an invalid # of pad bytes");
|
||||||
throw new IOException("Invalid number of pad bytes (" + numPadBytes
|
throw new IOException("Invalid number of pad bytes (" + numPadBytes
|
||||||
+ ") for " + data.length + " bytes");
|
+ ") for " + startIndex + " index");
|
||||||
}
|
}
|
||||||
|
|
||||||
int rv[] = new int[data.length - numPadBytes];
|
|
||||||
// optional, but a really good idea: verify the padding
|
// optional, but a really good idea: verify the padding
|
||||||
if (true) {
|
if (true) {
|
||||||
for (int i = data.length - numPadBytes; i < data.length; i++) {
|
for (int i = BLOCK_SIZE - numPadBytes; i < BLOCK_SIZE; i++) {
|
||||||
if (data[i] != (byte) numPadBytes) {
|
if (data[startIndex + i] != (byte) numPadBytes) {
|
||||||
throw new IOException("Incorrect padding on decryption: data[" + i
|
throw new IOException("Incorrect padding on decryption: data[" + i
|
||||||
+ "] = " + data[i] + " not " + numPadBytes);
|
+ "] = " + data[startIndex + i] + " not " + numPadBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < rv.length; i++)
|
|
||||||
rv[i] = data[i];
|
return BLOCK_SIZE - numPadBytes;
|
||||||
_cumulativePaddingStripped += numPadBytes;
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int remainingBytes() {
|
int remainingBytes() {
|
||||||
|
@ -106,18 +106,16 @@ public class AESOutputStream extends FilterOutputStream {
|
|||||||
int numBlocks = src.length / (BLOCK_SIZE - 1);
|
int numBlocks = src.length / (BLOCK_SIZE - 1);
|
||||||
|
|
||||||
byte block[] = new byte[BLOCK_SIZE];
|
byte block[] = new byte[BLOCK_SIZE];
|
||||||
block[BLOCK_SIZE - 1] = 0x01; // the padding byte for "full" blocks
|
|
||||||
for (int i = 0; i < numBlocks; i++) {
|
for (int i = 0; i < numBlocks; i++) {
|
||||||
System.arraycopy(src, i * 15, block, 0, 15);
|
DataHelper.xor(src, i * 15, _lastBlock, 0, block, 0, 15);
|
||||||
byte data[] = DataHelper.xor(block, _lastBlock);
|
// the padding byte for "full" blocks
|
||||||
byte encrypted[] = _context.AESEngine().encrypt(data, _key, _lastBlock);
|
block[BLOCK_SIZE - 1] = (byte)(_lastBlock[BLOCK_SIZE - 1] ^ 0x01);
|
||||||
_cumulativeWritten += encrypted.length;
|
_context.aes().encrypt(block, 0, block, 0, _key, _lastBlock, BLOCK_SIZE);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Padding block " + i + " of " + numBlocks + " with 1 byte. orig= "
|
_log.debug("Padding block " + i + " of " + numBlocks + " with 1 byte");
|
||||||
+ DataHelper.toHexString(data) + " (size=" + data.length + ") encrypted= "
|
out.write(block);
|
||||||
+ DataHelper.toHexString(encrypted) + " (size=" + encrypted.length + ")");
|
System.arraycopy(block, 0, _lastBlock, 0, BLOCK_SIZE);
|
||||||
out.write(encrypted);
|
_cumulativeWritten += BLOCK_SIZE;
|
||||||
System.arraycopy(encrypted, encrypted.length - BLOCK_SIZE, _lastBlock, 0, BLOCK_SIZE);
|
|
||||||
_cumulativePadding++;
|
_cumulativePadding++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,12 +127,12 @@ public class AESOutputStream extends FilterOutputStream {
|
|||||||
_log.debug("Padding " + src.length + " with " + paddingBytes + " bytes in " + numBlocks + " blocks");
|
_log.debug("Padding " + src.length + " with " + paddingBytes + " bytes in " + numBlocks + " blocks");
|
||||||
System.arraycopy(src, numBlocks * 15, block, 0, remainingBytes);
|
System.arraycopy(src, numBlocks * 15, block, 0, remainingBytes);
|
||||||
Arrays.fill(block, remainingBytes, BLOCK_SIZE, (byte) paddingBytes);
|
Arrays.fill(block, remainingBytes, BLOCK_SIZE, (byte) paddingBytes);
|
||||||
byte data[] = DataHelper.xor(block, _lastBlock);
|
DataHelper.xor(block, 0, _lastBlock, 0, block, 0, BLOCK_SIZE);
|
||||||
byte encrypted[] = _context.AESEngine().encrypt(data, _key, _lastBlock);
|
_context.aes().encrypt(block, 0, block, 0, _key, _lastBlock, BLOCK_SIZE);
|
||||||
out.write(encrypted);
|
out.write(block);
|
||||||
System.arraycopy(encrypted, encrypted.length - BLOCK_SIZE, _lastBlock, 0, BLOCK_SIZE);
|
System.arraycopy(block, 0, _lastBlock, 0, BLOCK_SIZE);
|
||||||
_cumulativePadding += paddingBytes;
|
_cumulativePadding += paddingBytes;
|
||||||
_cumulativeWritten += encrypted.length;
|
_cumulativeWritten += BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ package net.i2p.crypto;
|
|||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.SessionKey;
|
import net.i2p.data.SessionKey;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
@ -33,104 +34,63 @@ public class CryptixAESEngine extends AESEngine {
|
|||||||
super(context);
|
super(context);
|
||||||
_log = context.logManager().getLog(CryptixAESEngine.class);
|
_log = context.logManager().getLog(CryptixAESEngine.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] encrypt(byte payload[], SessionKey sessionKey, byte initializationVector[]) {
|
public void encrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int length) {
|
||||||
if ((initializationVector == null) || (payload == null) || (payload.length <= 0) || (sessionKey == null)
|
if ( (payload == null) || (out == null) || (sessionKey == null) || (iv == null) || (iv.length != 16) )
|
||||||
|| (initializationVector.length != 16)) return null;
|
throw new NullPointerException("invalid args to aes");
|
||||||
|
if (payload.length < payloadIndex + length)
|
||||||
|
throw new IllegalArgumentException("Payload is too short");
|
||||||
|
if (out.length < outIndex + length)
|
||||||
|
throw new IllegalArgumentException("Output is too short");
|
||||||
|
if (length <= 0)
|
||||||
|
throw new IllegalArgumentException("Length is too small");
|
||||||
|
if (length % 16 != 0)
|
||||||
|
throw new IllegalArgumentException("Only lengths mod 16 are supported here");
|
||||||
|
|
||||||
if (USE_FAKE_CRYPTO) {
|
if (USE_FAKE_CRYPTO) {
|
||||||
_log.warn("AES Crypto disabled! Using trivial XOR");
|
_log.warn("AES Crypto disabled! Using trivial XOR");
|
||||||
byte rv[] = new byte[payload.length];
|
System.arraycopy(payload, payloadIndex, out, outIndex, length);
|
||||||
for (int i = 0; i < rv.length; i++)
|
return;
|
||||||
rv[i] = (byte) (payload[i] ^ FAKE_KEY);
|
}
|
||||||
return rv;
|
|
||||||
|
int numblock = length / 16;
|
||||||
|
|
||||||
|
DataHelper.xor(iv, 0, payload, payloadIndex, out, outIndex, 16);
|
||||||
|
encryptBlock(out, outIndex, sessionKey, out, outIndex);
|
||||||
|
for (int x = 1; x < numblock; x++) {
|
||||||
|
DataHelper.xor(out, outIndex + (x-1) * 16, payload, payloadIndex + x * 16, out, outIndex + x * 16, 16);
|
||||||
|
encryptBlock(out, outIndex + x * 16, sessionKey, out, outIndex + x * 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decrypt(byte payload[], int payloadIndex, byte out[], int outIndex, SessionKey sessionKey, byte iv[], int length) {
|
||||||
|
if ((iv== null) || (payload == null) || (payload.length <= 0) || (sessionKey == null)
|
||||||
|
|| (iv.length != 16))
|
||||||
|
throw new IllegalArgumentException("bad setup");
|
||||||
|
|
||||||
|
if (USE_FAKE_CRYPTO) {
|
||||||
|
_log.warn("AES Crypto disabled! Using trivial XOR");
|
||||||
|
System.arraycopy(payload, payloadIndex, out, outIndex, length);
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numblock = payload.length / 16;
|
int numblock = payload.length / 16;
|
||||||
if (payload.length % 16 != 0) numblock++;
|
if (payload.length % 16 != 0) numblock++;
|
||||||
byte[][] plain = new byte[numblock][16];
|
|
||||||
for (int x = 0; x < numblock; x++) {
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
plain[x][y] = payload[x * 16 + y];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[][] cipher = new byte[numblock][16];
|
decryptBlock(payload, 0, sessionKey, out, 0);
|
||||||
cipher[0] = encrypt(xor(initializationVector, plain[0]), sessionKey);
|
DataHelper.xor(out, 0, iv, 0, out, 0, 16);
|
||||||
for (int x = 1; x < numblock; x++) {
|
for (int x = 1; x < numblock; x++) {
|
||||||
cipher[x] = encrypt(xor(cipher[x - 1], plain[x]), sessionKey);
|
decryptBlock(payload, x * 16, sessionKey, out, x * 16);
|
||||||
|
DataHelper.xor(out, x * 16, payload, (x - 1) * 16, out, x * 16, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] ret = new byte[numblock * 16];
|
|
||||||
for (int x = 0; x < numblock; x++) {
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
ret[x * 16 + y] = cipher[x][y];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] decrypt(byte payload[], SessionKey sessionKey, byte initializationVector[]) {
|
final void encryptBlock(byte payload[], int inIndex, SessionKey sessionKey, byte out[], int outIndex) {
|
||||||
if ((initializationVector == null) || (payload == null) || (payload.length <= 0) || (sessionKey == null)
|
|
||||||
|| (initializationVector.length != 16)) return null;
|
|
||||||
|
|
||||||
if (USE_FAKE_CRYPTO) {
|
|
||||||
_log.warn("AES Crypto disabled! Using trivial XOR");
|
|
||||||
byte rv[] = new byte[payload.length];
|
|
||||||
for (int i = 0; i < rv.length; i++)
|
|
||||||
rv[i] = (byte) (payload[i] ^ FAKE_KEY);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numblock = payload.length / 16;
|
|
||||||
if (payload.length % 16 != 0) numblock++;
|
|
||||||
byte[][] cipher = new byte[numblock][16];
|
|
||||||
for (int x = 0; x < numblock; x++) {
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
cipher[x][y] = payload[x * 16 + y];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[][] plain = new byte[numblock][16];
|
|
||||||
plain[0] = xor(decrypt(cipher[0], sessionKey), initializationVector);
|
|
||||||
for (int x = 1; x < numblock; x++) {
|
|
||||||
plain[x] = xor(decrypt(cipher[x], sessionKey), cipher[x - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] ret = new byte[numblock * 16];
|
|
||||||
for (int x = 0; x < numblock; x++) {
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
ret[x * 16 + y] = plain[x][y];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
final static byte[] xor(byte[] a, byte[] b) {
|
|
||||||
if ((a == null) || (b == null) || (a.length != b.length)) return null;
|
|
||||||
byte[] ret = new byte[a.length];
|
|
||||||
for (int x = 0; x < a.length; x++) {
|
|
||||||
ret[x] = (byte) (a[x] ^ b[x]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Encrypt the payload with the session key
|
|
||||||
* @param payload data to be encrypted
|
|
||||||
* @param sessionKey private esession key to encrypt to
|
|
||||||
* @return encrypted data
|
|
||||||
*/
|
|
||||||
final byte[] encrypt(byte payload[], SessionKey sessionKey) {
|
|
||||||
try {
|
try {
|
||||||
Object key = CryptixRijndael_Algorithm.makeKey(sessionKey.getData(), 16);
|
Object key = CryptixRijndael_Algorithm.makeKey(sessionKey.getData(), 16);
|
||||||
byte rv[] = new byte[payload.length];
|
CryptixRijndael_Algorithm.blockEncrypt(payload, out, inIndex, outIndex, key, 16);
|
||||||
CryptixRijndael_Algorithm.blockEncrypt(payload, rv, 0, key, 16);
|
|
||||||
return rv;
|
|
||||||
} catch (InvalidKeyException ike) {
|
} catch (InvalidKeyException ike) {
|
||||||
_log.error("Invalid key", ike);
|
_log.error("Invalid key", ike);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,15 +99,55 @@ public class CryptixAESEngine extends AESEngine {
|
|||||||
* @param sessionKey private session key
|
* @param sessionKey private session key
|
||||||
* @return unencrypted data
|
* @return unencrypted data
|
||||||
*/
|
*/
|
||||||
final byte[] decrypt(byte payload[], SessionKey sessionKey) {
|
final void decryptBlock(byte payload[], int inIndex, SessionKey sessionKey, byte rv[], int outIndex) {
|
||||||
try {
|
try {
|
||||||
Object key = CryptixRijndael_Algorithm.makeKey(sessionKey.getData(), 16);
|
Object key = CryptixRijndael_Algorithm.makeKey(sessionKey.getData(), 16);
|
||||||
byte rv[] = new byte[payload.length];
|
CryptixRijndael_Algorithm.blockDecrypt(payload, rv, inIndex, outIndex, key, 16);
|
||||||
CryptixRijndael_Algorithm.blockDecrypt(payload, rv, 0, key, 16);
|
|
||||||
return rv;
|
|
||||||
} catch (InvalidKeyException ike) {
|
} catch (InvalidKeyException ike) {
|
||||||
_log.error("Invalid key", ike);
|
_log.error("Invalid key", ike);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
I2PAppContext ctx = new I2PAppContext();
|
||||||
|
try {
|
||||||
|
testEDBlock(ctx);
|
||||||
|
testED(ctx);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||||
|
}
|
||||||
|
private static void testED(I2PAppContext ctx) {
|
||||||
|
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);
|
||||||
|
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))
|
||||||
|
throw new RuntimeException("full D(E(orig)) != orig");
|
||||||
|
else
|
||||||
|
System.out.println("full D(E(orig)) == orig");
|
||||||
|
}
|
||||||
|
private static void testEDBlock(I2PAppContext ctx) {
|
||||||
|
SessionKey key = ctx.keyGenerator().generateSessionKey();
|
||||||
|
byte iv[] = new byte[16];
|
||||||
|
byte orig[] = new byte[16];
|
||||||
|
byte encrypted[] = new byte[16];
|
||||||
|
byte decrypted[] = new byte[16];
|
||||||
|
ctx.random().nextBytes(iv);
|
||||||
|
ctx.random().nextBytes(orig);
|
||||||
|
CryptixAESEngine aes = new CryptixAESEngine(ctx);
|
||||||
|
aes.encryptBlock(orig, 0, key, encrypted, 0);
|
||||||
|
aes.decryptBlock(encrypted, 0, key, decrypted, 0);
|
||||||
|
if (!DataHelper.eq(decrypted,orig))
|
||||||
|
throw new RuntimeException("block D(E(orig)) != orig");
|
||||||
|
else
|
||||||
|
System.out.println("block D(E(orig)) == orig");
|
||||||
|
}
|
||||||
}
|
}
|
@ -352,8 +352,10 @@ public class DHSessionKeyBuilder {
|
|||||||
byte iv[] = new byte[16];
|
byte iv[] = new byte[16];
|
||||||
RandomSource.getInstance().nextBytes(iv);
|
RandomSource.getInstance().nextBytes(iv);
|
||||||
String origVal = "1234567890123456"; // 16 bytes max using AESEngine
|
String origVal = "1234567890123456"; // 16 bytes max using AESEngine
|
||||||
byte enc[] = ctx.AESEngine().encrypt(origVal.getBytes(), key1, iv);
|
byte enc[] = new byte[16];
|
||||||
byte dec[] = ctx.AESEngine().decrypt(enc, key2, iv);
|
byte dec[] = new byte[16];
|
||||||
|
ctx.aes().encrypt(origVal.getBytes(), 0, enc, 0, key1, iv, 16);
|
||||||
|
ctx.aes().decrypt(enc, 0, dec, 0, key2, iv, 16);
|
||||||
String tranVal = new String(dec);
|
String tranVal = new String(dec);
|
||||||
if (origVal.equals(tranVal))
|
if (origVal.equals(tranVal))
|
||||||
_log.debug("**Success: D(E(val)) == val");
|
_log.debug("**Success: D(E(val)) == val");
|
||||||
|
@ -248,7 +248,8 @@ public class ElGamalAESEngine {
|
|||||||
SessionKey foundKey) throws DataFormatException {
|
SessionKey foundKey) throws DataFormatException {
|
||||||
//_log.debug("iv for decryption: " + DataHelper.toString(iv, 16));
|
//_log.debug("iv for decryption: " + DataHelper.toString(iv, 16));
|
||||||
//_log.debug("decrypting AES block. encr.length = " + (encrypted == null? -1 : encrypted.length) + " sentTag: " + DataHelper.toString(sentTag, 32));
|
//_log.debug("decrypting AES block. encr.length = " + (encrypted == null? -1 : encrypted.length) + " sentTag: " + DataHelper.toString(sentTag, 32));
|
||||||
byte decrypted[] = _context.AESEngine().decrypt(encrypted, key, iv);
|
byte decrypted[] = new byte[encrypted.length];
|
||||||
|
_context.aes().decrypt(encrypted, 0, decrypted, 0, key, iv, encrypted.length);
|
||||||
//Hash h = _context.sha().calculateHash(decrypted);
|
//Hash h = _context.sha().calculateHash(decrypted);
|
||||||
//_log.debug("Hash of entire aes block after decryption: \n" + DataHelper.toString(h.getData(), 32));
|
//_log.debug("Hash of entire aes block after decryption: \n" + DataHelper.toString(h.getData(), 32));
|
||||||
try {
|
try {
|
||||||
@ -503,7 +504,8 @@ public class ElGamalAESEngine {
|
|||||||
byte aesUnencr[] = aesSrc.toByteArray();
|
byte aesUnencr[] = aesSrc.toByteArray();
|
||||||
//Hash h = _context.sha().calculateHash(aesUnencr);
|
//Hash h = _context.sha().calculateHash(aesUnencr);
|
||||||
//_log.debug("Hash of entire aes block before encryption: (len=" + aesUnencr.length + ")\n" + DataHelper.toString(h.getData(), 32));
|
//_log.debug("Hash of entire aes block before encryption: (len=" + aesUnencr.length + ")\n" + DataHelper.toString(h.getData(), 32));
|
||||||
byte aesEncr[] = _context.AESEngine().encrypt(aesUnencr, key, iv);
|
byte aesEncr[] = new byte[aesUnencr.length];
|
||||||
|
_context.aes().encrypt(aesUnencr, 0, aesEncr, 0, key, iv, aesEncr.length);
|
||||||
//_log.debug("Encrypted length: " + aesEncr.length);
|
//_log.debug("Encrypted length: " + aesEncr.length);
|
||||||
return aesEncr;
|
return aesEncr;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
|
@ -467,12 +467,38 @@ public class DataHelper {
|
|||||||
|
|
||||||
public final static byte[] xor(byte lhs[], byte rhs[]) {
|
public final static byte[] xor(byte lhs[], byte rhs[]) {
|
||||||
if ((lhs == null) || (rhs == null) || (lhs.length != rhs.length)) return null;
|
if ((lhs == null) || (rhs == null) || (lhs.length != rhs.length)) return null;
|
||||||
|
byte rv[] = new byte[lhs.length];
|
||||||
|
|
||||||
byte diff[] = new byte[lhs.length];
|
byte diff[] = new byte[lhs.length];
|
||||||
for (int i = 0; i < lhs.length; i++)
|
xor(lhs, 0, rhs, 0, diff, 0, lhs.length);
|
||||||
diff[i] = (byte) (lhs[i] ^ rhs[i]);
|
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xor the lhs with the rhs, storing the result in out.
|
||||||
|
*
|
||||||
|
* @param lhs one of the source arrays
|
||||||
|
* @param startLeft starting index in the lhs array to begin the xor
|
||||||
|
* @param rhs the other source array
|
||||||
|
* @param startRight starting index in the rhs array to begin the xor
|
||||||
|
* @param out output array
|
||||||
|
* @param startOut starting index in the out array to store the result
|
||||||
|
* @param len how many bytes into the various arrays to xor
|
||||||
|
*/
|
||||||
|
public final static void xor(byte lhs[], int startLeft, byte rhs[], int startRight, byte out[], int startOut, int len) {
|
||||||
|
if ( (lhs == null) || (rhs == null) || (out == null) )
|
||||||
|
throw new NullPointerException("Invalid params to xor (" + lhs + ", " + rhs + ", " + out + ")");
|
||||||
|
if (lhs.length < startLeft + len)
|
||||||
|
throw new IllegalArgumentException("Left hand side is too short");
|
||||||
|
if (rhs.length < startRight + len)
|
||||||
|
throw new IllegalArgumentException("Right hand side is too short");
|
||||||
|
if (out.length < startOut + len)
|
||||||
|
throw new IllegalArgumentException("Result is too short");
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
out[startOut + i] = (byte) (lhs[startLeft + i] ^ rhs[startRight + i]);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// The following hashcode helpers make it simpler to write consistently hashing
|
// The following hashcode helpers make it simpler to write consistently hashing
|
||||||
// functions for objects based on their value, not JVM memory address
|
// functions for objects based on their value, not JVM memory address
|
||||||
|
@ -72,22 +72,28 @@ public class AES256Bench {
|
|||||||
iv[x] = (byte)civ[x];
|
iv[x] = (byte)civ[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] e = _context.AESEngine().encrypt(plain, key, iv);
|
byte[] e = new byte[plain.length];
|
||||||
byte[] d = _context.AESEngine().decrypt(e, key, iv);
|
_context.aes().encrypt(plain, 0, e, 0, key, iv, plain.length);
|
||||||
|
byte[] d = new byte[e.length];
|
||||||
|
_context.aes().decrypt(e, 0, d, 0, key, iv, d.length);
|
||||||
boolean same = true;
|
boolean same = true;
|
||||||
for (int x = 0; x < d.length; x++) {
|
for (int x = 0; x < d.length; x++) {
|
||||||
if (plain[x] != d[x]) {
|
if (plain[x] != d[x]) {
|
||||||
same = false;
|
throw new RuntimeException("Failed decrypt at " + x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Standard test D(E(value)) == value? " + same);
|
System.out.println("Standard test D(E(value)) == value? " + same);
|
||||||
|
if (!same) throw new RuntimeException("moo");
|
||||||
|
|
||||||
plain = "1234567890123456".getBytes();
|
plain = "1234567890123456".getBytes();
|
||||||
e = _context.AESEngine().encrypt(plain, key, iv);
|
e = new byte[plain.length];
|
||||||
d = _context.AESEngine().decrypt(e, key, iv);
|
_context.aes().encrypt(plain, 0, e, 0, key, iv, plain.length);
|
||||||
|
d = new byte[e.length];
|
||||||
|
_context.aes().decrypt(e, 0, d, 0, key, iv, d.length);
|
||||||
same = DataHelper.eq(plain, d);
|
same = DataHelper.eq(plain, d);
|
||||||
System.out.println("Different value test D(E(value)) == value? " + same);
|
System.out.println("Different value test D(E(value)) == value? " + same);
|
||||||
|
if (!same) throw new RuntimeException("moo");
|
||||||
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println();
|
System.out.println();
|
||||||
@ -104,9 +110,11 @@ public class AES256Bench {
|
|||||||
message[i] = (byte)((i%26)+'a');
|
message[i] = (byte)((i%26)+'a');
|
||||||
for (int x = 0; x < times; x++) {
|
for (int x = 0; x < times; x++) {
|
||||||
long startencrypt = System.currentTimeMillis();
|
long startencrypt = System.currentTimeMillis();
|
||||||
e = _context.AESEngine().encrypt(message, key, iv);
|
e = new byte[message.length];
|
||||||
|
d = new byte[e.length];
|
||||||
|
_context.aes().encrypt(message, 0, e, 0, key, iv, message.length);
|
||||||
long endencryptstartdecrypt = System.currentTimeMillis();
|
long endencryptstartdecrypt = System.currentTimeMillis();
|
||||||
d = _context.AESEngine().decrypt(e, key, iv);
|
_context.aes().decrypt(e, 0, d, 0, key, iv, d.length);
|
||||||
long enddecrypt = System.currentTimeMillis();
|
long enddecrypt = System.currentTimeMillis();
|
||||||
System.out.print(".");
|
System.out.print(".");
|
||||||
encrypttime += endencryptstartdecrypt - startencrypt;
|
encrypttime += endencryptstartdecrypt - startencrypt;
|
||||||
|
@ -145,8 +145,10 @@ class ElGamalAESEngineTest {
|
|||||||
String msg = "Hello world01234012345678901234501234567890123450123456789012345";
|
String msg = "Hello world01234012345678901234501234567890123450123456789012345";
|
||||||
h = SHA256Generator.getInstance().calculateHash(msg.getBytes());
|
h = SHA256Generator.getInstance().calculateHash(msg.getBytes());
|
||||||
_log.debug("Hash of entire aes block before encryption: \n" + DataHelper.toString(h.getData(), 32));
|
_log.debug("Hash of entire aes block before encryption: \n" + DataHelper.toString(h.getData(), 32));
|
||||||
byte aesEncr[] = _context.AESEngine().encrypt(msg.getBytes(), sessionKey, iv);
|
byte aesEncr[] = new byte[msg.getBytes().length];
|
||||||
byte aesDecr[] = _context.AESEngine().decrypt(aesEncr, sessionKey, iv);
|
byte aesDecr[] = new byte[aesEncr.length];
|
||||||
|
_context.aes().encrypt(msg.getBytes(), 0, aesEncr, 0, sessionKey, iv, aesEncr.length);
|
||||||
|
_context.aes().decrypt(aesEncr, 0, aesDecr, 0, sessionKey, iv, aesEncr.length);
|
||||||
h = SHA256Generator.getInstance().calculateHash(aesDecr);
|
h = SHA256Generator.getInstance().calculateHash(aesDecr);
|
||||||
_log.debug("Hash of entire aes block after decryption: \n" + DataHelper.toString(h.getData(), 32));
|
_log.debug("Hash of entire aes block after decryption: \n" + DataHelper.toString(h.getData(), 32));
|
||||||
if (msg.equals(new String(aesDecr))) {
|
if (msg.equals(new String(aesDecr))) {
|
||||||
|
@ -89,7 +89,7 @@ public class TunnelMessage extends I2NPMessageImpl {
|
|||||||
if ( (_tunnelId == null) || (_data == null) || (_data.length <= 0) )
|
if ( (_tunnelId == null) || (_data == null) || (_data.length <= 0) )
|
||||||
throw new I2NPMessageException("Not enough data to write out");
|
throw new I2NPMessageException("Not enough data to write out");
|
||||||
|
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream(4096);
|
ByteArrayOutputStream os = new ByteArrayOutputStream(64+_data.length);
|
||||||
try {
|
try {
|
||||||
_tunnelId.writeBytes(os);
|
_tunnelId.writeBytes(os);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
@ -60,6 +60,13 @@ public class InNetMessagePool {
|
|||||||
I2NPMessage messageBody = msg.getMessage();
|
I2NPMessage messageBody = msg.getMessage();
|
||||||
msg.processingComplete();
|
msg.processingComplete();
|
||||||
Date exp = messageBody.getMessageExpiration();
|
Date exp = messageBody.getMessageExpiration();
|
||||||
|
|
||||||
|
if (_log.shouldLog(Log.INFO))
|
||||||
|
_log.info("Received inbound "
|
||||||
|
+ " with id " + messageBody.getUniqueId()
|
||||||
|
+ " expiring on " + exp
|
||||||
|
+ " of type " + messageBody.getClass().getName());
|
||||||
|
|
||||||
boolean valid = _context.messageValidator().validateMessage(messageBody.getUniqueId(), exp.getTime());
|
boolean valid = _context.messageValidator().validateMessage(messageBody.getUniqueId(), exp.getTime());
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
@ -41,6 +41,13 @@ public class OutNetMessagePool {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void add(OutNetMessage msg) {
|
public void add(OutNetMessage msg) {
|
||||||
|
if (_log.shouldLog(Log.INFO))
|
||||||
|
_log.info("Adding outbound message to "
|
||||||
|
+ msg.getTarget().getIdentity().getHash().toBase64().substring(0,6)
|
||||||
|
+ " with id " + msg.getMessage().getUniqueId()
|
||||||
|
+ " expiring on " + msg.getMessage().getMessageExpiration()
|
||||||
|
+ " of type " + msg.getMessageType());
|
||||||
|
|
||||||
boolean valid = validate(msg);
|
boolean valid = validate(msg);
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
MessageSelector selector = msg.getReplySelector();
|
MessageSelector selector = msg.getReplySelector();
|
||||||
|
@ -415,7 +415,7 @@ public class HandleTunnelMessageJob extends JobImpl {
|
|||||||
byte iv[] = new byte[16];
|
byte iv[] = new byte[16];
|
||||||
Hash h = getContext().sha().calculateHash(key.getData());
|
Hash h = getContext().sha().calculateHash(key.getData());
|
||||||
System.arraycopy(h.getData(), 0, iv, 0, iv.length);
|
System.arraycopy(h.getData(), 0, iv, 0, iv.length);
|
||||||
byte decrypted[] = getContext().AESEngine().safeDecrypt(encryptedMessage, key, iv);
|
byte decrypted[] = getContext().aes().safeDecrypt(encryptedMessage, key, iv);
|
||||||
if (decrypted == null) {
|
if (decrypted == null) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Error decrypting the message", getAddedBy());
|
_log.error("Error decrypting the message", getAddedBy());
|
||||||
@ -429,7 +429,7 @@ public class HandleTunnelMessageJob extends JobImpl {
|
|||||||
byte iv[] = new byte[16];
|
byte iv[] = new byte[16];
|
||||||
Hash h = getContext().sha().calculateHash(key.getData());
|
Hash h = getContext().sha().calculateHash(key.getData());
|
||||||
System.arraycopy(h.getData(), 0, iv, 0, iv.length);
|
System.arraycopy(h.getData(), 0, iv, 0, iv.length);
|
||||||
byte decrypted[] = getContext().AESEngine().safeDecrypt(encryptedInstructions, key, iv);
|
byte decrypted[] = getContext().aes().safeDecrypt(encryptedInstructions, key, iv);
|
||||||
if (decrypted == null) {
|
if (decrypted == null) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Error decrypting the instructions", getAddedBy());
|
_log.error("Error decrypting the instructions", getAddedBy());
|
||||||
|
@ -396,7 +396,7 @@ public class SendTunnelMessageJob extends JobImpl {
|
|||||||
byte iv[] = new byte[16];
|
byte iv[] = new byte[16];
|
||||||
Hash h = getContext().sha().calculateHash(key.getData());
|
Hash h = getContext().sha().calculateHash(key.getData());
|
||||||
System.arraycopy(h.getData(), 0, iv, 0, iv.length);
|
System.arraycopy(h.getData(), 0, iv, 0, iv.length);
|
||||||
return getContext().AESEngine().safeEncrypt(baos.toByteArray(), key, iv, paddedSize);
|
return getContext().aes().safeEncrypt(baos.toByteArray(), key, iv, paddedSize);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Error writing out data to encrypt", ioe);
|
_log.error("Error writing out data to encrypt", ioe);
|
||||||
|
@ -307,8 +307,8 @@ public class ConnectionBuilder {
|
|||||||
byte pre[] = new byte[48];
|
byte pre[] = new byte[48];
|
||||||
System.arraycopy(_nonce.getData(), 0, pre, 0, 4);
|
System.arraycopy(_nonce.getData(), 0, pre, 0, 4);
|
||||||
System.arraycopy(_connectionTag.getData(), 0, pre, 4, 32);
|
System.arraycopy(_connectionTag.getData(), 0, pre, 4, 32);
|
||||||
byte encr[] = _context.AESEngine().encrypt(pre, _key, _iv);
|
_context.aes().encrypt(pre, 0, pre, 0, _key, _iv, pre.length);
|
||||||
Hash h = _context.sha().calculateHash(encr);
|
Hash h = _context.sha().calculateHash(pre);
|
||||||
_nextConnectionTag = new ByteArray(h.getData());
|
_nextConnectionTag = new ByteArray(h.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,7 +638,9 @@ public class ConnectionBuilder {
|
|||||||
private void establishComplete() {
|
private void establishComplete() {
|
||||||
_connectionIn = new BandwidthLimitedInputStream(_context, _rawIn, _actualPeer.getIdentity());
|
_connectionIn = new BandwidthLimitedInputStream(_context, _rawIn, _actualPeer.getIdentity());
|
||||||
OutputStream blos = new BandwidthLimitedOutputStream(_context, _rawOut, _actualPeer.getIdentity());
|
OutputStream blos = new BandwidthLimitedOutputStream(_context, _rawOut, _actualPeer.getIdentity());
|
||||||
_connectionOut = blos;
|
_connectionOut = blos;
|
||||||
|
//_connectionIn = _rawIn;
|
||||||
|
//_connectionOut = _rawOut;
|
||||||
|
|
||||||
Hash peer = _actualPeer.getIdentity().getHash();
|
Hash peer = _actualPeer.getIdentity().getHash();
|
||||||
_context.netDb().store(peer, _actualPeer);
|
_context.netDb().store(peer, _actualPeer);
|
||||||
|
@ -328,8 +328,8 @@ public class ConnectionHandler {
|
|||||||
byte pre[] = new byte[48];
|
byte pre[] = new byte[48];
|
||||||
System.arraycopy(_nonce.getData(), 0, pre, 0, 4);
|
System.arraycopy(_nonce.getData(), 0, pre, 0, 4);
|
||||||
System.arraycopy(_connectionTag.getData(), 0, pre, 4, 32);
|
System.arraycopy(_connectionTag.getData(), 0, pre, 4, 32);
|
||||||
byte encr[] = _context.AESEngine().encrypt(pre, _key, _iv);
|
_context.aes().encrypt(pre, 0, pre, 0, _key, _iv, pre.length);
|
||||||
Hash h = _context.sha().calculateHash(encr);
|
Hash h = _context.sha().calculateHash(pre);
|
||||||
_nextConnectionTag = new ByteArray(h.getData());
|
_nextConnectionTag = new ByteArray(h.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -804,6 +804,8 @@ public class ConnectionHandler {
|
|||||||
_connectionIn = new BandwidthLimitedInputStream(_context, _rawIn, _actualPeer.getIdentity());
|
_connectionIn = new BandwidthLimitedInputStream(_context, _rawIn, _actualPeer.getIdentity());
|
||||||
OutputStream blos = new BandwidthLimitedOutputStream(_context, _rawOut, _actualPeer.getIdentity());
|
OutputStream blos = new BandwidthLimitedOutputStream(_context, _rawOut, _actualPeer.getIdentity());
|
||||||
_connectionOut = blos;
|
_connectionOut = blos;
|
||||||
|
//_connectionIn = _rawIn;
|
||||||
|
//_connectionOut = _rawOut;
|
||||||
|
|
||||||
Hash peer = _actualPeer.getIdentity().getHash();
|
Hash peer = _actualPeer.getIdentity().getHash();
|
||||||
_context.netDb().store(peer, _actualPeer);
|
_context.netDb().store(peer, _actualPeer);
|
||||||
|
@ -74,6 +74,11 @@ class ConnectionRunner implements Runnable {
|
|||||||
out.flush();
|
out.flush();
|
||||||
after = _context.clock().now();
|
after = _context.clock().now();
|
||||||
}
|
}
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("Just sent message " + msg.getMessageId() + " to "
|
||||||
|
+ msg.getTarget().getIdentity().getHash().toBase64().substring(0,6)
|
||||||
|
+ " writeTime = " + (after-before) +"ms"
|
||||||
|
+ " lifetime = " + msg.getLifetime() + "ms");
|
||||||
|
|
||||||
ok = true;
|
ok = true;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
|
@ -4,12 +4,14 @@ import net.i2p.data.Hash;
|
|||||||
import net.i2p.data.RouterIdentity;
|
import net.i2p.data.RouterIdentity;
|
||||||
import net.i2p.data.i2np.I2NPMessageReader;
|
import net.i2p.data.i2np.I2NPMessageReader;
|
||||||
import net.i2p.data.i2np.I2NPMessage;
|
import net.i2p.data.i2np.I2NPMessage;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receive messages from a message reader and bounce them off to the transport
|
* Receive messages from a message reader and bounce them off to the transport
|
||||||
* for further enqueueing.
|
* for further enqueueing.
|
||||||
*/
|
*/
|
||||||
public class MessageHandler implements I2NPMessageReader.I2NPMessageEventListener {
|
public class MessageHandler implements I2NPMessageReader.I2NPMessageEventListener {
|
||||||
|
private Log _log;
|
||||||
private TCPTransport _transport;
|
private TCPTransport _transport;
|
||||||
private TCPConnection _con;
|
private TCPConnection _con;
|
||||||
private RouterIdentity _ident;
|
private RouterIdentity _ident;
|
||||||
@ -20,6 +22,7 @@ public class MessageHandler implements I2NPMessageReader.I2NPMessageEventListene
|
|||||||
_con = con;
|
_con = con;
|
||||||
_ident = con.getRemoteRouterIdentity();
|
_ident = con.getRemoteRouterIdentity();
|
||||||
_identHash = _ident.calculateHash();
|
_identHash = _ident.calculateHash();
|
||||||
|
_log = con.getRouterContext().logManager().getLog(MessageHandler.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnected(I2NPMessageReader reader) {
|
public void disconnected(I2NPMessageReader reader) {
|
||||||
@ -27,6 +30,10 @@ public class MessageHandler implements I2NPMessageReader.I2NPMessageEventListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void messageReceived(I2NPMessageReader reader, I2NPMessage message, long msToRead) {
|
public void messageReceived(I2NPMessageReader reader, I2NPMessage message, long msToRead) {
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("Just received message " + message.getUniqueId() + " from "
|
||||||
|
+ _identHash.toBase64().substring(0,6)
|
||||||
|
+ " readTime = " + msToRead + "ms type = " + message.getClass().getName());
|
||||||
_transport.messageReceived(message, _ident, _identHash, msToRead, message.getSize());
|
_transport.messageReceived(message, _ident, _identHash, msToRead, message.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +202,7 @@ public class TCPConnection {
|
|||||||
|
|
||||||
/** Have we been closed already? */
|
/** Have we been closed already? */
|
||||||
boolean getIsClosed() { return _closed; }
|
boolean getIsClosed() { return _closed; }
|
||||||
|
RouterContext getRouterContext() { return _context; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The message was sent.
|
* The message was sent.
|
||||||
|
Reference in New Issue
Block a user