diff --git a/router/doc/tunnel.html b/router/doc/tunnel.html index 6b7ec90a9f12f982d0fa73cff25a5293888e5750..102ccdedce98b81916caa7f4f58bcef7b87c8301 100644 --- a/router/doc/tunnel.html +++ b/router/doc/tunnel.html @@ -1,4 +1,4 @@ -<code>$Id: tunnel.html,v 1.3 2005/01/12 14:22:40 jrandom Exp $</code> +<code>$Id: tunnel.html,v 1.4 2005/01/12 19:57:36 jrandom Exp $</code> <pre> 1) <a href="#tunnel.overview">Tunnel overview</a> 2) <a href="#tunnel.operation">Tunnel operation</a> @@ -248,9 +248,9 @@ for certain whether any of the checksum blocks have been tagged, as that would corrupt the verification block (V[7]).</p> <p>The IV[0] is a random 16 byte value, and IV[i] is the first 16 bytes of -H(D(IV[i-1], K[i-1])). We don't use the same IV along the path, as that would +H(D(IV[i-1], K[i-1]) xor IV_WHITENER). We don't use the same IV along the path, as that would allow trivial collusion, and we use the hash of the decrypted value to propogate -the IV so as to hamper key leakage.</p> +the IV so as to hamper key leakage. IV_WHITENER is a fixed 16 byte value.</p> <p>When the gateway wants to send the message, they export the right row for the peer who is the first hop (usually the peer1.recv row) and forward that entirely.</p> diff --git a/router/java/src/net/i2p/router/tunnel/GatewayMessage.java b/router/java/src/net/i2p/router/tunnel/GatewayMessage.java index 62d4a46a286201e9a477592b761b7a1bceb1b45f..12f122afac41f155b8b7d13fa6245bb306e16602 100644 --- a/router/java/src/net/i2p/router/tunnel/GatewayMessage.java +++ b/router/java/src/net/i2p/router/tunnel/GatewayMessage.java @@ -54,6 +54,12 @@ public class GatewayMessage { private static final int COLUMNS = HOPS; private static final int HASH_ROWS = HOPS; + /** used to munge the IV during per-hop translations */ + static final byte IV_WHITENER[] = new byte[] { (byte)0x31, (byte)0xd6, (byte)0x74, (byte)0x17, + (byte)0xa0, (byte)0xb6, (byte)0x28, (byte)0xed, + (byte)0xdf, (byte)0xee, (byte)0x5b, (byte)0x86, + (byte)0x74, (byte)0x61, (byte)0x50, (byte)0x7d }; + public GatewayMessage(I2PAppContext ctx) { _context = ctx; _log = ctx.logManager().getLog(GatewayMessage.class); @@ -135,6 +141,7 @@ public class GatewayMessage { // decrypt, since we're simulating what the participants do _context.aes().decryptBlock(_iv[i-1], 0, key, _iv[i], 0); + DataHelper.xor(_iv[i], 0, IV_WHITENER, 0, _iv[i], 0, IV_SIZE); Hash h = _context.sha().calculateHash(_iv[i]); System.arraycopy(h.getData(), 0, _iv[i], 0, IV_SIZE); } diff --git a/router/java/src/net/i2p/router/tunnel/TunnelMessageProcessor.java b/router/java/src/net/i2p/router/tunnel/TunnelMessageProcessor.java index e6153c2b6caaa0b48f63439a1fdaf3996e34e934..f6ef511dd29f9df3ccd5aa8810c494b8ddb9633a 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelMessageProcessor.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelMessageProcessor.java @@ -87,7 +87,9 @@ public class TunnelMessageProcessor { } // update the IV for the next layer + ctx.aes().decryptBlock(data, 0, layerKey, data, 0); + DataHelper.xor(data, 0, GatewayMessage.IV_WHITENER, 0, data, 0, IV_SIZE); Hash h = ctx.sha().calculateHash(data, 0, IV_SIZE); System.arraycopy(h.getData(), 0, data, 0, IV_SIZE);