diff --git a/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java b/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java index 2297ae25298d164bea5854dccb8557531a3b0112..3dc56bed55a4ce56095f3b0d1f1e42e786143217 100644 --- a/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java +++ b/router/java/src/com/southernstorm/noise/protocol/HandshakeState.java @@ -136,6 +136,8 @@ public class HandshakeState implements Destroyable, Cloneable { public static final String PATTERN_ID_XK = "XK"; public static final String PATTERN_ID_IK = "IK"; public static final String PATTERN_ID_N = "N"; + /** same as N but no post-mixHash needed */ + public static final String PATTERN_ID_N_NO_RESPONSE = "N!"; private static String dh; private static final String cipher; private static final String hash; @@ -205,6 +207,8 @@ public class HandshakeState implements Destroyable, Cloneable { pattern = PATTERN_IK; else if (patternId.equals(PATTERN_ID_N)) pattern = PATTERN_N; + else if (patternId.equals(PATTERN_ID_N_NO_RESPONSE)) // same as N but no post-mixHash needed + pattern = PATTERN_N; else throw new IllegalArgumentException("Handshake pattern is not recognized"); short flags = pattern[0]; @@ -650,13 +654,13 @@ public class HandshakeState implements Destroyable, Cloneable { // Add the payload to the message buffer and encrypt it. if (payload != null) { // no need to hash for N, we don't split() and no more messages follow - if (patternId.equals(PATTERN_ID_N)) + if (patternId.equals(PATTERN_ID_N_NO_RESPONSE)) messagePosn += symmetric.encryptOnly(payload, payloadOffset, message, messagePosn, payloadLength); else messagePosn += symmetric.encryptAndHash(payload, payloadOffset, message, messagePosn, payloadLength); } else { // no need to hash for N, we don't split() and no more messages follow - if (patternId.equals(PATTERN_ID_N)) + if (patternId.equals(PATTERN_ID_N_NO_RESPONSE)) messagePosn += symmetric.encryptOnly(message, messagePosn, message, messagePosn, 0); else messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, 0); @@ -830,7 +834,7 @@ public class HandshakeState implements Destroyable, Cloneable { // Decrypt the message payload. int payloadLength; // no need to hash for N, we don't split() and no more messages follow - if (patternId.equals(PATTERN_ID_N)) + if (patternId.equals(PATTERN_ID_N_NO_RESPONSE)) payloadLength = symmetric.decryptOnly(message, messageOffset, payload, payloadOffset, messageEnd - messageOffset); else payloadLength = symmetric.decryptAndHash(message, messageOffset, payload, payloadOffset, messageEnd - messageOffset); diff --git a/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java b/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java index 4c7f09ee5fee9bd1e38f96bc0f278a0ecf38e2f8..4e17269656199e5c9e2e64bf7630e63a3b87196e 100644 --- a/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java +++ b/router/java/src/com/southernstorm/noise/protocol/SymmetricState.java @@ -121,7 +121,8 @@ class SymmetricState implements Destroyable, Cloneable { } else if (patternId.equals(HandshakeState.PATTERN_ID_IK)) { initCK = INIT_CK_IK; initHash = INIT_HASH_IK; - } else if (patternId.equals(HandshakeState.PATTERN_ID_N)) { + } else if (patternId.equals(HandshakeState.PATTERN_ID_N) || + patternId.equals(HandshakeState.PATTERN_ID_N_NO_RESPONSE)) { initCK = INIT_CK_N; initHash = INIT_HASH_N; } else { diff --git a/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java b/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java index 133e8c4cf7d4e74fbb7d7d9c044fcb7f90807753..c57d22f72d21d438df4b2b2edfbf14b82d19ef88 100644 --- a/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java +++ b/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java @@ -503,7 +503,7 @@ public final class ECIESAEADEngine { HandshakeState state; try { - state = new HandshakeState(HandshakeState.PATTERN_ID_N, HandshakeState.RESPONDER, _context.commSystem().getXDHFactory()); + state = new HandshakeState(HandshakeState.PATTERN_ID_N_NO_RESPONSE, HandshakeState.RESPONDER, _context.commSystem().getXDHFactory()); } catch (GeneralSecurityException gse) { throw new IllegalStateException("bad proto", gse); } @@ -1009,7 +1009,7 @@ public final class ECIESAEADEngine { private byte[] encryptNewSession(CloveSet cloves, PublicKey target) { HandshakeState state; try { - state = new HandshakeState(HandshakeState.PATTERN_ID_N, HandshakeState.INITIATOR, _context.commSystem().getXDHFactory()); + state = new HandshakeState(HandshakeState.PATTERN_ID_N_NO_RESPONSE, HandshakeState.INITIATOR, _context.commSystem().getXDHFactory()); } catch (GeneralSecurityException gse) { throw new IllegalStateException("bad proto", gse); }