From d301669726b7c446de13e159a723d57a1c9f238c Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 15 Oct 2020 11:01:22 +0000 Subject: [PATCH] Router: Don't re-derive public key from private for every HandshakeState --- .../noise/protocol/Curve25519DHState.java | 23 +++++++++++++++++++ .../southernstorm/noise/protocol/DHState.java | 17 ++++++++++++++ .../net/i2p/data/i2np/BuildRequestRecord.java | 4 ++-- .../crypto/ratchet/ECIESAEADEngine.java | 8 +++---- .../transport/ntcp/InboundEstablishState.java | 4 ++-- .../transport/ntcp/OutboundNTCP2State.java | 4 ++-- 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/router/java/src/com/southernstorm/noise/protocol/Curve25519DHState.java b/router/java/src/com/southernstorm/noise/protocol/Curve25519DHState.java index 62524153ac..1a3d7fb014 100644 --- a/router/java/src/com/southernstorm/noise/protocol/Curve25519DHState.java +++ b/router/java/src/com/southernstorm/noise/protocol/Curve25519DHState.java @@ -107,12 +107,35 @@ class Curve25519DHState implements DHState, Cloneable { System.arraycopy(privateKey, 0, key, offset, 32); } + /** + * @deprecated use setKeys() + */ + @Deprecated @Override public void setPrivateKey(byte[] key, int offset) { System.arraycopy(key, offset, privateKey, 0, 32); Curve25519.eval(publicKey, 0, privateKey, null); mode = 0x03; } + + /** + * Sets the private and public keys for this object. + * I2P for efficiency, since setPrivateKey() calculates the public key + * and overwrites it. + * Does NOT check that the two keys match. + * + * @param privkey The buffer containing the private key. + * @param privoffset The first offset in the buffer that contains the key. + * @param pubkey The buffer containing the public key. + * @param puboffset The first offset in the buffer that contains the key. + * @since 0.9.48 + */ + @Override + public void setKeys(byte[] privkey, int privoffset, byte[] pubkey, int puboffset) { + System.arraycopy(privkey, privoffset, privateKey, 0, 32); + System.arraycopy(pubkey, puboffset, publicKey, 0, 32); + mode = 0x03; + } @Override public void setToNullPublicKey() { diff --git a/router/java/src/com/southernstorm/noise/protocol/DHState.java b/router/java/src/com/southernstorm/noise/protocol/DHState.java index a3a9cdef5b..62b135a3f7 100644 --- a/router/java/src/com/southernstorm/noise/protocol/DHState.java +++ b/router/java/src/com/southernstorm/noise/protocol/DHState.java @@ -95,8 +95,25 @@ public interface DHState extends Destroyable, Cloneable { * * If this object previously held only a public key, then * this function will change it into a key pair. + * + * @deprecated use setKeys() */ + @Deprecated void setPrivateKey(byte[] key, int offset); + + /** + * Sets the private and public keys for this object. + * I2P for efficiency, since setPrivateKey() calculates the public key + * and overwrites it. + * Does NOT check that the two keys match. + * + * @param privkey The buffer containing the private key. + * @param privoffset The first offset in the buffer that contains the key. + * @param pubkey The buffer containing the private key. + * @param puboffset The first offset in the buffer that contains the key. + * @since 0.9.48 + */ + void setKeys(byte[] privkey, int privoffset, byte[] pubkey, int puboffset); /** * Sets this object to the null public key and clears the private key. diff --git a/router/java/src/net/i2p/data/i2np/BuildRequestRecord.java b/router/java/src/net/i2p/data/i2np/BuildRequestRecord.java index bd5085667f..48ed6b717a 100644 --- a/router/java/src/net/i2p/data/i2np/BuildRequestRecord.java +++ b/router/java/src/net/i2p/data/i2np/BuildRequestRecord.java @@ -380,8 +380,8 @@ public class BuildRequestRecord { try { KeyFactory kf = TEST ? TESTKF : ctx.commSystem().getXDHFactory(); state = new HandshakeState(HandshakeState.PATTERN_ID_N, HandshakeState.RESPONDER, kf); - state.getLocalKeyPair().setPublicKey(ourKey.toPublic().getData(), 0); - state.getLocalKeyPair().setPrivateKey(ourKey.getData(), 0); + state.getLocalKeyPair().setKeys(ourKey.getData(), 0, + ourKey.toPublic().getData(), 0); state.start(); decrypted = new byte[LENGTH_EC]; state.readMessage(encryptedRecord.getData(), PEER_SIZE, EncryptedBuildRecord.LENGTH - PEER_SIZE, 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 56183161cf..36bd14da41 100644 --- a/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java +++ b/router/java/src/net/i2p/router/crypto/ratchet/ECIESAEADEngine.java @@ -356,8 +356,8 @@ public final class ECIESAEADEngine { } catch (GeneralSecurityException gse) { throw new IllegalStateException("bad proto", gse); } - state.getLocalKeyPair().setPublicKey(targetPrivateKey.toPublic().getData(), 0); - state.getLocalKeyPair().setPrivateKey(targetPrivateKey.getData(), 0); + state.getLocalKeyPair().setKeys(targetPrivateKey.getData(), 0, + targetPrivateKey.toPublic().getData(), 0); state.start(); if (_log.shouldDebug()) _log.debug("State before decrypt new session: " + state); @@ -786,8 +786,8 @@ public final class ECIESAEADEngine { throw new IllegalStateException("bad proto", gse); } state.getRemotePublicKey().setPublicKey(target.getData(), 0); - state.getLocalKeyPair().setPublicKey(priv.toPublic().getData(), 0); - state.getLocalKeyPair().setPrivateKey(priv.getData(), 0); + state.getLocalKeyPair().setKeys(priv.getData(), 0, + priv.toPublic().getData(), 0); state.start(); if (_log.shouldDebug()) _log.debug("State before encrypt new session: " + state); diff --git a/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java b/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java index b7d0d6f990..1bd397cc04 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java @@ -685,8 +685,8 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa } catch (GeneralSecurityException gse) { throw new IllegalStateException("bad proto", gse); } - _handshakeState.getLocalKeyPair().setPublicKey(_transport.getNTCP2StaticPubkey(), 0); - _handshakeState.getLocalKeyPair().setPrivateKey(_transport.getNTCP2StaticPrivkey(), 0); + _handshakeState.getLocalKeyPair().setKeys(_transport.getNTCP2StaticPrivkey(), 0, + _transport.getNTCP2StaticPubkey(), 0); Hash h = _context.routerHash(); SessionKey bobHash = new SessionKey(h.getData()); // save encrypted data for CBC for msg 2 diff --git a/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java b/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java index be1f9c8908..7ecc42a0d7 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java +++ b/router/java/src/net/i2p/router/transport/ntcp/OutboundNTCP2State.java @@ -217,8 +217,8 @@ class OutboundNTCP2State implements EstablishState { return; } _handshakeState.getRemotePublicKey().setPublicKey(bk, 0); - _handshakeState.getLocalKeyPair().setPublicKey(_transport.getNTCP2StaticPubkey(), 0); - _handshakeState.getLocalKeyPair().setPrivateKey(_transport.getNTCP2StaticPrivkey(), 0); + _handshakeState.getLocalKeyPair().setKeys(_transport.getNTCP2StaticPrivkey(), 0, + _transport.getNTCP2StaticPubkey(), 0); // output to _tmp try { _handshakeState.start(); -- GitLab