diff --git a/libaxolotl/protobuf/LocalStorageProtocol.proto b/libaxolotl/protobuf/LocalStorageProtocol.proto index e3facdfb7c..6b4d6104f1 100644 --- a/libaxolotl/protobuf/LocalStorageProtocol.proto +++ b/libaxolotl/protobuf/LocalStorageProtocol.proto @@ -5,8 +5,8 @@ option java_outer_classname = "StorageProtos"; message SessionStructure { message Chain { - optional bytes senderEphemeral = 1; - optional bytes senderEphemeralPrivate = 2; + optional bytes senderRatchetKey = 1; + optional bytes senderRatchetKeyPrivate = 2; message ChainKey { optional uint32 index = 1; @@ -28,8 +28,8 @@ message SessionStructure { optional uint32 sequence = 1; optional bytes localBaseKey = 2; optional bytes localBaseKeyPrivate = 3; - optional bytes localEphemeralKey = 4; - optional bytes localEphemeralKeyPrivate = 5; + optional bytes localRatchetKey = 4; + optional bytes localRatchetKeyPrivate = 5; optional bytes localIdentityKey = 7; optional bytes localIdentityKeyPrivate = 8; } diff --git a/libaxolotl/protobuf/WhisperTextProtocol.proto b/libaxolotl/protobuf/WhisperTextProtocol.proto index 3a6420ee86..93d19f0de7 100644 --- a/libaxolotl/protobuf/WhisperTextProtocol.proto +++ b/libaxolotl/protobuf/WhisperTextProtocol.proto @@ -4,7 +4,7 @@ option java_package = "org.whispersystems.libaxolotl.protocol"; option java_outer_classname = "WhisperProtos"; message WhisperMessage { - optional bytes ephemeralKey = 1; + optional bytes ratchetKey = 1; optional uint32 counter = 2; optional uint32 previousCounter = 3; optional bytes ciphertext = 4; @@ -23,8 +23,7 @@ message PreKeyWhisperMessage { message KeyExchangeMessage { optional uint32 id = 1; optional bytes baseKey = 2; - optional bytes ephemeralKey = 3; + optional bytes ratchetKey = 3; optional bytes identityKey = 4; optional bytes baseKeySignature = 5; - optional bytes verification = 6; } \ No newline at end of file diff --git a/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java b/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java index 1859c4e8ea..0f43f83895 100644 --- a/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java +++ b/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java @@ -154,7 +154,8 @@ public class SessionBuilderTest extends AndroidTestCase { PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1, 31337, bobPreKeyPair.getPublicKey(), - 22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, + 22, bobSignedPreKeyPair.getPublicKey(), + bobSignedPreKeySignature, bobIdentityKeyStore.getIdentityKeyPair().getPublicKey()); aliceSessionBuilder.process(bobPreKey); diff --git a/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java b/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java index f8780fb279..cad3ddfdd0 100644 --- a/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java +++ b/libaxolotl/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java @@ -15,6 +15,8 @@ import org.whispersystems.libaxolotl.ecc.ECKeyPair; import org.whispersystems.libaxolotl.ecc.ECPublicKey; import org.whispersystems.libaxolotl.protocol.CiphertextMessage; import org.whispersystems.libaxolotl.protocol.WhisperMessage; +import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters; +import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters; import org.whispersystems.libaxolotl.ratchet.RatchetingSession; import org.whispersystems.libaxolotl.state.IdentityKeyStore; import org.whispersystems.libaxolotl.state.PreKeyStore; @@ -31,7 +33,6 @@ import java.util.Collections; import java.util.List; import java.util.Random; -import static org.whispersystems.libaxolotl.ratchet.RatchetingSession.AxolotlParameters; public class SessionCipherTest extends AndroidTestCase { @@ -149,30 +150,23 @@ public class SessionCipherTest extends AndroidTestCase { ECKeyPair bobBaseKey = Curve.generateKeyPair(true); ECKeyPair bobEphemeralKey = bobBaseKey; - AxolotlParameters aliceParameters = - AxolotlParameters.newBuilder() - .setOurIdentityKey(aliceIdentityKey) - .setOurBaseKey(aliceBaseKey) - .setOurEphemeralKey(aliceEphemeralKey) - .setOurPreKey(Optional.absent()) - .setTheirIdentityKey(bobIdentityKey.getPublicKey()) - .setTheirBaseKey(bobBaseKey.getPublicKey()) - .setTheirEphemeralKey(bobEphemeralKey.getPublicKey()) - .setTheirPreKey(Optional.absent()) - .create(); - - AxolotlParameters bobParameters = - RatchetingSession.AxolotlParameters.newBuilder() - .setOurIdentityKey(bobIdentityKey) - .setOurBaseKey(bobBaseKey) - .setOurEphemeralKey(bobEphemeralKey) - .setOurPreKey(Optional.absent()) - .setTheirIdentityKey(aliceIdentityKey.getPublicKey()) - .setTheirBaseKey(aliceBaseKey.getPublicKey()) - .setTheirEphemeralKey(aliceEphemeralKey.getPublicKey()) - .setTheirPreKey(Optional.absent()) - .create(); + AliceAxolotlParameters aliceParameters = AliceAxolotlParameters.newBuilder() + .setOurIdentityKey(aliceIdentityKey) + .setOurBaseKey(aliceBaseKey) + .setTheirIdentityKey(bobIdentityKey.getPublicKey()) + .setTheirSignedPreKey(bobEphemeralKey.getPublicKey()) + .setTheirRatchetKey(bobEphemeralKey.getPublicKey()) + .setTheirOneTimePreKey(Optional.absent()) + .create(); + BobAxolotlParameters bobParameters = BobAxolotlParameters.newBuilder() + .setOurIdentityKey(bobIdentityKey) + .setOurOneTimePreKey(Optional.absent()) + .setOurRatchetKey(bobEphemeralKey) + .setOurSignedPreKey(bobBaseKey) + .setTheirBaseKey(aliceBaseKey.getPublicKey()) + .setTheirIdentityKey(aliceIdentityKey.getPublicKey()) + .create(); RatchetingSession.initializeSession(aliceSessionState, 2, aliceParameters); RatchetingSession.initializeSession(bobSessionState, 2, bobParameters); @@ -197,33 +191,25 @@ public class SessionCipherTest extends AndroidTestCase { ECKeyPair bobPreKey = Curve.generateKeyPair(true); - AxolotlParameters aliceParameters = - AxolotlParameters.newBuilder() - .setOurIdentityKey(aliceIdentityKey) - .setOurBaseKey(aliceBaseKey) - .setOurEphemeralKey(aliceEphemeralKey) - .setOurPreKey(Optional.of(alicePreKey)) - .setTheirIdentityKey(bobIdentityKey.getPublicKey()) - .setTheirBaseKey(bobBaseKey.getPublicKey()) - .setTheirEphemeralKey(bobEphemeralKey.getPublicKey()) - .setTheirPreKey(Optional.of(bobPreKey.getPublicKey())) - .create(); - - AxolotlParameters bobParameters = - AxolotlParameters.newBuilder() - .setOurIdentityKey(bobIdentityKey) - .setOurBaseKey(bobBaseKey) - .setOurEphemeralKey(bobEphemeralKey) - .setOurPreKey(Optional.of(bobPreKey)) - .setTheirIdentityKey(aliceIdentityKey.getPublicKey()) - .setTheirBaseKey(aliceBaseKey.getPublicKey()) - .setTheirEphemeralKey(aliceEphemeralKey.getPublicKey()) - .setTheirPreKey(Optional.of(alicePreKey.getPublicKey())) - .create(); + AliceAxolotlParameters aliceParameters = AliceAxolotlParameters.newBuilder() + .setOurBaseKey(aliceBaseKey) + .setOurIdentityKey(aliceIdentityKey) + .setTheirOneTimePreKey(Optional.absent()) + .setTheirRatchetKey(bobEphemeralKey.getPublicKey()) + .setTheirSignedPreKey(bobBaseKey.getPublicKey()) + .setTheirIdentityKey(bobIdentityKey.getPublicKey()) + .create(); + BobAxolotlParameters bobParameters = BobAxolotlParameters.newBuilder() + .setOurRatchetKey(bobEphemeralKey) + .setOurSignedPreKey(bobBaseKey) + .setOurOneTimePreKey(Optional.absent()) + .setOurIdentityKey(bobIdentityKey) + .setTheirIdentityKey(aliceIdentityKey.getPublicKey()) + .setTheirBaseKey(aliceBaseKey.getPublicKey()) + .create(); RatchetingSession.initializeSession(aliceSessionState, 3, aliceParameters); RatchetingSession.initializeSession(bobSessionState, 3, bobParameters); - } } diff --git a/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java b/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java index 7752635d47..48f7bc64e4 100644 --- a/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java +++ b/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java @@ -9,14 +9,14 @@ import org.whispersystems.libaxolotl.ecc.Curve; import org.whispersystems.libaxolotl.ecc.ECKeyPair; import org.whispersystems.libaxolotl.ecc.ECPrivateKey; import org.whispersystems.libaxolotl.ecc.ECPublicKey; +import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters; +import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters; import org.whispersystems.libaxolotl.ratchet.RatchetingSession; import org.whispersystems.libaxolotl.state.SessionState; import org.whispersystems.libaxolotl.util.guava.Optional; import java.util.Arrays; -import static org.whispersystems.libaxolotl.ratchet.RatchetingSession.AxolotlParameters; - public class RatchetingSessionTest extends AndroidTestCase { public void testRatchetingSessionAsBob() throws InvalidKeyException { @@ -108,20 +108,17 @@ public class RatchetingSessionTest extends AndroidTestCase { ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0); IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0); - AxolotlParameters parameters = AxolotlParameters.newBuilder() - .setOurBaseKey(bobBaseKey) - .setOurEphemeralKey(bobEphemeralKey) - .setOurIdentityKey(bobIdentityKey) - .setOurPreKey(Optional.absent()) - .setTheirBaseKey(aliceBasePublicKey) - .setTheirEphemeralKey(aliceEphemeralPublicKey) - .setTheirIdentityKey(aliceIdentityPublicKey) - .setTheirPreKey(Optional.absent()) - .create(); + BobAxolotlParameters parameters = BobAxolotlParameters.newBuilder() + .setOurIdentityKey(bobIdentityKey) + .setOurSignedPreKey(bobBaseKey) + .setOurRatchetKey(bobEphemeralKey) + .setOurOneTimePreKey(Optional.absent()) + .setTheirIdentityKey(aliceIdentityPublicKey) + .setTheirBaseKey(aliceBasePublicKey) + .create(); SessionState session = new SessionState(); - RatchetingSession.initializeSession(session, 2, parameters); assertTrue(session.getLocalIdentityKey().equals(bobIdentityKey.getPublicKey())); @@ -217,16 +214,14 @@ public class RatchetingSessionTest extends AndroidTestCase { SessionState session = new SessionState(); - AxolotlParameters parameters = AxolotlParameters.newBuilder() - .setOurBaseKey(aliceBaseKey) - .setOurEphemeralKey(aliceEphemeralKey) - .setOurIdentityKey(aliceIdentityKey) - .setOurPreKey(Optional.absent()) - .setTheirBaseKey(bobBasePublicKey) - .setTheirEphemeralKey(bobEphemeralPublicKey) - .setTheirIdentityKey(bobIdentityKey) - .setTheirPreKey(Optional.absent()) - .create(); + AliceAxolotlParameters parameters = AliceAxolotlParameters.newBuilder() + .setOurBaseKey(aliceBaseKey) + .setOurIdentityKey(aliceIdentityKey) + .setTheirIdentityKey(bobIdentityKey) + .setTheirSignedPreKey(bobBasePublicKey) + .setTheirRatchetKey(bobEphemeralPublicKey) + .setTheirOneTimePreKey(Optional.absent()) + .create(); RatchetingSession.initializeSession(session, 2, parameters); diff --git a/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/VerifyKeyTest.java b/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/VerifyKeyTest.java index 11495e2ff6..d8be991d64 100644 --- a/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/VerifyKeyTest.java +++ b/libaxolotl/src/androidTest/java/org/whispersystems/test/ratchet/VerifyKeyTest.java @@ -3,6 +3,7 @@ package org.whispersystems.test.ratchet; import android.test.AndroidTestCase; import android.util.Log; +import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.InvalidKeyException; import org.whispersystems.libaxolotl.ecc.Curve; import org.whispersystems.libaxolotl.ecc.ECPublicKey; @@ -65,8 +66,8 @@ public class VerifyKeyTest extends AndroidTestCase { (byte)0x79, (byte)0x00, (byte)0xef, (byte)0x1b, (byte)0x40, (byte)0x0f, (byte)0xdc}; - byte[] expectedTag = {(byte)0x2f, (byte)0x77, (byte)0xaf, (byte)0xad, (byte)0x5b, - (byte)0x96, (byte)0xf5, (byte)0x3c}; + byte[] expectedTag = {(byte)0xd3, (byte)0x62, (byte)0x84, (byte)0x3c, + (byte)0x9d, (byte)0x59, (byte)0x8c, (byte)0x6f}; ECPublicKey aliceBaseKey = Curve.decodePoint(aliceBaseKeyBytes, 0); ECPublicKey alicePreKey = aliceBaseKey; @@ -77,9 +78,11 @@ public class VerifyKeyTest extends AndroidTestCase { ECPublicKey bobIdentityKey = Curve.decodePoint(bobIdentityKeyBytes, 0); VerifyKey verifyKey = new VerifyKey(key); - byte[] verification = verifyKey.generateVerification(aliceBaseKey, Optional.of(alicePreKey), - aliceIdentityKey, bobBaseKey, - Optional.of(bobPreKey), bobIdentityKey); + + byte[] verification = verifyKey.generateVerification(new IdentityKey(aliceIdentityKey), + new IdentityKey(bobIdentityKey), + aliceBaseKey, bobBaseKey, + Optional.of(bobPreKey)); assertTrue(MessageDigest.isEqual(verification, expectedTag)); } diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java index 8a02b4b53c..d99cd00b59 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java @@ -8,7 +8,10 @@ import org.whispersystems.libaxolotl.ecc.ECPublicKey; import org.whispersystems.libaxolotl.protocol.CiphertextMessage; import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage; import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage; +import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters; +import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters; import org.whispersystems.libaxolotl.ratchet.RatchetingSession; +import org.whispersystems.libaxolotl.ratchet.SymmetricAxolotlParameters; import org.whispersystems.libaxolotl.state.IdentityKeyStore; import org.whispersystems.libaxolotl.state.PreKeyBundle; import org.whispersystems.libaxolotl.state.PreKeyStore; @@ -22,8 +25,6 @@ import org.whispersystems.libaxolotl.util.guava.Optional; import java.security.MessageDigest; -import static org.whispersystems.libaxolotl.ratchet.RatchetingSession.AxolotlParameters; - /** * SessionBuilder is responsible for setting up encrypted sessions. * Once a session has been established, {@link org.whispersystems.libaxolotl.SessionCipher} @@ -120,21 +121,22 @@ public class SessionBuilder { return false; } - boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage(); + boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage(); + ECKeyPair ourSignedPreKey = signedPreKeyStore.loadSignedPreKey(message.getSignedPreKeyId()).getKeyPair(); - AxolotlParameters.Builder parameters = AxolotlParameters.newBuilder(); + BobAxolotlParameters.Builder parameters = BobAxolotlParameters.newBuilder(); - parameters.setTheirBaseKey(message.getBaseKey()); - parameters.setTheirEphemeralKey(message.getWhisperMessage().getSenderEphemeral()); - parameters.setTheirPreKey(Optional.of(message.getBaseKey())); - parameters.setTheirIdentityKey(message.getIdentityKey()); + parameters.setTheirBaseKey(message.getBaseKey()) + .setTheirIdentityKey(message.getIdentityKey()) + .setOurIdentityKey(identityKeyStore.getIdentityKeyPair()) + .setOurSignedPreKey(ourSignedPreKey) + .setOurRatchetKey(ourSignedPreKey); - parameters.setOurBaseKey(signedPreKeyStore.loadSignedPreKey(message.getSignedPreKeyId()).getKeyPair()); - parameters.setOurEphemeralKey(parameters.getOurBaseKey()); - parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()); - - if (message.getPreKeyId() >= 0) parameters.setOurPreKey(Optional.of(preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair())); - else parameters.setOurPreKey(Optional.absent()); + if (message.getPreKeyId() >= 0) { + parameters.setOurOneTimePreKey(Optional.of(preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair())); + } else { + parameters.setOurOneTimePreKey(Optional.absent()); + } if (!simultaneousInitiate) sessionRecord.reset(); else sessionRecord.archiveCurrentState(); @@ -171,19 +173,18 @@ public class SessionBuilder { return false; } - SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); - boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage(); - AxolotlParameters.Builder parameters = RatchetingSession.AxolotlParameters.newBuilder(); + SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); + ECKeyPair ourPreKey = preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair(); + boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage(); - parameters.setTheirBaseKey(message.getBaseKey()); - parameters.setTheirEphemeralKey(message.getWhisperMessage().getSenderEphemeral()); - parameters.setTheirPreKey(Optional.absent()); - parameters.setTheirIdentityKey(message.getIdentityKey()); + BobAxolotlParameters.Builder parameters = BobAxolotlParameters.newBuilder(); - parameters.setOurBaseKey(preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair()); - parameters.setOurEphemeralKey(parameters.getOurBaseKey()); - parameters.setOurPreKey(Optional.absent()); - parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()); + parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()) + .setOurSignedPreKey(ourPreKey) + .setOurRatchetKey(ourPreKey) + .setOurOneTimePreKey(Optional.absent()) + .setTheirIdentityKey(message.getIdentityKey()) + .setTheirBaseKey(message.getBaseKey()); if (!simultaneousInitiate) sessionRecord.reset(); else sessionRecord.archiveCurrentState(); @@ -195,12 +196,12 @@ public class SessionBuilder { if (simultaneousInitiate) sessionRecord.getSessionState().setNeedsRefresh(true); - sessionStore.storeSession(recipientId, deviceId, sessionRecord); - if (message.getPreKeyId() != Medium.MAX_VALUE) { preKeyStore.removePreKey(message.getPreKeyId()); } + sessionStore.storeSession(recipientId, deviceId, sessionRecord); + return true; } @@ -233,20 +234,21 @@ public class SessionBuilder { throw new InvalidKeyException("Both signed and unsigned prekeys are absent!"); } - SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); - AxolotlParameters.Builder parameters = AxolotlParameters.newBuilder(); - ECKeyPair ourBaseKey = Curve.generateKeyPair(true); + SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); + ECKeyPair ourBaseKey = Curve.generateKeyPair(true); + ECPublicKey theirSignedPreKey = preKey.getSignedPreKey() != null ? preKey.getSignedPreKey() : + preKey.getPreKey(); - parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()); - parameters.setOurBaseKey(ourBaseKey); - parameters.setOurEphemeralKey(Curve.generateKeyPair(true)); - parameters.setOurPreKey(Optional.of(parameters.getOurBaseKey())); + AliceAxolotlParameters.Builder parameters = AliceAxolotlParameters.newBuilder(); - parameters.setTheirIdentityKey(preKey.getIdentityKey()); - if (preKey.getSignedPreKey() == null) parameters.setTheirBaseKey(preKey.getPreKey()); - else parameters.setTheirBaseKey(preKey.getSignedPreKey()); - parameters.setTheirEphemeralKey(parameters.getTheirBaseKey()); - parameters.setTheirPreKey(Optional.fromNullable(preKey.getPreKey())); + parameters.setOurBaseKey(ourBaseKey) + .setOurIdentityKey(identityKeyStore.getIdentityKeyPair()) + .setTheirIdentityKey(preKey.getIdentityKey()) + .setTheirSignedPreKey(theirSignedPreKey) + .setTheirRatchetKey(theirSignedPreKey) + .setTheirOneTimePreKey(preKey.getSignedPreKey() != null ? + Optional.fromNullable(preKey.getPreKey()) : + Optional.absent()); if (sessionRecord.getSessionState().getNeedsRefresh()) sessionRecord.archiveCurrentState(); else sessionRecord.reset(); @@ -288,9 +290,8 @@ public class SessionBuilder { } private KeyExchangeMessage processInitiate(KeyExchangeMessage message) throws InvalidKeyException { - AxolotlParameters.Builder parameters = AxolotlParameters.newBuilder(); - int flags = KeyExchangeMessage.RESPONSE_FLAG; - SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); + int flags = KeyExchangeMessage.RESPONSE_FLAG; + SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); if (message.getVersion() >= 3 && !Curve.verifySignature(message.getIdentityKey().getPublicKey(), @@ -300,41 +301,42 @@ public class SessionBuilder { throw new InvalidKeyException("Bad signature!"); } + SymmetricAxolotlParameters.Builder builder = SymmetricAxolotlParameters.newBuilder(); + if (!sessionRecord.getSessionState().hasPendingKeyExchange()) { - Log.w(TAG, "We don't have a pending initiate..."); - parameters.setOurBaseKey(Curve.generateKeyPair(true)); - parameters.setOurEphemeralKey(Curve.generateKeyPair(true)); - parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()); - parameters.setOurPreKey(Optional.absent()); + builder.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()) + .setOurBaseKey(Curve.generateKeyPair(true)) + .setOurRatchetKey(Curve.generateKeyPair(true)); } else { - Log.w(TAG, "We already have a pending initiate, responding as simultaneous initiate..."); - parameters.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey()); - parameters.setOurEphemeralKey(sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey()); - parameters.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey()); - parameters.setOurPreKey(Optional.absent()); + builder.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey()) + .setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey()) + .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey()); flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG; } - parameters.setTheirBaseKey(message.getBaseKey()); - parameters.setTheirEphemeralKey(message.getEphemeralKey()); - parameters.setTheirPreKey(Optional.absent()); - parameters.setTheirIdentityKey(message.getIdentityKey()); + builder.setTheirBaseKey(message.getBaseKey()) + .setTheirRatchetKey(message.getRatchetKey()) + .setTheirIdentityKey(message.getIdentityKey()); + + SymmetricAxolotlParameters parameters = builder.create(); sessionRecord.reset(); RatchetingSession.initializeSession(sessionRecord.getSessionState(), Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION), - parameters.create()); + parameters); sessionStore.storeSession(recipientId, deviceId, sessionRecord); identityKeyStore.saveIdentity(recipientId, message.getIdentityKey()); + byte[] baseKeySignature = Curve.calculateSignature(parameters.getOurIdentityKey().getPrivateKey(), + parameters.getOurBaseKey().getPublicKey().serialize()); + return new KeyExchangeMessage(sessionRecord.getSessionState().getSessionVersion(), message.getSequence(), flags, - parameters.getOurBaseKey().getPublicKey(), null, - parameters.getOurEphemeralKey().getPublicKey(), - parameters.getOurIdentityKey().getPublicKey(), - sessionRecord.getSessionState().getVerification()); + parameters.getOurBaseKey().getPublicKey(), + baseKeySignature, parameters.getOurRatchetKey().getPublicKey(), + parameters.getOurIdentityKey().getPublicKey()); } private void processResponse(KeyExchangeMessage message) @@ -351,29 +353,27 @@ public class SessionBuilder { else return; } - AxolotlParameters parameters = - AxolotlParameters.newBuilder() - .setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey()) - .setOurEphemeralKey(sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey()) - .setOurPreKey(Optional.absent()) - .setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey()) - .setTheirBaseKey(message.getBaseKey()) - .setTheirEphemeralKey(message.getEphemeralKey()) - .setTheirPreKey(Optional.absent()) - .setTheirIdentityKey(message.getIdentityKey()) - .create(); + SymmetricAxolotlParameters.Builder parameters = SymmetricAxolotlParameters.newBuilder(); + + parameters.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey()) + .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey()) + .setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey()) + .setTheirBaseKey(message.getBaseKey()) + .setTheirRatchetKey(message.getRatchetKey()) + .setTheirIdentityKey(message.getIdentityKey()); sessionRecord.reset(); RatchetingSession.initializeSession(sessionRecord.getSessionState(), Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION), - parameters); + parameters.create()); if (sessionRecord.getSessionState().getSessionVersion() >= 3 && - !MessageDigest.isEqual(message.getVerificationTag(), - sessionRecord.getSessionState().getVerification())) + !Curve.verifySignature(message.getIdentityKey().getPublicKey(), + message.getBaseKey().serialize(), + message.getBaseKeySignature())) { - throw new InvalidKeyException("Verification tag doesn't match!"); + throw new InvalidKeyException("Base key signature doesn't match!"); } sessionStore.storeSession(recipientId, deviceId, sessionRecord); @@ -387,18 +387,23 @@ public class SessionBuilder { * @return the KeyExchangeMessage to deliver. */ public KeyExchangeMessage process() { - int sequence = KeyHelper.getRandomSequence(65534) + 1; - int flags = KeyExchangeMessage.INITIATE_FLAG; - ECKeyPair baseKey = Curve.generateKeyPair(true); - ECKeyPair ephemeralKey = Curve.generateKeyPair(true); - IdentityKeyPair identityKey = identityKeyStore.getIdentityKeyPair(); - SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); + try { + int sequence = KeyHelper.getRandomSequence(65534) + 1; + int flags = KeyExchangeMessage.INITIATE_FLAG; + ECKeyPair baseKey = Curve.generateKeyPair(true); + ECKeyPair ratchetKey = Curve.generateKeyPair(true); + IdentityKeyPair identityKey = identityKeyStore.getIdentityKeyPair(); + byte[] baseKeySignature = Curve.calculateSignature(identityKey.getPrivateKey(), baseKey.getPublicKey().serialize()); + SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); - sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ephemeralKey, identityKey); - sessionStore.storeSession(recipientId, deviceId, sessionRecord); + sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ratchetKey, identityKey); + sessionStore.storeSession(recipientId, deviceId, sessionRecord); - return new KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), null, - ephemeralKey.getPublicKey(), identityKey.getPublicKey(), null); + return new KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), baseKeySignature, + ratchetKey.getPublicKey(), identityKey.getPublicKey()); + } catch (InvalidKeyException e) { + throw new AssertionError(e); + } } diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java index edf2c7c4db..029942442f 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java @@ -98,7 +98,7 @@ public class SessionCipher { SessionState sessionState = sessionRecord.getSessionState(); ChainKey chainKey = sessionState.getSenderChainKey(); MessageKeys messageKeys = chainKey.getMessageKeys(); - ECPublicKey senderEphemeral = sessionState.getSenderEphemeral(); + ECPublicKey senderEphemeral = sessionState.getSenderRatchetKey(); int previousCounter = sessionState.getPreviousCounter(); int sessionVersion = sessionState.getSessionVersion(); @@ -223,7 +223,7 @@ public class SessionCipher { sessionState.getSessionVersion())); } - ECPublicKey theirEphemeral = ciphertextMessage.getSenderEphemeral(); + ECPublicKey theirEphemeral = ciphertextMessage.getSenderRatchetKey(); int counter = ciphertextMessage.getCounter(); ChainKey chainKey = getOrCreateChainKey(sessionState, theirEphemeral); MessageKeys messageKeys = getOrCreateMessageKeys(sessionState, theirEphemeral, @@ -254,7 +254,7 @@ public class SessionCipher { return sessionState.getReceiverChainKey(theirEphemeral); } else { RootKey rootKey = sessionState.getRootKey(); - ECKeyPair ourEphemeral = sessionState.getSenderEphemeralPair(); + ECKeyPair ourEphemeral = sessionState.getSenderRatchetKeyPair(); Pair receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral); ECKeyPair ourNewEphemeral = Curve.generateKeyPair(true); Pair senderChain = receiverChain.first().createChain(theirEphemeral, ourNewEphemeral); diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java index 97babda5f3..bec9208c87 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java @@ -29,15 +29,14 @@ public class KeyExchangeMessage { private final ECPublicKey baseKey; private final byte[] baseKeySignature; - private final ECPublicKey ephemeralKey; + private final ECPublicKey ratchetKey; private final IdentityKey identityKey; - private final byte[] verificationTag; private final byte[] serialized; public KeyExchangeMessage(int messageVersion, int sequence, int flags, ECPublicKey baseKey, byte[] baseKeySignature, - ECPublicKey ephemeralKey, - IdentityKey identityKey, byte[] verificationTag) + ECPublicKey ratchetKey, + IdentityKey identityKey) { this.supportedVersion = CiphertextMessage.CURRENT_VERSION; this.version = messageVersion; @@ -45,25 +44,21 @@ public class KeyExchangeMessage { this.flags = flags; this.baseKey = baseKey; this.baseKeySignature = baseKeySignature; - this.ephemeralKey = ephemeralKey; + this.ratchetKey = ratchetKey; this.identityKey = identityKey; - this.verificationTag = verificationTag; byte[] version = {ByteUtil.intsToByteHighAndLow(this.version, this.supportedVersion)}; - Builder builder = WhisperProtos.KeyExchangeMessage.newBuilder() - .setId((sequence << 5) | flags) - .setBaseKey(ByteString.copyFrom(baseKey.serialize())) - .setEphemeralKey(ByteString.copyFrom(ephemeralKey.serialize())) - .setIdentityKey(ByteString.copyFrom(identityKey.serialize())); + Builder builder = WhisperProtos.KeyExchangeMessage + .newBuilder() + .setId((sequence << 5) | flags) + .setBaseKey(ByteString.copyFrom(baseKey.serialize())) + .setRatchetKey(ByteString.copyFrom(ratchetKey.serialize())) + .setIdentityKey(ByteString.copyFrom(identityKey.serialize())); - if (messageVersion >= 3 && baseKeySignature != null) { + if (messageVersion >= 3) { builder.setBaseKeySignature(ByteString.copyFrom(baseKeySignature)); } - if (messageVersion >=3 && verificationTag != null) { - builder.setVerification(ByteString.copyFrom(verificationTag)); - } - this.serialized = ByteUtil.combine(version, builder.build().toByteArray()); } @@ -86,9 +81,8 @@ public class KeyExchangeMessage { WhisperProtos.KeyExchangeMessage message = WhisperProtos.KeyExchangeMessage.parseFrom(parts[1]); if (!message.hasId() || !message.hasBaseKey() || - !message.hasEphemeralKey() || !message.hasIdentityKey() || - (this.version >=3 && (((message.getId() & 0x1f) & INITIATE_FLAG) != 0) && !message.hasBaseKeySignature()) || - (this.version >=3 && (((message.getId() & 0x1f) & RESPONSE_FLAG) != 0) && !message.hasVerification())) + !message.hasRatchetKey() || !message.hasIdentityKey() || + (this.version >=3 && !message.hasBaseKeySignature())) { throw new InvalidMessageException("Some required fields missing!"); } @@ -98,8 +92,7 @@ public class KeyExchangeMessage { this.serialized = serialized; this.baseKey = Curve.decodePoint(message.getBaseKey().toByteArray(), 0); this.baseKeySignature = message.getBaseKeySignature().toByteArray(); - this.verificationTag = message.getVerification().toByteArray(); - this.ephemeralKey = Curve.decodePoint(message.getEphemeralKey().toByteArray(), 0); + this.ratchetKey = Curve.decodePoint(message.getRatchetKey().toByteArray(), 0); this.identityKey = new IdentityKey(message.getIdentityKey().toByteArray(), 0); } catch (InvalidKeyException | IOException e) { throw new InvalidMessageException(e); @@ -118,12 +111,8 @@ public class KeyExchangeMessage { return baseKeySignature; } - public byte[] getVerificationTag() { - return verificationTag; - } - - public ECPublicKey getEphemeralKey() { - return ephemeralKey; + public ECPublicKey getRatchetKey() { + return ratchetKey; } public IdentityKey getIdentityKey() { diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java index b104e237d7..901294ebb2 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java @@ -38,7 +38,7 @@ public class WhisperMessage implements CiphertextMessage { private static final int MAC_LENGTH = 8; private final int messageVersion; - private final ECPublicKey senderEphemeral; + private final ECPublicKey senderRatchetKey; private final int counter; private final int previousCounter; private final byte[] ciphertext; @@ -63,44 +63,44 @@ public class WhisperMessage implements CiphertextMessage { if (!whisperMessage.hasCiphertext() || !whisperMessage.hasCounter() || - !whisperMessage.hasEphemeralKey()) + !whisperMessage.hasRatchetKey()) { throw new InvalidMessageException("Incomplete message."); } - this.serialized = serialized; - this.senderEphemeral = Curve.decodePoint(whisperMessage.getEphemeralKey().toByteArray(), 0); - this.messageVersion = ByteUtil.highBitsToInt(version); - this.counter = whisperMessage.getCounter(); - this.previousCounter = whisperMessage.getPreviousCounter(); - this.ciphertext = whisperMessage.getCiphertext().toByteArray(); + this.serialized = serialized; + this.senderRatchetKey = Curve.decodePoint(whisperMessage.getRatchetKey().toByteArray(), 0); + this.messageVersion = ByteUtil.highBitsToInt(version); + this.counter = whisperMessage.getCounter(); + this.previousCounter = whisperMessage.getPreviousCounter(); + this.ciphertext = whisperMessage.getCiphertext().toByteArray(); } catch (InvalidProtocolBufferException | InvalidKeyException | ParseException e) { throw new InvalidMessageException(e); } } - public WhisperMessage(int messageVersion, SecretKeySpec macKey, ECPublicKey senderEphemeral, + public WhisperMessage(int messageVersion, SecretKeySpec macKey, ECPublicKey senderRatchetKey, int counter, int previousCounter, byte[] ciphertext) { byte[] version = {ByteUtil.intsToByteHighAndLow(messageVersion, CURRENT_VERSION)}; byte[] message = WhisperProtos.WhisperMessage.newBuilder() - .setEphemeralKey(ByteString.copyFrom(senderEphemeral.serialize())) + .setRatchetKey(ByteString.copyFrom(senderRatchetKey.serialize())) .setCounter(counter) .setPreviousCounter(previousCounter) .setCiphertext(ByteString.copyFrom(ciphertext)) .build().toByteArray(); byte[] mac = getMac(macKey, ByteUtil.combine(version, message)); - this.serialized = ByteUtil.combine(version, message, mac); - this.senderEphemeral = senderEphemeral; - this.counter = counter; - this.previousCounter = previousCounter; - this.ciphertext = ciphertext; - this.messageVersion = messageVersion; + this.serialized = ByteUtil.combine(version, message, mac); + this.senderRatchetKey = senderRatchetKey; + this.counter = counter; + this.previousCounter = previousCounter; + this.ciphertext = ciphertext; + this.messageVersion = messageVersion; } - public ECPublicKey getSenderEphemeral() { - return senderEphemeral; + public ECPublicKey getSenderRatchetKey() { + return senderRatchetKey; } public int getMessageVersion() { diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java index eedb6e5fe3..b4e85e54df 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java @@ -11,15 +11,15 @@ public final class WhisperProtos { public interface WhisperMessageOrBuilder extends com.google.protobuf.MessageOrBuilder { - // optional bytes ephemeralKey = 1; + // optional bytes ratchetKey = 1; /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - boolean hasEphemeralKey(); + boolean hasRatchetKey(); /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - com.google.protobuf.ByteString getEphemeralKey(); + com.google.protobuf.ByteString getRatchetKey(); // optional uint32 counter = 2; /** @@ -104,7 +104,7 @@ public final class WhisperProtos { } case 10: { bitField0_ |= 0x00000001; - ephemeralKey_ = input.readBytes(); + ratchetKey_ = input.readBytes(); break; } case 16: { @@ -162,20 +162,20 @@ public final class WhisperProtos { } private int bitField0_; - // optional bytes ephemeralKey = 1; - public static final int EPHEMERALKEY_FIELD_NUMBER = 1; - private com.google.protobuf.ByteString ephemeralKey_; + // optional bytes ratchetKey = 1; + public static final int RATCHETKEY_FIELD_NUMBER = 1; + private com.google.protobuf.ByteString ratchetKey_; /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - public boolean hasEphemeralKey() { + public boolean hasRatchetKey() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - public com.google.protobuf.ByteString getEphemeralKey() { - return ephemeralKey_; + public com.google.protobuf.ByteString getRatchetKey() { + return ratchetKey_; } // optional uint32 counter = 2; @@ -227,7 +227,7 @@ public final class WhisperProtos { } private void initFields() { - ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; + ratchetKey_ = com.google.protobuf.ByteString.EMPTY; counter_ = 0; previousCounter_ = 0; ciphertext_ = com.google.protobuf.ByteString.EMPTY; @@ -245,7 +245,7 @@ public final class WhisperProtos { throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, ephemeralKey_); + output.writeBytes(1, ratchetKey_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { output.writeUInt32(2, counter_); @@ -267,7 +267,7 @@ public final class WhisperProtos { size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, ephemeralKey_); + .computeBytesSize(1, ratchetKey_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream @@ -397,7 +397,7 @@ public final class WhisperProtos { public Builder clear() { super.clear(); - ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; + ratchetKey_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000001); counter_ = 0; bitField0_ = (bitField0_ & ~0x00000002); @@ -436,7 +436,7 @@ public final class WhisperProtos { if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } - result.ephemeralKey_ = ephemeralKey_; + result.ratchetKey_ = ratchetKey_; if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } @@ -465,8 +465,8 @@ public final class WhisperProtos { public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage other) { if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.getDefaultInstance()) return this; - if (other.hasEphemeralKey()) { - setEphemeralKey(other.getEphemeralKey()); + if (other.hasRatchetKey()) { + setRatchetKey(other.getRatchetKey()); } if (other.hasCounter()) { setCounter(other.getCounter()); @@ -504,38 +504,38 @@ public final class WhisperProtos { } private int bitField0_; - // optional bytes ephemeralKey = 1; - private com.google.protobuf.ByteString ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; + // optional bytes ratchetKey = 1; + private com.google.protobuf.ByteString ratchetKey_ = com.google.protobuf.ByteString.EMPTY; /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - public boolean hasEphemeralKey() { + public boolean hasRatchetKey() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - public com.google.protobuf.ByteString getEphemeralKey() { - return ephemeralKey_; + public com.google.protobuf.ByteString getRatchetKey() { + return ratchetKey_; } /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - public Builder setEphemeralKey(com.google.protobuf.ByteString value) { + public Builder setRatchetKey(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000001; - ephemeralKey_ = value; + ratchetKey_ = value; onChanged(); return this; } /** - * optional bytes ephemeralKey = 1; + * optional bytes ratchetKey = 1; */ - public Builder clearEphemeralKey() { + public Builder clearRatchetKey() { bitField0_ = (bitField0_ & ~0x00000001); - ephemeralKey_ = getDefaultInstance().getEphemeralKey(); + ratchetKey_ = getDefaultInstance().getRatchetKey(); onChanged(); return this; } @@ -1602,15 +1602,15 @@ public final class WhisperProtos { */ com.google.protobuf.ByteString getBaseKey(); - // optional bytes ephemeralKey = 3; + // optional bytes ratchetKey = 3; /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - boolean hasEphemeralKey(); + boolean hasRatchetKey(); /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - com.google.protobuf.ByteString getEphemeralKey(); + com.google.protobuf.ByteString getRatchetKey(); // optional bytes identityKey = 4; /** @@ -1625,22 +1625,20 @@ public final class WhisperProtos { // optional bytes baseKeySignature = 5; /** * optional bytes baseKeySignature = 5; + * + *
+     *  optional bytes  verification     = 6;
+     * 
*/ boolean hasBaseKeySignature(); /** * optional bytes baseKeySignature = 5; + * + *
+     *  optional bytes  verification     = 6;
+     * 
*/ com.google.protobuf.ByteString getBaseKeySignature(); - - // optional bytes verification = 6; - /** - * optional bytes verification = 6; - */ - boolean hasVerification(); - /** - * optional bytes verification = 6; - */ - com.google.protobuf.ByteString getVerification(); } /** * Protobuf type {@code textsecure.KeyExchangeMessage} @@ -1705,7 +1703,7 @@ public final class WhisperProtos { } case 26: { bitField0_ |= 0x00000004; - ephemeralKey_ = input.readBytes(); + ratchetKey_ = input.readBytes(); break; } case 34: { @@ -1718,11 +1716,6 @@ public final class WhisperProtos { baseKeySignature_ = input.readBytes(); break; } - case 50: { - bitField0_ |= 0x00000020; - verification_ = input.readBytes(); - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -1795,20 +1788,20 @@ public final class WhisperProtos { return baseKey_; } - // optional bytes ephemeralKey = 3; - public static final int EPHEMERALKEY_FIELD_NUMBER = 3; - private com.google.protobuf.ByteString ephemeralKey_; + // optional bytes ratchetKey = 3; + public static final int RATCHETKEY_FIELD_NUMBER = 3; + private com.google.protobuf.ByteString ratchetKey_; /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - public boolean hasEphemeralKey() { + public boolean hasRatchetKey() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - public com.google.protobuf.ByteString getEphemeralKey() { - return ephemeralKey_; + public com.google.protobuf.ByteString getRatchetKey() { + return ratchetKey_; } // optional bytes identityKey = 4; @@ -1832,40 +1825,31 @@ public final class WhisperProtos { private com.google.protobuf.ByteString baseKeySignature_; /** * optional bytes baseKeySignature = 5; + * + *
+     *  optional bytes  verification     = 6;
+     * 
*/ public boolean hasBaseKeySignature() { return ((bitField0_ & 0x00000010) == 0x00000010); } /** * optional bytes baseKeySignature = 5; + * + *
+     *  optional bytes  verification     = 6;
+     * 
*/ public com.google.protobuf.ByteString getBaseKeySignature() { return baseKeySignature_; } - // optional bytes verification = 6; - public static final int VERIFICATION_FIELD_NUMBER = 6; - private com.google.protobuf.ByteString verification_; - /** - * optional bytes verification = 6; - */ - public boolean hasVerification() { - return ((bitField0_ & 0x00000020) == 0x00000020); - } - /** - * optional bytes verification = 6; - */ - public com.google.protobuf.ByteString getVerification() { - return verification_; - } - private void initFields() { id_ = 0; baseKey_ = com.google.protobuf.ByteString.EMPTY; - ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; + ratchetKey_ = com.google.protobuf.ByteString.EMPTY; identityKey_ = com.google.protobuf.ByteString.EMPTY; baseKeySignature_ = com.google.protobuf.ByteString.EMPTY; - verification_ = com.google.protobuf.ByteString.EMPTY; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -1886,7 +1870,7 @@ public final class WhisperProtos { output.writeBytes(2, baseKey_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeBytes(3, ephemeralKey_); + output.writeBytes(3, ratchetKey_); } if (((bitField0_ & 0x00000008) == 0x00000008)) { output.writeBytes(4, identityKey_); @@ -1894,9 +1878,6 @@ public final class WhisperProtos { if (((bitField0_ & 0x00000010) == 0x00000010)) { output.writeBytes(5, baseKeySignature_); } - if (((bitField0_ & 0x00000020) == 0x00000020)) { - output.writeBytes(6, verification_); - } getUnknownFields().writeTo(output); } @@ -1916,7 +1897,7 @@ public final class WhisperProtos { } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, ephemeralKey_); + .computeBytesSize(3, ratchetKey_); } if (((bitField0_ & 0x00000008) == 0x00000008)) { size += com.google.protobuf.CodedOutputStream @@ -1926,10 +1907,6 @@ public final class WhisperProtos { size += com.google.protobuf.CodedOutputStream .computeBytesSize(5, baseKeySignature_); } - if (((bitField0_ & 0x00000020) == 0x00000020)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(6, verification_); - } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -2050,14 +2027,12 @@ public final class WhisperProtos { bitField0_ = (bitField0_ & ~0x00000001); baseKey_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000002); - ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; + ratchetKey_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000004); identityKey_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000008); baseKeySignature_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000010); - verification_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000020); return this; } @@ -2097,7 +2072,7 @@ public final class WhisperProtos { if (((from_bitField0_ & 0x00000004) == 0x00000004)) { to_bitField0_ |= 0x00000004; } - result.ephemeralKey_ = ephemeralKey_; + result.ratchetKey_ = ratchetKey_; if (((from_bitField0_ & 0x00000008) == 0x00000008)) { to_bitField0_ |= 0x00000008; } @@ -2106,10 +2081,6 @@ public final class WhisperProtos { to_bitField0_ |= 0x00000010; } result.baseKeySignature_ = baseKeySignature_; - if (((from_bitField0_ & 0x00000020) == 0x00000020)) { - to_bitField0_ |= 0x00000020; - } - result.verification_ = verification_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -2132,8 +2103,8 @@ public final class WhisperProtos { if (other.hasBaseKey()) { setBaseKey(other.getBaseKey()); } - if (other.hasEphemeralKey()) { - setEphemeralKey(other.getEphemeralKey()); + if (other.hasRatchetKey()) { + setRatchetKey(other.getRatchetKey()); } if (other.hasIdentityKey()) { setIdentityKey(other.getIdentityKey()); @@ -2141,9 +2112,6 @@ public final class WhisperProtos { if (other.hasBaseKeySignature()) { setBaseKeySignature(other.getBaseKeySignature()); } - if (other.hasVerification()) { - setVerification(other.getVerification()); - } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -2240,38 +2208,38 @@ public final class WhisperProtos { return this; } - // optional bytes ephemeralKey = 3; - private com.google.protobuf.ByteString ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; + // optional bytes ratchetKey = 3; + private com.google.protobuf.ByteString ratchetKey_ = com.google.protobuf.ByteString.EMPTY; /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - public boolean hasEphemeralKey() { + public boolean hasRatchetKey() { return ((bitField0_ & 0x00000004) == 0x00000004); } /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - public com.google.protobuf.ByteString getEphemeralKey() { - return ephemeralKey_; + public com.google.protobuf.ByteString getRatchetKey() { + return ratchetKey_; } /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - public Builder setEphemeralKey(com.google.protobuf.ByteString value) { + public Builder setRatchetKey(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000004; - ephemeralKey_ = value; + ratchetKey_ = value; onChanged(); return this; } /** - * optional bytes ephemeralKey = 3; + * optional bytes ratchetKey = 3; */ - public Builder clearEphemeralKey() { + public Builder clearRatchetKey() { bitField0_ = (bitField0_ & ~0x00000004); - ephemeralKey_ = getDefaultInstance().getEphemeralKey(); + ratchetKey_ = getDefaultInstance().getRatchetKey(); onChanged(); return this; } @@ -2316,18 +2284,30 @@ public final class WhisperProtos { private com.google.protobuf.ByteString baseKeySignature_ = com.google.protobuf.ByteString.EMPTY; /** * optional bytes baseKeySignature = 5; + * + *
+       *  optional bytes  verification     = 6;
+       * 
*/ public boolean hasBaseKeySignature() { return ((bitField0_ & 0x00000010) == 0x00000010); } /** * optional bytes baseKeySignature = 5; + * + *
+       *  optional bytes  verification     = 6;
+       * 
*/ public com.google.protobuf.ByteString getBaseKeySignature() { return baseKeySignature_; } /** * optional bytes baseKeySignature = 5; + * + *
+       *  optional bytes  verification     = 6;
+       * 
*/ public Builder setBaseKeySignature(com.google.protobuf.ByteString value) { if (value == null) { @@ -2340,6 +2320,10 @@ public final class WhisperProtos { } /** * optional bytes baseKeySignature = 5; + * + *
+       *  optional bytes  verification     = 6;
+       * 
*/ public Builder clearBaseKeySignature() { bitField0_ = (bitField0_ & ~0x00000010); @@ -2348,42 +2332,6 @@ public final class WhisperProtos { return this; } - // optional bytes verification = 6; - private com.google.protobuf.ByteString verification_ = com.google.protobuf.ByteString.EMPTY; - /** - * optional bytes verification = 6; - */ - public boolean hasVerification() { - return ((bitField0_ & 0x00000020) == 0x00000020); - } - /** - * optional bytes verification = 6; - */ - public com.google.protobuf.ByteString getVerification() { - return verification_; - } - /** - * optional bytes verification = 6; - */ - public Builder setVerification(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000020; - verification_ = value; - onChanged(); - return this; - } - /** - * optional bytes verification = 6; - */ - public Builder clearVerification() { - bitField0_ = (bitField0_ & ~0x00000020); - verification_ = getDefaultInstance().getVerification(); - onChanged(); - return this; - } - // @@protoc_insertion_point(builder_scope:textsecure.KeyExchangeMessage) } @@ -2420,18 +2368,18 @@ public final class WhisperProtos { static { java.lang.String[] descriptorData = { "\n\031WhisperTextProtocol.proto\022\ntextsecure\"" + - "d\n\016WhisperMessage\022\024\n\014ephemeralKey\030\001 \001(\014\022" + - "\017\n\007counter\030\002 \001(\r\022\027\n\017previousCounter\030\003 \001(" + - "\r\022\022\n\nciphertext\030\004 \001(\014\"\245\001\n\024PreKeyWhisperM" + - "essage\022\026\n\016registrationId\030\005 \001(\r\022\020\n\010preKey" + - "Id\030\001 \001(\r\022\026\n\016signedPreKeyId\030\006 \001(\r\022\017\n\007base" + - "Key\030\002 \001(\014\022\023\n\013identityKey\030\003 \001(\014\022\024\n\014verifi" + - "cation\030\007 \001(\014\022\017\n\007message\030\004 \001(\014\"\214\001\n\022KeyExc" + - "hangeMessage\022\n\n\002id\030\001 \001(\r\022\017\n\007baseKey\030\002 \001(" + - "\014\022\024\n\014ephemeralKey\030\003 \001(\014\022\023\n\013identityKey\030\004", - " \001(\014\022\030\n\020baseKeySignature\030\005 \001(\014\022\024\n\014verifi" + - "cation\030\006 \001(\014B7\n&org.whispersystems.libax" + - "olotl.protocolB\rWhisperProtos" + "b\n\016WhisperMessage\022\022\n\nratchetKey\030\001 \001(\014\022\017\n" + + "\007counter\030\002 \001(\r\022\027\n\017previousCounter\030\003 \001(\r\022" + + "\022\n\nciphertext\030\004 \001(\014\"\245\001\n\024PreKeyWhisperMes" + + "sage\022\026\n\016registrationId\030\005 \001(\r\022\020\n\010preKeyId" + + "\030\001 \001(\r\022\026\n\016signedPreKeyId\030\006 \001(\r\022\017\n\007baseKe" + + "y\030\002 \001(\014\022\023\n\013identityKey\030\003 \001(\014\022\024\n\014verifica" + + "tion\030\007 \001(\014\022\017\n\007message\030\004 \001(\014\"t\n\022KeyExchan" + + "geMessage\022\n\n\002id\030\001 \001(\r\022\017\n\007baseKey\030\002 \001(\014\022\022" + + "\n\nratchetKey\030\003 \001(\014\022\023\n\013identityKey\030\004 \001(\014\022", + "\030\n\020baseKeySignature\030\005 \001(\014B7\n&org.whisper" + + "systems.libaxolotl.protocolB\rWhisperProt" + + "os" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -2443,7 +2391,7 @@ public final class WhisperProtos { internal_static_textsecure_WhisperMessage_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_textsecure_WhisperMessage_descriptor, - new java.lang.String[] { "EphemeralKey", "Counter", "PreviousCounter", "Ciphertext", }); + new java.lang.String[] { "RatchetKey", "Counter", "PreviousCounter", "Ciphertext", }); internal_static_textsecure_PreKeyWhisperMessage_descriptor = getDescriptor().getMessageTypes().get(1); internal_static_textsecure_PreKeyWhisperMessage_fieldAccessorTable = new @@ -2455,7 +2403,7 @@ public final class WhisperProtos { internal_static_textsecure_KeyExchangeMessage_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_textsecure_KeyExchangeMessage_descriptor, - new java.lang.String[] { "Id", "BaseKey", "EphemeralKey", "IdentityKey", "BaseKeySignature", "Verification", }); + new java.lang.String[] { "Id", "BaseKey", "RatchetKey", "IdentityKey", "BaseKeySignature", }); return null; } }; diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java new file mode 100644 index 0000000000..13c995e972 --- /dev/null +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java @@ -0,0 +1,109 @@ +package org.whispersystems.libaxolotl.ratchet; + +import org.whispersystems.libaxolotl.IdentityKey; +import org.whispersystems.libaxolotl.IdentityKeyPair; +import org.whispersystems.libaxolotl.ecc.ECKeyPair; +import org.whispersystems.libaxolotl.ecc.ECPublicKey; +import org.whispersystems.libaxolotl.util.guava.Optional; + +public class AliceAxolotlParameters { + + private final IdentityKeyPair ourIdentityKey; + private final ECKeyPair ourBaseKey; + + private final IdentityKey theirIdentityKey; + private final ECPublicKey theirSignedPreKey; + private final Optional theirOneTimePreKey; + private final ECPublicKey theirRatchetKey; + + private AliceAxolotlParameters(IdentityKeyPair ourIdentityKey, ECKeyPair ourBaseKey, + IdentityKey theirIdentityKey, ECPublicKey theirSignedPreKey, + ECPublicKey theirRatchetKey, Optional theirOneTimePreKey) + { + this.ourIdentityKey = ourIdentityKey; + this.ourBaseKey = ourBaseKey; + this.theirIdentityKey = theirIdentityKey; + this.theirSignedPreKey = theirSignedPreKey; + this.theirRatchetKey = theirRatchetKey; + this.theirOneTimePreKey = theirOneTimePreKey; + + if (ourIdentityKey == null || ourBaseKey == null || theirIdentityKey == null || + theirSignedPreKey == null || theirRatchetKey == null || theirOneTimePreKey == null) + { + throw new IllegalArgumentException("Null values!"); + } + } + + public IdentityKeyPair getOurIdentityKey() { + return ourIdentityKey; + } + + public ECKeyPair getOurBaseKey() { + return ourBaseKey; + } + + public IdentityKey getTheirIdentityKey() { + return theirIdentityKey; + } + + public ECPublicKey getTheirSignedPreKey() { + return theirSignedPreKey; + } + + public Optional getTheirOneTimePreKey() { + return theirOneTimePreKey; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public ECPublicKey getTheirRatchetKey() { + return theirRatchetKey; + } + + public static class Builder { + private IdentityKeyPair ourIdentityKey; + private ECKeyPair ourBaseKey; + + private IdentityKey theirIdentityKey; + private ECPublicKey theirSignedPreKey; + private ECPublicKey theirRatchetKey; + private Optional theirOneTimePreKey; + + public Builder setOurIdentityKey(IdentityKeyPair ourIdentityKey) { + this.ourIdentityKey = ourIdentityKey; + return this; + } + + public Builder setOurBaseKey(ECKeyPair ourBaseKey) { + this.ourBaseKey = ourBaseKey; + return this; + } + + public Builder setTheirRatchetKey(ECPublicKey theirRatchetKey) { + this.theirRatchetKey = theirRatchetKey; + return this; + } + + public Builder setTheirIdentityKey(IdentityKey theirIdentityKey) { + this.theirIdentityKey = theirIdentityKey; + return this; + } + + public Builder setTheirSignedPreKey(ECPublicKey theirSignedPreKey) { + this.theirSignedPreKey = theirSignedPreKey; + return this; + } + + public Builder setTheirOneTimePreKey(Optional theirOneTimePreKey) { + this.theirOneTimePreKey = theirOneTimePreKey; + return this; + } + + public AliceAxolotlParameters create() { + return new AliceAxolotlParameters(ourIdentityKey, ourBaseKey, theirIdentityKey, + theirSignedPreKey, theirRatchetKey, theirOneTimePreKey); + } + } +} diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java new file mode 100644 index 0000000000..27116a8b44 --- /dev/null +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java @@ -0,0 +1,109 @@ +package org.whispersystems.libaxolotl.ratchet; + +import org.whispersystems.libaxolotl.IdentityKey; +import org.whispersystems.libaxolotl.IdentityKeyPair; +import org.whispersystems.libaxolotl.ecc.ECKeyPair; +import org.whispersystems.libaxolotl.ecc.ECPublicKey; +import org.whispersystems.libaxolotl.util.guava.Optional; + +public class BobAxolotlParameters { + + private final IdentityKeyPair ourIdentityKey; + private final ECKeyPair ourSignedPreKey; + private final Optional ourOneTimePreKey; + private final ECKeyPair ourRatchetKey; + + private final IdentityKey theirIdentityKey; + private final ECPublicKey theirBaseKey; + + BobAxolotlParameters(IdentityKeyPair ourIdentityKey, ECKeyPair ourSignedPreKey, + ECKeyPair ourRatchetKey, Optional ourOneTimePreKey, + IdentityKey theirIdentityKey, ECPublicKey theirBaseKey) + { + this.ourIdentityKey = ourIdentityKey; + this.ourSignedPreKey = ourSignedPreKey; + this.ourRatchetKey = ourRatchetKey; + this.ourOneTimePreKey = ourOneTimePreKey; + this.theirIdentityKey = theirIdentityKey; + this.theirBaseKey = theirBaseKey; + + if (ourIdentityKey == null || ourSignedPreKey == null || ourRatchetKey == null || + ourOneTimePreKey == null || theirIdentityKey == null || theirBaseKey == null) + { + throw new IllegalArgumentException("Null value!"); + } + } + + public IdentityKeyPair getOurIdentityKey() { + return ourIdentityKey; + } + + public ECKeyPair getOurSignedPreKey() { + return ourSignedPreKey; + } + + public Optional getOurOneTimePreKey() { + return ourOneTimePreKey; + } + + public IdentityKey getTheirIdentityKey() { + return theirIdentityKey; + } + + public ECPublicKey getTheirBaseKey() { + return theirBaseKey; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public ECKeyPair getOurRatchetKey() { + return ourRatchetKey; + } + + public static class Builder { + private IdentityKeyPair ourIdentityKey; + private ECKeyPair ourSignedPreKey; + private Optional ourOneTimePreKey; + private ECKeyPair ourRatchetKey; + + private IdentityKey theirIdentityKey; + private ECPublicKey theirBaseKey; + + public Builder setOurIdentityKey(IdentityKeyPair ourIdentityKey) { + this.ourIdentityKey = ourIdentityKey; + return this; + } + + public Builder setOurSignedPreKey(ECKeyPair ourSignedPreKey) { + this.ourSignedPreKey = ourSignedPreKey; + return this; + } + + public Builder setOurOneTimePreKey(Optional ourOneTimePreKey) { + this.ourOneTimePreKey = ourOneTimePreKey; + return this; + } + + public Builder setTheirIdentityKey(IdentityKey theirIdentityKey) { + this.theirIdentityKey = theirIdentityKey; + return this; + } + + public Builder setTheirBaseKey(ECPublicKey theirBaseKey) { + this.theirBaseKey = theirBaseKey; + return this; + } + + public Builder setOurRatchetKey(ECKeyPair ourRatchetKey) { + this.ourRatchetKey = ourRatchetKey; + return this; + } + + public BobAxolotlParameters create() { + return new BobAxolotlParameters(ourIdentityKey, ourSignedPreKey, ourRatchetKey, + ourOneTimePreKey, theirIdentityKey, theirBaseKey); + } + } +} diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java index 4c6a6900f2..c732be1d2a 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java @@ -16,8 +16,6 @@ */ package org.whispersystems.libaxolotl.ratchet; -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.IdentityKeyPair; import org.whispersystems.libaxolotl.InvalidKeyException; import org.whispersystems.libaxolotl.ecc.Curve; import org.whispersystems.libaxolotl.ecc.ECKeyPair; @@ -37,288 +35,176 @@ public class RatchetingSession { public static void initializeSession(SessionState sessionState, int sessionVersion, - AxolotlParameters parameters) + SymmetricAxolotlParameters parameters) throws InvalidKeyException { - if (isAlice(parameters)) initializeSessionAsAlice(sessionState, sessionVersion, parameters); - else initializeSessionAsBob(sessionState, sessionVersion, parameters); + if (isAlice(parameters.getOurBaseKey().getPublicKey(), parameters.getTheirBaseKey())) { + AliceAxolotlParameters.Builder aliceParameters = AliceAxolotlParameters.newBuilder(); - sessionState.setSessionVersion(sessionVersion); - } + aliceParameters.setOurBaseKey(parameters.getOurBaseKey()) + .setOurIdentityKey(parameters.getOurIdentityKey()) + .setTheirRatchetKey(parameters.getTheirRatchetKey()) + .setTheirIdentityKey(parameters.getTheirIdentityKey()) + .setTheirSignedPreKey(parameters.getTheirBaseKey()) + .setTheirOneTimePreKey(Optional.absent()); - private static void initializeSessionAsAlice(SessionState sessionState, - int sessionVersion, - AxolotlParameters parameters) - throws InvalidKeyException - { - sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey()); - sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey()); + RatchetingSession.initializeSession(sessionState, sessionVersion, aliceParameters.create()); + } else { + BobAxolotlParameters.Builder bobParameters = BobAxolotlParameters.newBuilder(); - ECKeyPair sendingKey = Curve.generateKeyPair(true); - DHEResult result = calculate4DHE(true, sessionVersion, parameters); + bobParameters.setOurIdentityKey(parameters.getOurIdentityKey()) + .setOurRatchetKey(parameters.getOurRatchetKey()) + .setOurSignedPreKey(parameters.getOurBaseKey()) + .setOurOneTimePreKey(Optional.absent()) + .setTheirBaseKey(parameters.getTheirBaseKey()) + .setTheirIdentityKey(parameters.getTheirIdentityKey()); - Pair sendingChain = result.getRootKey().createChain(parameters.getTheirEphemeralKey(), sendingKey); - - sessionState.addReceiverChain(parameters.getTheirEphemeralKey(), result.getChainKey()); - sessionState.setSenderChain(sendingKey, sendingChain.second()); - sessionState.setRootKey(sendingChain.first()); - - if (sessionVersion >= 3) { - sessionState.setVerification(calculateVerificationTag(true, result.getVerifyKey(), parameters)); + RatchetingSession.initializeSession(sessionState, sessionVersion, bobParameters.create()); } } - private static void initializeSessionAsBob(SessionState sessionState, - int sessionVersion, - AxolotlParameters parameters) - throws InvalidKeyException - { - sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey()); - sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey()); - - DHEResult result = calculate4DHE(false, sessionVersion, parameters); - - sessionState.setSenderChain(parameters.getOurEphemeralKey(), result.getChainKey()); - sessionState.setRootKey(result.getRootKey()); - - if (sessionVersion >= 3) { - sessionState.setVerification(calculateVerificationTag(false, result.getVerifyKey(), parameters)); - } - } - - private static DHEResult calculate4DHE(boolean isAlice, int sessionVersion, AxolotlParameters parameters) + public static void initializeSession(SessionState sessionState, + int sessionVersion, + AliceAxolotlParameters parameters) throws InvalidKeyException { try { - HKDF kdf = HKDF.createFor(sessionVersion); - byte[] discontinuity = new byte[32]; - ByteArrayOutputStream secrets = new ByteArrayOutputStream(); + sessionState.setSessionVersion(sessionVersion); + sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey()); + sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey()); + + ECKeyPair sendingRatchetKey = Curve.generateKeyPair(true); + ByteArrayOutputStream secrets = new ByteArrayOutputStream(); if (sessionVersion >= 3) { - Arrays.fill(discontinuity, (byte) 0xFF); - secrets.write(discontinuity); + secrets.write(getDiscontinuityBytes()); } - if (isAlice) { - secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(), - parameters.getOurIdentityKey().getPrivateKey())); - secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), - parameters.getOurBaseKey().getPrivateKey())); - } else { - secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), - parameters.getOurBaseKey().getPrivateKey())); - secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(), - parameters.getOurIdentityKey().getPrivateKey())); - } - - secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(), + secrets.write(Curve.calculateAgreement(parameters.getTheirSignedPreKey(), + parameters.getOurIdentityKey().getPrivateKey())); + secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), + parameters.getOurBaseKey().getPrivateKey())); + secrets.write(Curve.calculateAgreement(parameters.getTheirSignedPreKey(), parameters.getOurBaseKey().getPrivateKey())); - if (sessionVersion >= 3 && parameters.getTheirPreKey().isPresent() && parameters.getOurPreKey().isPresent()) { - secrets.write(Curve.calculateAgreement(parameters.getTheirPreKey().get(), parameters.getOurPreKey().get().getPrivateKey())); + if (sessionVersion >= 3 & parameters.getTheirOneTimePreKey().isPresent()) { + secrets.write(Curve.calculateAgreement(parameters.getTheirOneTimePreKey().get(), + parameters.getOurBaseKey().getPrivateKey())); } - byte[] derivedSecretBytes = kdf.deriveSecrets(secrets.toByteArray(), "WhisperText".getBytes(), 96); - byte[][] derivedSecrets = ByteUtil.split(derivedSecretBytes, 32, 32, 32); + DerivedKeys derivedKeys = calculateDerivedKeys(sessionVersion, secrets.toByteArray()); + Pair sendingChain = derivedKeys.getRootKey().createChain(parameters.getTheirRatchetKey(), sendingRatchetKey); - return new DHEResult(new RootKey(kdf, derivedSecrets[0]), - new ChainKey(kdf, derivedSecrets[1], 0), - new VerifyKey(derivedSecrets[2])); + sessionState.addReceiverChain(parameters.getTheirRatchetKey(), derivedKeys.getChainKey()); + sessionState.setSenderChain(sendingRatchetKey, sendingChain.second()); + sessionState.setRootKey(sendingChain.first()); - } catch (IOException | ParseException e) { + if (sessionVersion >= 3) { + sessionState.setVerification(calculateVerificationTag(derivedKeys.getVerifyKey(), parameters)); + } + + } catch (IOException e) { throw new AssertionError(e); } } - private static byte[] calculateVerificationTag(boolean isAlice, VerifyKey verifyKey, - AxolotlParameters parameters) + public static void initializeSession(SessionState sessionState, + int sessionVersion, + BobAxolotlParameters parameters) + throws InvalidKeyException { - if (isAlice) { - return verifyKey.generateVerification(parameters.getOurBaseKey().getPublicKey(), - getPublicKey(parameters.getOurPreKey()), - parameters.getOurIdentityKey().getPublicKey().getPublicKey(), - parameters.getTheirBaseKey(), - parameters.getTheirPreKey(), - parameters.getTheirIdentityKey().getPublicKey()); + + try { + sessionState.setSessionVersion(sessionVersion); + sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey()); + sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey()); + + ByteArrayOutputStream secrets = new ByteArrayOutputStream(); + + if (sessionVersion >= 3) { + secrets.write(getDiscontinuityBytes()); + } + + secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), + parameters.getOurSignedPreKey().getPrivateKey())); + secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(), + parameters.getOurIdentityKey().getPrivateKey())); + secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(), + parameters.getOurSignedPreKey().getPrivateKey())); + + if (sessionVersion >= 3 && parameters.getOurOneTimePreKey().isPresent()) { + secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(), + parameters.getOurOneTimePreKey().get().getPrivateKey())); + } + + DerivedKeys derivedKeys = calculateDerivedKeys(sessionVersion, secrets.toByteArray()); + + sessionState.setSenderChain(parameters.getOurRatchetKey(), derivedKeys.getChainKey()); + sessionState.setRootKey(derivedKeys.getRootKey()); + + if (sessionVersion >= 3) { + sessionState.setVerification(calculateVerificationTag(derivedKeys.getVerifyKey(), parameters)); + } + } catch (IOException e) { + throw new AssertionError(e); + } + } + + private static byte[] calculateVerificationTag(VerifyKey verifyKey, AliceAxolotlParameters parameters) { + return verifyKey.generateVerification(parameters.getOurIdentityKey().getPublicKey(), + parameters.getTheirIdentityKey(), + parameters.getOurBaseKey().getPublicKey(), + parameters.getTheirSignedPreKey(), + parameters.getTheirOneTimePreKey()); + } + + private static byte[] calculateVerificationTag(VerifyKey verifyKey, BobAxolotlParameters parameters) { + Optional ourOneTimePreKey; + + if (parameters.getOurOneTimePreKey().isPresent()) { + ourOneTimePreKey = Optional.of(parameters.getOurOneTimePreKey().get().getPublicKey()); } else { - return verifyKey.generateVerification(parameters.getTheirBaseKey(), - parameters.getTheirPreKey(), - parameters.getTheirIdentityKey().getPublicKey(), - parameters.getOurBaseKey().getPublicKey(), - getPublicKey(parameters.getOurPreKey()), - parameters.getOurIdentityKey().getPublicKey().getPublicKey()); + ourOneTimePreKey = Optional.absent(); + } + + return verifyKey.generateVerification(parameters.getTheirIdentityKey(), + parameters.getOurIdentityKey().getPublicKey(), + parameters.getTheirBaseKey(), + parameters.getOurSignedPreKey().getPublicKey(), + ourOneTimePreKey); + } + + private static byte[] getDiscontinuityBytes() { + byte[] discontinuity = new byte[32]; + Arrays.fill(discontinuity, (byte) 0xFF); + return discontinuity; + } + + private static DerivedKeys calculateDerivedKeys(int sessionVersion, byte[] masterSecret) { + try { + HKDF kdf = HKDF.createFor(sessionVersion); + byte[] derivedSecretBytes = kdf.deriveSecrets(masterSecret, "WhisperText".getBytes(), 96); + byte[][] derivedSecrets = ByteUtil.split(derivedSecretBytes, 32, 32, 32); + + return new DerivedKeys(new RootKey(kdf, derivedSecrets[0]), + new ChainKey(kdf, derivedSecrets[1], 0), + new VerifyKey(derivedSecrets[2])); + } catch (ParseException e) { + throw new AssertionError(e); } } - private static boolean isAlice(AxolotlParameters parameters) - { - if (parameters.getOurEphemeralKey().equals(parameters.getOurBaseKey())) { - return false; - } - - if (parameters.getTheirEphemeralKey().equals(parameters.getTheirBaseKey())) { - return true; - } - - return isLowEnd(parameters.getOurBaseKey().getPublicKey(), parameters.getTheirBaseKey()); - } - - private static boolean isLowEnd(ECPublicKey ourKey, ECPublicKey theirKey) { + private static boolean isAlice(ECPublicKey ourKey, ECPublicKey theirKey) { return ourKey.compareTo(theirKey) < 0; } - private static Optional getPublicKey(Optional keyPair) { - if (keyPair.isPresent()) return Optional.of(keyPair.get().getPublicKey()); - else return Optional.absent(); - } - public static class AxolotlParameters { - private final ECKeyPair ourBaseKey; - private final ECKeyPair ourEphemeralKey; - private final Optional ourPreKey; - private final IdentityKeyPair ourIdentityKey; - - private final ECPublicKey theirBaseKey; - private final ECPublicKey theirEphemeralKey; - private final Optional theirPreKey; - private final IdentityKey theirIdentityKey; - - public AxolotlParameters(ECKeyPair ourBaseKey, ECKeyPair ourEphemeralKey, - Optional ourPreKey, IdentityKeyPair ourIdentityKey, - ECPublicKey theirBaseKey, ECPublicKey theirEphemeralKey, - Optional theirPreKey, IdentityKey theirIdentityKey) - { - this.ourBaseKey = ourBaseKey; - this.ourEphemeralKey = ourEphemeralKey; - this.ourPreKey = ourPreKey; - this.ourIdentityKey = ourIdentityKey; - this.theirBaseKey = theirBaseKey; - this.theirEphemeralKey = theirEphemeralKey; - this.theirPreKey = theirPreKey; - this.theirIdentityKey = theirIdentityKey; - } - - public ECKeyPair getOurBaseKey() { - return ourBaseKey; - } - - public ECKeyPair getOurEphemeralKey() { - return ourEphemeralKey; - } - - public Optional getOurPreKey() { - return ourPreKey; - } - - public IdentityKeyPair getOurIdentityKey() { - return ourIdentityKey; - } - - public ECPublicKey getTheirBaseKey() { - return theirBaseKey; - } - - public ECPublicKey getTheirEphemeralKey() { - return theirEphemeralKey; - } - - public Optional getTheirPreKey() { - return theirPreKey; - } - - public IdentityKey getTheirIdentityKey() { - return theirIdentityKey; - } - - public static Builder newBuilder() { - return new Builder(); - } - - public static class Builder { - private ECKeyPair ourBaseKey; - private ECKeyPair ourEphemeralKey; - private Optional ourPreKey; - private IdentityKeyPair ourIdentityKey; - private ECPublicKey theirBaseKey; - private ECPublicKey theirEphemeralKey; - private Optional theirPreKey; - private IdentityKey theirIdentityKey; - - public Builder setOurBaseKey(ECKeyPair ourBaseKey) { - this.ourBaseKey = ourBaseKey; - return this; - } - - public ECKeyPair getOurBaseKey() { - return ourBaseKey; - } - - public Builder setOurEphemeralKey(ECKeyPair ourEphemeralKey) { - this.ourEphemeralKey = ourEphemeralKey; - return this; - } - - public ECKeyPair getOurEphemeralKey() { - return ourEphemeralKey; - } - - public Builder setOurPreKey(Optional ourPreKey) { - this.ourPreKey = ourPreKey; - return this; - } - - public Builder setOurIdentityKey(IdentityKeyPair ourIdentityKey) { - this.ourIdentityKey = ourIdentityKey; - return this; - } - - public IdentityKeyPair getOurIdentityKey() { - return ourIdentityKey; - } - - public Builder setTheirBaseKey(ECPublicKey theirBaseKey) { - this.theirBaseKey = theirBaseKey; - return this; - } - - public ECPublicKey getTheirBaseKey() { - return theirBaseKey; - } - - public Builder setTheirEphemeralKey(ECPublicKey theirEphemeralKey) { - this.theirEphemeralKey = theirEphemeralKey; - return this; - } - - public Builder setTheirPreKey(Optional theirPreKey) { - this.theirPreKey = theirPreKey; - return this; - } - - public Builder setTheirIdentityKey(IdentityKey theirIdentityKey) { - this.theirIdentityKey = theirIdentityKey; - return this; - } - - public AxolotlParameters create() { - if (ourBaseKey == null || ourEphemeralKey == null || ourPreKey == null || ourIdentityKey == null || - theirBaseKey == null || theirEphemeralKey == null || theirPreKey == null || theirIdentityKey == null) - { - throw new IllegalArgumentException("All parameters not specified!"); - } - - return new AxolotlParameters(ourBaseKey, ourEphemeralKey, ourPreKey, ourIdentityKey, - theirBaseKey, theirEphemeralKey, theirPreKey, theirIdentityKey); - } - } - } - - private static class DHEResult { + private static class DerivedKeys { private final RootKey rootKey; private final ChainKey chainKey; private final VerifyKey verifyKey; - private DHEResult(RootKey rootKey, ChainKey chainKey, VerifyKey verifyKey) { + private DerivedKeys(RootKey rootKey, ChainKey chainKey, VerifyKey verifyKey) { this.rootKey = rootKey; this.chainKey = chainKey; this.verifyKey = verifyKey; @@ -336,5 +222,4 @@ public class RatchetingSession { return verifyKey; } } - } diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java new file mode 100644 index 0000000000..7a63c45ffb --- /dev/null +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java @@ -0,0 +1,108 @@ +package org.whispersystems.libaxolotl.ratchet; + +import org.whispersystems.libaxolotl.IdentityKey; +import org.whispersystems.libaxolotl.IdentityKeyPair; +import org.whispersystems.libaxolotl.ecc.ECKeyPair; +import org.whispersystems.libaxolotl.ecc.ECPublicKey; + +public class SymmetricAxolotlParameters { + + private final ECKeyPair ourBaseKey; + private final ECKeyPair ourRatchetKey; + private final IdentityKeyPair ourIdentityKey; + + private final ECPublicKey theirBaseKey; + private final ECPublicKey theirRatchetKey; + private final IdentityKey theirIdentityKey; + + SymmetricAxolotlParameters(ECKeyPair ourBaseKey, ECKeyPair ourRatchetKey, + IdentityKeyPair ourIdentityKey, ECPublicKey theirBaseKey, + ECPublicKey theirRatchetKey, IdentityKey theirIdentityKey) + { + this.ourBaseKey = ourBaseKey; + this.ourRatchetKey = ourRatchetKey; + this.ourIdentityKey = ourIdentityKey; + this.theirBaseKey = theirBaseKey; + this.theirRatchetKey = theirRatchetKey; + this.theirIdentityKey = theirIdentityKey; + + if (ourBaseKey == null || ourRatchetKey == null || ourIdentityKey == null || + theirBaseKey == null || theirRatchetKey == null || theirIdentityKey == null) + { + throw new IllegalArgumentException("Null values!"); + } + } + + public ECKeyPair getOurBaseKey() { + return ourBaseKey; + } + + public ECKeyPair getOurRatchetKey() { + return ourRatchetKey; + } + + public IdentityKeyPair getOurIdentityKey() { + return ourIdentityKey; + } + + public ECPublicKey getTheirBaseKey() { + return theirBaseKey; + } + + public ECPublicKey getTheirRatchetKey() { + return theirRatchetKey; + } + + public IdentityKey getTheirIdentityKey() { + return theirIdentityKey; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + private ECKeyPair ourBaseKey; + private ECKeyPair ourRatchetKey; + private IdentityKeyPair ourIdentityKey; + + private ECPublicKey theirBaseKey; + private ECPublicKey theirRatchetKey; + private IdentityKey theirIdentityKey; + + public Builder setOurBaseKey(ECKeyPair ourBaseKey) { + this.ourBaseKey = ourBaseKey; + return this; + } + + public Builder setOurRatchetKey(ECKeyPair ourRatchetKey) { + this.ourRatchetKey = ourRatchetKey; + return this; + } + + public Builder setOurIdentityKey(IdentityKeyPair ourIdentityKey) { + this.ourIdentityKey = ourIdentityKey; + return this; + } + + public Builder setTheirBaseKey(ECPublicKey theirBaseKey) { + this.theirBaseKey = theirBaseKey; + return this; + } + + public Builder setTheirRatchetKey(ECPublicKey theirRatchetKey) { + this.theirRatchetKey = theirRatchetKey; + return this; + } + + public Builder setTheirIdentityKey(IdentityKey theirIdentityKey) { + this.theirIdentityKey = theirIdentityKey; + return this; + } + + public SymmetricAxolotlParameters create() { + return new SymmetricAxolotlParameters(ourBaseKey, ourRatchetKey, ourIdentityKey, + theirBaseKey, theirRatchetKey, theirIdentityKey); + } + } +} diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/VerifyKey.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/VerifyKey.java index 19294378c7..e2ca84b148 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/VerifyKey.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/ratchet/VerifyKey.java @@ -1,5 +1,6 @@ package org.whispersystems.libaxolotl.ratchet; +import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.ecc.ECPublicKey; import org.whispersystems.libaxolotl.util.ByteUtil; import org.whispersystems.libaxolotl.util.guava.Optional; @@ -24,29 +25,26 @@ public class VerifyKey { return key; } - public byte[] generateVerification(ECPublicKey aliceBaseKey, - Optional alicePreKey, - ECPublicKey aliceIdentityKey, - ECPublicKey bobBaseKey, - Optional bobPreKey, - ECPublicKey bobIdentityKey) + public byte[] generateVerification(IdentityKey aliceIdentity, + IdentityKey bobIdentity, + ECPublicKey aliceBaseKey, + ECPublicKey bobSignedPreKey, + Optional bobOneTimePreKey) { try { Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(key, "HmacSHA256")); mac.update(VERIFICATION_INFO); + mac.update(aliceIdentity.getPublicKey().serialize()); + mac.update(bobIdentity.getPublicKey().serialize()); mac.update(aliceBaseKey.serialize()); - mac.update(aliceIdentityKey.serialize()); - mac.update(bobBaseKey.serialize()); - mac.update(bobIdentityKey.serialize()); + mac.update(bobSignedPreKey.serialize()); - if (alicePreKey.isPresent() && bobPreKey.isPresent()) { - mac.update(alicePreKey.get().serialize()); - mac.update(bobPreKey.get().serialize()); + if (bobOneTimePreKey.isPresent()) { + mac.update(bobOneTimePreKey.get().serialize()); } - return ByteUtil.trim(mac.doFinal(), 8); } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw new AssertionError(e); diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java index 29cb027699..2e3bbb7367 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java @@ -32,11 +32,10 @@ import org.whispersystems.libaxolotl.kdf.HKDF; import org.whispersystems.libaxolotl.ratchet.ChainKey; import org.whispersystems.libaxolotl.ratchet.MessageKeys; import org.whispersystems.libaxolotl.ratchet.RootKey; -import org.whispersystems.libaxolotl.ratchet.VerifyKey; -import org.whispersystems.libaxolotl.util.Pair; import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain; import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange; import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey; +import org.whispersystems.libaxolotl.util.Pair; import java.util.Iterator; import java.util.LinkedList; @@ -159,18 +158,18 @@ public class SessionState { .build(); } - public ECPublicKey getSenderEphemeral() { + public ECPublicKey getSenderRatchetKey() { try { - return Curve.decodePoint(sessionStructure.getSenderChain().getSenderEphemeral().toByteArray(), 0); + return Curve.decodePoint(sessionStructure.getSenderChain().getSenderRatchetKey().toByteArray(), 0); } catch (InvalidKeyException e) { throw new AssertionError(e); } } - public ECKeyPair getSenderEphemeralPair() { - ECPublicKey publicKey = getSenderEphemeral(); + public ECKeyPair getSenderRatchetKeyPair() { + ECPublicKey publicKey = getSenderRatchetKey(); ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getSenderChain() - .getSenderEphemeralPrivate() + .getSenderRatchetKeyPrivate() .toByteArray()); return new ECKeyPair(publicKey, privateKey); @@ -190,9 +189,9 @@ public class SessionState { for (Chain receiverChain : receiverChains) { try { - ECPublicKey chainSenderEphemeral = Curve.decodePoint(receiverChain.getSenderEphemeral().toByteArray(), 0); + ECPublicKey chainSenderRatchetKey = Curve.decodePoint(receiverChain.getSenderRatchetKey().toByteArray(), 0); - if (chainSenderEphemeral.equals(senderEphemeral)) { + if (chainSenderRatchetKey.equals(senderEphemeral)) { return new Pair<>(receiverChain,index); } } catch (InvalidKeyException e) { @@ -218,7 +217,7 @@ public class SessionState { } } - public void addReceiverChain(ECPublicKey senderEphemeral, ChainKey chainKey) { + public void addReceiverChain(ECPublicKey senderRatchetKey, ChainKey chainKey) { Chain.ChainKey chainKeyStructure = Chain.ChainKey.newBuilder() .setKey(ByteString.copyFrom(chainKey.getKey())) .setIndex(chainKey.getIndex()) @@ -226,7 +225,7 @@ public class SessionState { Chain chain = Chain.newBuilder() .setChainKey(chainKeyStructure) - .setSenderEphemeral(ByteString.copyFrom(senderEphemeral.serialize())) + .setSenderRatchetKey(ByteString.copyFrom(senderRatchetKey.serialize())) .build(); this.sessionStructure = this.sessionStructure.toBuilder().addReceiverChains(chain).build(); @@ -238,15 +237,15 @@ public class SessionState { } } - public void setSenderChain(ECKeyPair senderEphemeralPair, ChainKey chainKey) { + public void setSenderChain(ECKeyPair senderRatchetKeyPair, ChainKey chainKey) { Chain.ChainKey chainKeyStructure = Chain.ChainKey.newBuilder() .setKey(ByteString.copyFrom(chainKey.getKey())) .setIndex(chainKey.getIndex()) .build(); Chain senderChain = Chain.newBuilder() - .setSenderEphemeral(ByteString.copyFrom(senderEphemeralPair.getPublicKey().serialize())) - .setSenderEphemeralPrivate(ByteString.copyFrom(senderEphemeralPair.getPrivateKey().serialize())) + .setSenderRatchetKey(ByteString.copyFrom(senderRatchetKeyPair.getPublicKey().serialize())) + .setSenderRatchetKeyPrivate(ByteString.copyFrom(senderRatchetKeyPair.getPrivateKey().serialize())) .setChainKey(chainKeyStructure) .build(); @@ -363,7 +362,7 @@ public class SessionState { public void setPendingKeyExchange(int sequence, ECKeyPair ourBaseKey, - ECKeyPair ourEphemeralKey, + ECKeyPair ourRatchetKey, IdentityKeyPair ourIdentityKey) { PendingKeyExchange structure = @@ -371,8 +370,8 @@ public class SessionState { .setSequence(sequence) .setLocalBaseKey(ByteString.copyFrom(ourBaseKey.getPublicKey().serialize())) .setLocalBaseKeyPrivate(ByteString.copyFrom(ourBaseKey.getPrivateKey().serialize())) - .setLocalEphemeralKey(ByteString.copyFrom(ourEphemeralKey.getPublicKey().serialize())) - .setLocalEphemeralKeyPrivate(ByteString.copyFrom(ourEphemeralKey.getPrivateKey().serialize())) + .setLocalRatchetKey(ByteString.copyFrom(ourRatchetKey.getPublicKey().serialize())) + .setLocalRatchetKeyPrivate(ByteString.copyFrom(ourRatchetKey.getPrivateKey().serialize())) .setLocalIdentityKey(ByteString.copyFrom(ourIdentityKey.getPublicKey().serialize())) .setLocalIdentityKeyPrivate(ByteString.copyFrom(ourIdentityKey.getPrivateKey().serialize())) .build(); @@ -397,12 +396,12 @@ public class SessionState { return new ECKeyPair(publicKey, privateKey); } - public ECKeyPair getPendingKeyExchangeEphemeralKey() throws InvalidKeyException { + public ECKeyPair getPendingKeyExchangeRatchetKey() throws InvalidKeyException { ECPublicKey publicKey = Curve.decodePoint(sessionStructure.getPendingKeyExchange() - .getLocalEphemeralKey().toByteArray(), 0); + .getLocalRatchetKey().toByteArray(), 0); ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getPendingKeyExchange() - .getLocalEphemeralKeyPrivate() + .getLocalRatchetKeyPrivate() .toByteArray()); return new ECKeyPair(publicKey, privateKey); diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java index 69bd84ca26..59b1c5d030 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java @@ -371,25 +371,25 @@ public final class StorageProtos { public interface ChainOrBuilder extends com.google.protobuf.MessageOrBuilder { - // optional bytes senderEphemeral = 1; + // optional bytes senderRatchetKey = 1; /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - boolean hasSenderEphemeral(); + boolean hasSenderRatchetKey(); /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - com.google.protobuf.ByteString getSenderEphemeral(); + com.google.protobuf.ByteString getSenderRatchetKey(); - // optional bytes senderEphemeralPrivate = 2; + // optional bytes senderRatchetKeyPrivate = 2; /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - boolean hasSenderEphemeralPrivate(); + boolean hasSenderRatchetKeyPrivate(); /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - com.google.protobuf.ByteString getSenderEphemeralPrivate(); + com.google.protobuf.ByteString getSenderRatchetKeyPrivate(); // optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3; /** @@ -483,12 +483,12 @@ public final class StorageProtos { } case 10: { bitField0_ |= 0x00000001; - senderEphemeral_ = input.readBytes(); + senderRatchetKey_ = input.readBytes(); break; } case 18: { bitField0_ |= 0x00000002; - senderEphemeralPrivate_ = input.readBytes(); + senderRatchetKeyPrivate_ = input.readBytes(); break; } case 26: { @@ -1599,36 +1599,36 @@ public final class StorageProtos { } private int bitField0_; - // optional bytes senderEphemeral = 1; - public static final int SENDEREPHEMERAL_FIELD_NUMBER = 1; - private com.google.protobuf.ByteString senderEphemeral_; + // optional bytes senderRatchetKey = 1; + public static final int SENDERRATCHETKEY_FIELD_NUMBER = 1; + private com.google.protobuf.ByteString senderRatchetKey_; /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - public boolean hasSenderEphemeral() { + public boolean hasSenderRatchetKey() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - public com.google.protobuf.ByteString getSenderEphemeral() { - return senderEphemeral_; + public com.google.protobuf.ByteString getSenderRatchetKey() { + return senderRatchetKey_; } - // optional bytes senderEphemeralPrivate = 2; - public static final int SENDEREPHEMERALPRIVATE_FIELD_NUMBER = 2; - private com.google.protobuf.ByteString senderEphemeralPrivate_; + // optional bytes senderRatchetKeyPrivate = 2; + public static final int SENDERRATCHETKEYPRIVATE_FIELD_NUMBER = 2; + private com.google.protobuf.ByteString senderRatchetKeyPrivate_; /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - public boolean hasSenderEphemeralPrivate() { + public boolean hasSenderRatchetKeyPrivate() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - public com.google.protobuf.ByteString getSenderEphemeralPrivate() { - return senderEphemeralPrivate_; + public com.google.protobuf.ByteString getSenderRatchetKeyPrivate() { + return senderRatchetKeyPrivate_; } // optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3; @@ -1690,8 +1690,8 @@ public final class StorageProtos { } private void initFields() { - senderEphemeral_ = com.google.protobuf.ByteString.EMPTY; - senderEphemeralPrivate_ = com.google.protobuf.ByteString.EMPTY; + senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY; + senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance(); messageKeys_ = java.util.Collections.emptyList(); } @@ -1708,10 +1708,10 @@ public final class StorageProtos { throws java.io.IOException { getSerializedSize(); if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, senderEphemeral_); + output.writeBytes(1, senderRatchetKey_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, senderEphemeralPrivate_); + output.writeBytes(2, senderRatchetKeyPrivate_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { output.writeMessage(3, chainKey_); @@ -1730,11 +1730,11 @@ public final class StorageProtos { size = 0; if (((bitField0_ & 0x00000001) == 0x00000001)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, senderEphemeral_); + .computeBytesSize(1, senderRatchetKey_); } if (((bitField0_ & 0x00000002) == 0x00000002)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, senderEphemeralPrivate_); + .computeBytesSize(2, senderRatchetKeyPrivate_); } if (((bitField0_ & 0x00000004) == 0x00000004)) { size += com.google.protobuf.CodedOutputStream @@ -1862,9 +1862,9 @@ public final class StorageProtos { public Builder clear() { super.clear(); - senderEphemeral_ = com.google.protobuf.ByteString.EMPTY; + senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000001); - senderEphemeralPrivate_ = com.google.protobuf.ByteString.EMPTY; + senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000002); if (chainKeyBuilder_ == null) { chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance(); @@ -1909,11 +1909,11 @@ public final class StorageProtos { if (((from_bitField0_ & 0x00000001) == 0x00000001)) { to_bitField0_ |= 0x00000001; } - result.senderEphemeral_ = senderEphemeral_; + result.senderRatchetKey_ = senderRatchetKey_; if (((from_bitField0_ & 0x00000002) == 0x00000002)) { to_bitField0_ |= 0x00000002; } - result.senderEphemeralPrivate_ = senderEphemeralPrivate_; + result.senderRatchetKeyPrivate_ = senderRatchetKeyPrivate_; if (((from_bitField0_ & 0x00000004) == 0x00000004)) { to_bitField0_ |= 0x00000004; } @@ -1947,11 +1947,11 @@ public final class StorageProtos { public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain other) { if (other == org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance()) return this; - if (other.hasSenderEphemeral()) { - setSenderEphemeral(other.getSenderEphemeral()); + if (other.hasSenderRatchetKey()) { + setSenderRatchetKey(other.getSenderRatchetKey()); } - if (other.hasSenderEphemeralPrivate()) { - setSenderEphemeralPrivate(other.getSenderEphemeralPrivate()); + if (other.hasSenderRatchetKeyPrivate()) { + setSenderRatchetKeyPrivate(other.getSenderRatchetKeyPrivate()); } if (other.hasChainKey()) { mergeChainKey(other.getChainKey()); @@ -2009,74 +2009,74 @@ public final class StorageProtos { } private int bitField0_; - // optional bytes senderEphemeral = 1; - private com.google.protobuf.ByteString senderEphemeral_ = com.google.protobuf.ByteString.EMPTY; + // optional bytes senderRatchetKey = 1; + private com.google.protobuf.ByteString senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY; /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - public boolean hasSenderEphemeral() { + public boolean hasSenderRatchetKey() { return ((bitField0_ & 0x00000001) == 0x00000001); } /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - public com.google.protobuf.ByteString getSenderEphemeral() { - return senderEphemeral_; + public com.google.protobuf.ByteString getSenderRatchetKey() { + return senderRatchetKey_; } /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - public Builder setSenderEphemeral(com.google.protobuf.ByteString value) { + public Builder setSenderRatchetKey(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000001; - senderEphemeral_ = value; + senderRatchetKey_ = value; onChanged(); return this; } /** - * optional bytes senderEphemeral = 1; + * optional bytes senderRatchetKey = 1; */ - public Builder clearSenderEphemeral() { + public Builder clearSenderRatchetKey() { bitField0_ = (bitField0_ & ~0x00000001); - senderEphemeral_ = getDefaultInstance().getSenderEphemeral(); + senderRatchetKey_ = getDefaultInstance().getSenderRatchetKey(); onChanged(); return this; } - // optional bytes senderEphemeralPrivate = 2; - private com.google.protobuf.ByteString senderEphemeralPrivate_ = com.google.protobuf.ByteString.EMPTY; + // optional bytes senderRatchetKeyPrivate = 2; + private com.google.protobuf.ByteString senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - public boolean hasSenderEphemeralPrivate() { + public boolean hasSenderRatchetKeyPrivate() { return ((bitField0_ & 0x00000002) == 0x00000002); } /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - public com.google.protobuf.ByteString getSenderEphemeralPrivate() { - return senderEphemeralPrivate_; + public com.google.protobuf.ByteString getSenderRatchetKeyPrivate() { + return senderRatchetKeyPrivate_; } /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - public Builder setSenderEphemeralPrivate(com.google.protobuf.ByteString value) { + public Builder setSenderRatchetKeyPrivate(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000002; - senderEphemeralPrivate_ = value; + senderRatchetKeyPrivate_ = value; onChanged(); return this; } /** - * optional bytes senderEphemeralPrivate = 2; + * optional bytes senderRatchetKeyPrivate = 2; */ - public Builder clearSenderEphemeralPrivate() { + public Builder clearSenderRatchetKeyPrivate() { bitField0_ = (bitField0_ & ~0x00000002); - senderEphemeralPrivate_ = getDefaultInstance().getSenderEphemeralPrivate(); + senderRatchetKeyPrivate_ = getDefaultInstance().getSenderRatchetKeyPrivate(); onChanged(); return this; } @@ -2482,25 +2482,25 @@ public final class StorageProtos { */ com.google.protobuf.ByteString getLocalBaseKeyPrivate(); - // optional bytes localEphemeralKey = 4; + // optional bytes localRatchetKey = 4; /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - boolean hasLocalEphemeralKey(); + boolean hasLocalRatchetKey(); /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - com.google.protobuf.ByteString getLocalEphemeralKey(); + com.google.protobuf.ByteString getLocalRatchetKey(); - // optional bytes localEphemeralKeyPrivate = 5; + // optional bytes localRatchetKeyPrivate = 5; /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - boolean hasLocalEphemeralKeyPrivate(); + boolean hasLocalRatchetKeyPrivate(); /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - com.google.protobuf.ByteString getLocalEphemeralKeyPrivate(); + com.google.protobuf.ByteString getLocalRatchetKeyPrivate(); // optional bytes localIdentityKey = 7; /** @@ -2590,12 +2590,12 @@ public final class StorageProtos { } case 34: { bitField0_ |= 0x00000008; - localEphemeralKey_ = input.readBytes(); + localRatchetKey_ = input.readBytes(); break; } case 42: { bitField0_ |= 0x00000010; - localEphemeralKeyPrivate_ = input.readBytes(); + localRatchetKeyPrivate_ = input.readBytes(); break; } case 58: { @@ -2696,36 +2696,36 @@ public final class StorageProtos { return localBaseKeyPrivate_; } - // optional bytes localEphemeralKey = 4; - public static final int LOCALEPHEMERALKEY_FIELD_NUMBER = 4; - private com.google.protobuf.ByteString localEphemeralKey_; + // optional bytes localRatchetKey = 4; + public static final int LOCALRATCHETKEY_FIELD_NUMBER = 4; + private com.google.protobuf.ByteString localRatchetKey_; /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - public boolean hasLocalEphemeralKey() { + public boolean hasLocalRatchetKey() { return ((bitField0_ & 0x00000008) == 0x00000008); } /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - public com.google.protobuf.ByteString getLocalEphemeralKey() { - return localEphemeralKey_; + public com.google.protobuf.ByteString getLocalRatchetKey() { + return localRatchetKey_; } - // optional bytes localEphemeralKeyPrivate = 5; - public static final int LOCALEPHEMERALKEYPRIVATE_FIELD_NUMBER = 5; - private com.google.protobuf.ByteString localEphemeralKeyPrivate_; + // optional bytes localRatchetKeyPrivate = 5; + public static final int LOCALRATCHETKEYPRIVATE_FIELD_NUMBER = 5; + private com.google.protobuf.ByteString localRatchetKeyPrivate_; /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - public boolean hasLocalEphemeralKeyPrivate() { + public boolean hasLocalRatchetKeyPrivate() { return ((bitField0_ & 0x00000010) == 0x00000010); } /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - public com.google.protobuf.ByteString getLocalEphemeralKeyPrivate() { - return localEphemeralKeyPrivate_; + public com.google.protobuf.ByteString getLocalRatchetKeyPrivate() { + return localRatchetKeyPrivate_; } // optional bytes localIdentityKey = 7; @@ -2764,8 +2764,8 @@ public final class StorageProtos { sequence_ = 0; localBaseKey_ = com.google.protobuf.ByteString.EMPTY; localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; - localEphemeralKey_ = com.google.protobuf.ByteString.EMPTY; - localEphemeralKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; + localRatchetKey_ = com.google.protobuf.ByteString.EMPTY; + localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; localIdentityKey_ = com.google.protobuf.ByteString.EMPTY; localIdentityKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; } @@ -2791,10 +2791,10 @@ public final class StorageProtos { output.writeBytes(3, localBaseKeyPrivate_); } if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeBytes(4, localEphemeralKey_); + output.writeBytes(4, localRatchetKey_); } if (((bitField0_ & 0x00000010) == 0x00000010)) { - output.writeBytes(5, localEphemeralKeyPrivate_); + output.writeBytes(5, localRatchetKeyPrivate_); } if (((bitField0_ & 0x00000020) == 0x00000020)) { output.writeBytes(7, localIdentityKey_); @@ -2825,11 +2825,11 @@ public final class StorageProtos { } if (((bitField0_ & 0x00000008) == 0x00000008)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(4, localEphemeralKey_); + .computeBytesSize(4, localRatchetKey_); } if (((bitField0_ & 0x00000010) == 0x00000010)) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(5, localEphemeralKeyPrivate_); + .computeBytesSize(5, localRatchetKeyPrivate_); } if (((bitField0_ & 0x00000020) == 0x00000020)) { size += com.google.protobuf.CodedOutputStream @@ -2961,9 +2961,9 @@ public final class StorageProtos { bitField0_ = (bitField0_ & ~0x00000002); localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000004); - localEphemeralKey_ = com.google.protobuf.ByteString.EMPTY; + localRatchetKey_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000008); - localEphemeralKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; + localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000010); localIdentityKey_ = com.google.protobuf.ByteString.EMPTY; bitField0_ = (bitField0_ & ~0x00000020); @@ -3012,11 +3012,11 @@ public final class StorageProtos { if (((from_bitField0_ & 0x00000008) == 0x00000008)) { to_bitField0_ |= 0x00000008; } - result.localEphemeralKey_ = localEphemeralKey_; + result.localRatchetKey_ = localRatchetKey_; if (((from_bitField0_ & 0x00000010) == 0x00000010)) { to_bitField0_ |= 0x00000010; } - result.localEphemeralKeyPrivate_ = localEphemeralKeyPrivate_; + result.localRatchetKeyPrivate_ = localRatchetKeyPrivate_; if (((from_bitField0_ & 0x00000020) == 0x00000020)) { to_bitField0_ |= 0x00000020; } @@ -3050,11 +3050,11 @@ public final class StorageProtos { if (other.hasLocalBaseKeyPrivate()) { setLocalBaseKeyPrivate(other.getLocalBaseKeyPrivate()); } - if (other.hasLocalEphemeralKey()) { - setLocalEphemeralKey(other.getLocalEphemeralKey()); + if (other.hasLocalRatchetKey()) { + setLocalRatchetKey(other.getLocalRatchetKey()); } - if (other.hasLocalEphemeralKeyPrivate()) { - setLocalEphemeralKeyPrivate(other.getLocalEphemeralKeyPrivate()); + if (other.hasLocalRatchetKeyPrivate()) { + setLocalRatchetKeyPrivate(other.getLocalRatchetKeyPrivate()); } if (other.hasLocalIdentityKey()) { setLocalIdentityKey(other.getLocalIdentityKey()); @@ -3194,74 +3194,74 @@ public final class StorageProtos { return this; } - // optional bytes localEphemeralKey = 4; - private com.google.protobuf.ByteString localEphemeralKey_ = com.google.protobuf.ByteString.EMPTY; + // optional bytes localRatchetKey = 4; + private com.google.protobuf.ByteString localRatchetKey_ = com.google.protobuf.ByteString.EMPTY; /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - public boolean hasLocalEphemeralKey() { + public boolean hasLocalRatchetKey() { return ((bitField0_ & 0x00000008) == 0x00000008); } /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - public com.google.protobuf.ByteString getLocalEphemeralKey() { - return localEphemeralKey_; + public com.google.protobuf.ByteString getLocalRatchetKey() { + return localRatchetKey_; } /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - public Builder setLocalEphemeralKey(com.google.protobuf.ByteString value) { + public Builder setLocalRatchetKey(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000008; - localEphemeralKey_ = value; + localRatchetKey_ = value; onChanged(); return this; } /** - * optional bytes localEphemeralKey = 4; + * optional bytes localRatchetKey = 4; */ - public Builder clearLocalEphemeralKey() { + public Builder clearLocalRatchetKey() { bitField0_ = (bitField0_ & ~0x00000008); - localEphemeralKey_ = getDefaultInstance().getLocalEphemeralKey(); + localRatchetKey_ = getDefaultInstance().getLocalRatchetKey(); onChanged(); return this; } - // optional bytes localEphemeralKeyPrivate = 5; - private com.google.protobuf.ByteString localEphemeralKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; + // optional bytes localRatchetKeyPrivate = 5; + private com.google.protobuf.ByteString localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - public boolean hasLocalEphemeralKeyPrivate() { + public boolean hasLocalRatchetKeyPrivate() { return ((bitField0_ & 0x00000010) == 0x00000010); } /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - public com.google.protobuf.ByteString getLocalEphemeralKeyPrivate() { - return localEphemeralKeyPrivate_; + public com.google.protobuf.ByteString getLocalRatchetKeyPrivate() { + return localRatchetKeyPrivate_; } /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - public Builder setLocalEphemeralKeyPrivate(com.google.protobuf.ByteString value) { + public Builder setLocalRatchetKeyPrivate(com.google.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } bitField0_ |= 0x00000010; - localEphemeralKeyPrivate_ = value; + localRatchetKeyPrivate_ = value; onChanged(); return this; } /** - * optional bytes localEphemeralKeyPrivate = 5; + * optional bytes localRatchetKeyPrivate = 5; */ - public Builder clearLocalEphemeralKeyPrivate() { + public Builder clearLocalRatchetKeyPrivate() { bitField0_ = (bitField0_ & ~0x00000010); - localEphemeralKeyPrivate_ = getDefaultInstance().getLocalEphemeralKeyPrivate(); + localRatchetKeyPrivate_ = getDefaultInstance().getLocalRatchetKeyPrivate(); onChanged(); return this; } @@ -8333,7 +8333,7 @@ public final class StorageProtos { static { java.lang.String[] descriptorData = { "\n\032LocalStorageProtocol.proto\022\ntextsecure" + - "\"\337\010\n\020SessionStructure\022\026\n\016sessionVersion\030" + + "\"\335\010\n\020SessionStructure\022\026\n\016sessionVersion\030" + "\001 \001(\r\022\033\n\023localIdentityPublic\030\002 \001(\014\022\034\n\024re" + "moteIdentityPublic\030\003 \001(\014\022\017\n\007rootKey\030\004 \001(" + "\014\022\027\n\017previousCounter\030\005 \001(\r\0227\n\013senderChai" + @@ -8346,33 +8346,33 @@ public final class StorageProtos { "gPreKey\022\034\n\024remoteRegistrationId\030\n \001(\r\022\033\n" + "\023localRegistrationId\030\013 \001(\r\022\024\n\014needsRefre" + "sh\030\014 \001(\010\022\024\n\014aliceBaseKey\030\r \001(\014\022\024\n\014verifi" + - "cation\030\016 \001(\014\032\253\002\n\005Chain\022\027\n\017senderEphemera" + - "l\030\001 \001(\014\022\036\n\026senderEphemeralPrivate\030\002 \001(\014\022" + - "=\n\010chainKey\030\003 \001(\0132+.textsecure.SessionSt" + - "ructure.Chain.ChainKey\022B\n\013messageKeys\030\004 " + - "\003(\0132-.textsecure.SessionStructure.Chain." + - "MessageKey\032&\n\010ChainKey\022\r\n\005index\030\001 \001(\r\022\013\n", - "\003key\030\002 \001(\014\032>\n\nMessageKey\022\r\n\005index\030\001 \001(\r\022" + - "\021\n\tcipherKey\030\002 \001(\014\022\016\n\006macKey\030\003 \001(\014\032\321\001\n\022P" + - "endingKeyExchange\022\020\n\010sequence\030\001 \001(\r\022\024\n\014l" + - "ocalBaseKey\030\002 \001(\014\022\033\n\023localBaseKeyPrivate" + - "\030\003 \001(\014\022\031\n\021localEphemeralKey\030\004 \001(\014\022 \n\030loc" + - "alEphemeralKeyPrivate\030\005 \001(\014\022\030\n\020localIden" + - "tityKey\030\007 \001(\014\022\037\n\027localIdentityKeyPrivate" + - "\030\010 \001(\014\032J\n\rPendingPreKey\022\020\n\010preKeyId\030\001 \001(" + - "\r\022\026\n\016signedPreKeyId\030\003 \001(\005\022\017\n\007baseKey\030\002 \001" + - "(\014\"\177\n\017RecordStructure\0224\n\016currentSession\030", - "\001 \001(\0132\034.textsecure.SessionStructure\0226\n\020p" + - "reviousSessions\030\002 \003(\0132\034.textsecure.Sessi" + - "onStructure\"J\n\025PreKeyRecordStructure\022\n\n\002" + + "cation\030\016 \001(\014\032\255\002\n\005Chain\022\030\n\020senderRatchetK" + + "ey\030\001 \001(\014\022\037\n\027senderRatchetKeyPrivate\030\002 \001(" + + "\014\022=\n\010chainKey\030\003 \001(\0132+.textsecure.Session" + + "Structure.Chain.ChainKey\022B\n\013messageKeys\030" + + "\004 \003(\0132-.textsecure.SessionStructure.Chai" + + "n.MessageKey\032&\n\010ChainKey\022\r\n\005index\030\001 \001(\r\022", + "\013\n\003key\030\002 \001(\014\032>\n\nMessageKey\022\r\n\005index\030\001 \001(" + + "\r\022\021\n\tcipherKey\030\002 \001(\014\022\016\n\006macKey\030\003 \001(\014\032\315\001\n" + + "\022PendingKeyExchange\022\020\n\010sequence\030\001 \001(\r\022\024\n" + + "\014localBaseKey\030\002 \001(\014\022\033\n\023localBaseKeyPriva" + + "te\030\003 \001(\014\022\027\n\017localRatchetKey\030\004 \001(\014\022\036\n\026loc" + + "alRatchetKeyPrivate\030\005 \001(\014\022\030\n\020localIdenti" + + "tyKey\030\007 \001(\014\022\037\n\027localIdentityKeyPrivate\030\010" + + " \001(\014\032J\n\rPendingPreKey\022\020\n\010preKeyId\030\001 \001(\r\022" + + "\026\n\016signedPreKeyId\030\003 \001(\005\022\017\n\007baseKey\030\002 \001(\014" + + "\"\177\n\017RecordStructure\0224\n\016currentSession\030\001 ", + "\001(\0132\034.textsecure.SessionStructure\0226\n\020pre" + + "viousSessions\030\002 \003(\0132\034.textsecure.Session" + + "Structure\"J\n\025PreKeyRecordStructure\022\n\n\002id" + + "\030\001 \001(\r\022\021\n\tpublicKey\030\002 \001(\014\022\022\n\nprivateKey\030" + + "\003 \001(\014\"v\n\033SignedPreKeyRecordStructure\022\n\n\002" + "id\030\001 \001(\r\022\021\n\tpublicKey\030\002 \001(\014\022\022\n\nprivateKe" + - "y\030\003 \001(\014\"v\n\033SignedPreKeyRecordStructure\022\n" + - "\n\002id\030\001 \001(\r\022\021\n\tpublicKey\030\002 \001(\014\022\022\n\nprivate" + - "Key\030\003 \001(\014\022\021\n\tsignature\030\004 \001(\014\022\021\n\ttimestam" + - "p\030\005 \001(\006\"A\n\030IdentityKeyPairStructure\022\021\n\tp" + - "ublicKey\030\001 \001(\014\022\022\n\nprivateKey\030\002 \001(\014B4\n#or" + - "g.whispersystems.libaxolotl.stateB\rStora", - "geProtos" + "y\030\003 \001(\014\022\021\n\tsignature\030\004 \001(\014\022\021\n\ttimestamp\030" + + "\005 \001(\006\"A\n\030IdentityKeyPairStructure\022\021\n\tpub" + + "licKey\030\001 \001(\014\022\022\n\nprivateKey\030\002 \001(\014B4\n#org." + + "whispersystems.libaxolotl.stateB\rStorage", + "Protos" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -8390,7 +8390,7 @@ public final class StorageProtos { internal_static_textsecure_SessionStructure_Chain_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_textsecure_SessionStructure_Chain_descriptor, - new java.lang.String[] { "SenderEphemeral", "SenderEphemeralPrivate", "ChainKey", "MessageKeys", }); + new java.lang.String[] { "SenderRatchetKey", "SenderRatchetKeyPrivate", "ChainKey", "MessageKeys", }); internal_static_textsecure_SessionStructure_Chain_ChainKey_descriptor = internal_static_textsecure_SessionStructure_Chain_descriptor.getNestedTypes().get(0); internal_static_textsecure_SessionStructure_Chain_ChainKey_fieldAccessorTable = new @@ -8408,7 +8408,7 @@ public final class StorageProtos { internal_static_textsecure_SessionStructure_PendingKeyExchange_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor, - new java.lang.String[] { "Sequence", "LocalBaseKey", "LocalBaseKeyPrivate", "LocalEphemeralKey", "LocalEphemeralKeyPrivate", "LocalIdentityKey", "LocalIdentityKeyPrivate", }); + new java.lang.String[] { "Sequence", "LocalBaseKey", "LocalBaseKeyPrivate", "LocalRatchetKey", "LocalRatchetKeyPrivate", "LocalIdentityKey", "LocalIdentityKeyPrivate", }); internal_static_textsecure_SessionStructure_PendingPreKey_descriptor = internal_static_textsecure_SessionStructure_descriptor.getNestedTypes().get(2); internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable = new