Rename axolotl terminology.

1) ephemeralKey -> ratchetKey

2) Have the caller specify Alice/Bob orientation.

3) Reorganize verification tag.

4) Remove verification tag from key exchange messages, replace
   with signatures in both directions.
This commit is contained in:
Moxie Marlinspike 2014-07-23 01:00:32 -07:00
parent 82bd75fb75
commit 641ac9aed9
18 changed files with 962 additions and 828 deletions

View File

@ -5,8 +5,8 @@ option java_outer_classname = "StorageProtos";
message SessionStructure { message SessionStructure {
message Chain { message Chain {
optional bytes senderEphemeral = 1; optional bytes senderRatchetKey = 1;
optional bytes senderEphemeralPrivate = 2; optional bytes senderRatchetKeyPrivate = 2;
message ChainKey { message ChainKey {
optional uint32 index = 1; optional uint32 index = 1;
@ -28,8 +28,8 @@ message SessionStructure {
optional uint32 sequence = 1; optional uint32 sequence = 1;
optional bytes localBaseKey = 2; optional bytes localBaseKey = 2;
optional bytes localBaseKeyPrivate = 3; optional bytes localBaseKeyPrivate = 3;
optional bytes localEphemeralKey = 4; optional bytes localRatchetKey = 4;
optional bytes localEphemeralKeyPrivate = 5; optional bytes localRatchetKeyPrivate = 5;
optional bytes localIdentityKey = 7; optional bytes localIdentityKey = 7;
optional bytes localIdentityKeyPrivate = 8; optional bytes localIdentityKeyPrivate = 8;
} }

View File

@ -4,7 +4,7 @@ option java_package = "org.whispersystems.libaxolotl.protocol";
option java_outer_classname = "WhisperProtos"; option java_outer_classname = "WhisperProtos";
message WhisperMessage { message WhisperMessage {
optional bytes ephemeralKey = 1; optional bytes ratchetKey = 1;
optional uint32 counter = 2; optional uint32 counter = 2;
optional uint32 previousCounter = 3; optional uint32 previousCounter = 3;
optional bytes ciphertext = 4; optional bytes ciphertext = 4;
@ -23,8 +23,7 @@ message PreKeyWhisperMessage {
message KeyExchangeMessage { message KeyExchangeMessage {
optional uint32 id = 1; optional uint32 id = 1;
optional bytes baseKey = 2; optional bytes baseKey = 2;
optional bytes ephemeralKey = 3; optional bytes ratchetKey = 3;
optional bytes identityKey = 4; optional bytes identityKey = 4;
optional bytes baseKeySignature = 5; optional bytes baseKeySignature = 5;
optional bytes verification = 6;
} }

View File

@ -154,7 +154,8 @@ public class SessionBuilderTest extends AndroidTestCase {
PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1, PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
31337, bobPreKeyPair.getPublicKey(), 31337, bobPreKeyPair.getPublicKey(),
22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature, 22, bobSignedPreKeyPair.getPublicKey(),
bobSignedPreKeySignature,
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey()); bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
aliceSessionBuilder.process(bobPreKey); aliceSessionBuilder.process(bobPreKey);

View File

@ -15,6 +15,8 @@ import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPublicKey; import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage; import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
import org.whispersystems.libaxolotl.protocol.WhisperMessage; 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.ratchet.RatchetingSession;
import org.whispersystems.libaxolotl.state.IdentityKeyStore; import org.whispersystems.libaxolotl.state.IdentityKeyStore;
import org.whispersystems.libaxolotl.state.PreKeyStore; import org.whispersystems.libaxolotl.state.PreKeyStore;
@ -31,7 +33,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import static org.whispersystems.libaxolotl.ratchet.RatchetingSession.AxolotlParameters;
public class SessionCipherTest extends AndroidTestCase { public class SessionCipherTest extends AndroidTestCase {
@ -149,30 +150,23 @@ public class SessionCipherTest extends AndroidTestCase {
ECKeyPair bobBaseKey = Curve.generateKeyPair(true); ECKeyPair bobBaseKey = Curve.generateKeyPair(true);
ECKeyPair bobEphemeralKey = bobBaseKey; ECKeyPair bobEphemeralKey = bobBaseKey;
AxolotlParameters aliceParameters = AliceAxolotlParameters aliceParameters = AliceAxolotlParameters.newBuilder()
AxolotlParameters.newBuilder() .setOurIdentityKey(aliceIdentityKey)
.setOurIdentityKey(aliceIdentityKey) .setOurBaseKey(aliceBaseKey)
.setOurBaseKey(aliceBaseKey) .setTheirIdentityKey(bobIdentityKey.getPublicKey())
.setOurEphemeralKey(aliceEphemeralKey) .setTheirSignedPreKey(bobEphemeralKey.getPublicKey())
.setOurPreKey(Optional.<ECKeyPair>absent()) .setTheirRatchetKey(bobEphemeralKey.getPublicKey())
.setTheirIdentityKey(bobIdentityKey.getPublicKey()) .setTheirOneTimePreKey(Optional.<ECPublicKey>absent())
.setTheirBaseKey(bobBaseKey.getPublicKey()) .create();
.setTheirEphemeralKey(bobEphemeralKey.getPublicKey())
.setTheirPreKey(Optional.<ECPublicKey>absent())
.create();
AxolotlParameters bobParameters =
RatchetingSession.AxolotlParameters.newBuilder()
.setOurIdentityKey(bobIdentityKey)
.setOurBaseKey(bobBaseKey)
.setOurEphemeralKey(bobEphemeralKey)
.setOurPreKey(Optional.<ECKeyPair>absent())
.setTheirIdentityKey(aliceIdentityKey.getPublicKey())
.setTheirBaseKey(aliceBaseKey.getPublicKey())
.setTheirEphemeralKey(aliceEphemeralKey.getPublicKey())
.setTheirPreKey(Optional.<ECPublicKey>absent())
.create();
BobAxolotlParameters bobParameters = BobAxolotlParameters.newBuilder()
.setOurIdentityKey(bobIdentityKey)
.setOurOneTimePreKey(Optional.<ECKeyPair>absent())
.setOurRatchetKey(bobEphemeralKey)
.setOurSignedPreKey(bobBaseKey)
.setTheirBaseKey(aliceBaseKey.getPublicKey())
.setTheirIdentityKey(aliceIdentityKey.getPublicKey())
.create();
RatchetingSession.initializeSession(aliceSessionState, 2, aliceParameters); RatchetingSession.initializeSession(aliceSessionState, 2, aliceParameters);
RatchetingSession.initializeSession(bobSessionState, 2, bobParameters); RatchetingSession.initializeSession(bobSessionState, 2, bobParameters);
@ -197,33 +191,25 @@ public class SessionCipherTest extends AndroidTestCase {
ECKeyPair bobPreKey = Curve.generateKeyPair(true); ECKeyPair bobPreKey = Curve.generateKeyPair(true);
AxolotlParameters aliceParameters = AliceAxolotlParameters aliceParameters = AliceAxolotlParameters.newBuilder()
AxolotlParameters.newBuilder() .setOurBaseKey(aliceBaseKey)
.setOurIdentityKey(aliceIdentityKey) .setOurIdentityKey(aliceIdentityKey)
.setOurBaseKey(aliceBaseKey) .setTheirOneTimePreKey(Optional.<ECPublicKey>absent())
.setOurEphemeralKey(aliceEphemeralKey) .setTheirRatchetKey(bobEphemeralKey.getPublicKey())
.setOurPreKey(Optional.of(alicePreKey)) .setTheirSignedPreKey(bobBaseKey.getPublicKey())
.setTheirIdentityKey(bobIdentityKey.getPublicKey()) .setTheirIdentityKey(bobIdentityKey.getPublicKey())
.setTheirBaseKey(bobBaseKey.getPublicKey()) .create();
.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();
BobAxolotlParameters bobParameters = BobAxolotlParameters.newBuilder()
.setOurRatchetKey(bobEphemeralKey)
.setOurSignedPreKey(bobBaseKey)
.setOurOneTimePreKey(Optional.<ECKeyPair>absent())
.setOurIdentityKey(bobIdentityKey)
.setTheirIdentityKey(aliceIdentityKey.getPublicKey())
.setTheirBaseKey(aliceBaseKey.getPublicKey())
.create();
RatchetingSession.initializeSession(aliceSessionState, 3, aliceParameters); RatchetingSession.initializeSession(aliceSessionState, 3, aliceParameters);
RatchetingSession.initializeSession(bobSessionState, 3, bobParameters); RatchetingSession.initializeSession(bobSessionState, 3, bobParameters);
} }
} }

View File

@ -9,14 +9,14 @@ import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair; import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPrivateKey; import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
import org.whispersystems.libaxolotl.ecc.ECPublicKey; 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.ratchet.RatchetingSession;
import org.whispersystems.libaxolotl.state.SessionState; import org.whispersystems.libaxolotl.state.SessionState;
import org.whispersystems.libaxolotl.util.guava.Optional; import org.whispersystems.libaxolotl.util.guava.Optional;
import java.util.Arrays; import java.util.Arrays;
import static org.whispersystems.libaxolotl.ratchet.RatchetingSession.AxolotlParameters;
public class RatchetingSessionTest extends AndroidTestCase { public class RatchetingSessionTest extends AndroidTestCase {
public void testRatchetingSessionAsBob() throws InvalidKeyException { public void testRatchetingSessionAsBob() throws InvalidKeyException {
@ -108,20 +108,17 @@ public class RatchetingSessionTest extends AndroidTestCase {
ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0); ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0);
IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0); IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0);
AxolotlParameters parameters = AxolotlParameters.newBuilder() BobAxolotlParameters parameters = BobAxolotlParameters.newBuilder()
.setOurBaseKey(bobBaseKey) .setOurIdentityKey(bobIdentityKey)
.setOurEphemeralKey(bobEphemeralKey) .setOurSignedPreKey(bobBaseKey)
.setOurIdentityKey(bobIdentityKey) .setOurRatchetKey(bobEphemeralKey)
.setOurPreKey(Optional.<ECKeyPair>absent()) .setOurOneTimePreKey(Optional.<ECKeyPair>absent())
.setTheirBaseKey(aliceBasePublicKey) .setTheirIdentityKey(aliceIdentityPublicKey)
.setTheirEphemeralKey(aliceEphemeralPublicKey) .setTheirBaseKey(aliceBasePublicKey)
.setTheirIdentityKey(aliceIdentityPublicKey) .create();
.setTheirPreKey(Optional.<ECPublicKey>absent())
.create();
SessionState session = new SessionState(); SessionState session = new SessionState();
RatchetingSession.initializeSession(session, 2, parameters); RatchetingSession.initializeSession(session, 2, parameters);
assertTrue(session.getLocalIdentityKey().equals(bobIdentityKey.getPublicKey())); assertTrue(session.getLocalIdentityKey().equals(bobIdentityKey.getPublicKey()));
@ -217,16 +214,14 @@ public class RatchetingSessionTest extends AndroidTestCase {
SessionState session = new SessionState(); SessionState session = new SessionState();
AxolotlParameters parameters = AxolotlParameters.newBuilder() AliceAxolotlParameters parameters = AliceAxolotlParameters.newBuilder()
.setOurBaseKey(aliceBaseKey) .setOurBaseKey(aliceBaseKey)
.setOurEphemeralKey(aliceEphemeralKey) .setOurIdentityKey(aliceIdentityKey)
.setOurIdentityKey(aliceIdentityKey) .setTheirIdentityKey(bobIdentityKey)
.setOurPreKey(Optional.<ECKeyPair>absent()) .setTheirSignedPreKey(bobBasePublicKey)
.setTheirBaseKey(bobBasePublicKey) .setTheirRatchetKey(bobEphemeralPublicKey)
.setTheirEphemeralKey(bobEphemeralPublicKey) .setTheirOneTimePreKey(Optional.<ECPublicKey>absent())
.setTheirIdentityKey(bobIdentityKey) .create();
.setTheirPreKey(Optional.<ECPublicKey>absent())
.create();
RatchetingSession.initializeSession(session, 2, parameters); RatchetingSession.initializeSession(session, 2, parameters);

View File

@ -3,6 +3,7 @@ package org.whispersystems.test.ratchet;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.util.Log; import android.util.Log;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.InvalidKeyException; import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.ecc.Curve; import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECPublicKey; 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)0x79, (byte)0x00, (byte)0xef, (byte)0x1b, (byte)0x40,
(byte)0x0f, (byte)0xdc}; (byte)0x0f, (byte)0xdc};
byte[] expectedTag = {(byte)0x2f, (byte)0x77, (byte)0xaf, (byte)0xad, (byte)0x5b, byte[] expectedTag = {(byte)0xd3, (byte)0x62, (byte)0x84, (byte)0x3c,
(byte)0x96, (byte)0xf5, (byte)0x3c}; (byte)0x9d, (byte)0x59, (byte)0x8c, (byte)0x6f};
ECPublicKey aliceBaseKey = Curve.decodePoint(aliceBaseKeyBytes, 0); ECPublicKey aliceBaseKey = Curve.decodePoint(aliceBaseKeyBytes, 0);
ECPublicKey alicePreKey = aliceBaseKey; ECPublicKey alicePreKey = aliceBaseKey;
@ -77,9 +78,11 @@ public class VerifyKeyTest extends AndroidTestCase {
ECPublicKey bobIdentityKey = Curve.decodePoint(bobIdentityKeyBytes, 0); ECPublicKey bobIdentityKey = Curve.decodePoint(bobIdentityKeyBytes, 0);
VerifyKey verifyKey = new VerifyKey(key); VerifyKey verifyKey = new VerifyKey(key);
byte[] verification = verifyKey.generateVerification(aliceBaseKey, Optional.of(alicePreKey),
aliceIdentityKey, bobBaseKey, byte[] verification = verifyKey.generateVerification(new IdentityKey(aliceIdentityKey),
Optional.of(bobPreKey), bobIdentityKey); new IdentityKey(bobIdentityKey),
aliceBaseKey, bobBaseKey,
Optional.of(bobPreKey));
assertTrue(MessageDigest.isEqual(verification, expectedTag)); assertTrue(MessageDigest.isEqual(verification, expectedTag));
} }

View File

@ -8,7 +8,10 @@ import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage; import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage; import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage;
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage; 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.RatchetingSession;
import org.whispersystems.libaxolotl.ratchet.SymmetricAxolotlParameters;
import org.whispersystems.libaxolotl.state.IdentityKeyStore; import org.whispersystems.libaxolotl.state.IdentityKeyStore;
import org.whispersystems.libaxolotl.state.PreKeyBundle; import org.whispersystems.libaxolotl.state.PreKeyBundle;
import org.whispersystems.libaxolotl.state.PreKeyStore; import org.whispersystems.libaxolotl.state.PreKeyStore;
@ -22,8 +25,6 @@ import org.whispersystems.libaxolotl.util.guava.Optional;
import java.security.MessageDigest; import java.security.MessageDigest;
import static org.whispersystems.libaxolotl.ratchet.RatchetingSession.AxolotlParameters;
/** /**
* SessionBuilder is responsible for setting up encrypted sessions. * SessionBuilder is responsible for setting up encrypted sessions.
* Once a session has been established, {@link org.whispersystems.libaxolotl.SessionCipher} * Once a session has been established, {@link org.whispersystems.libaxolotl.SessionCipher}
@ -120,21 +121,22 @@ public class SessionBuilder {
return false; 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.setTheirBaseKey(message.getBaseKey())
parameters.setTheirEphemeralKey(message.getWhisperMessage().getSenderEphemeral()); .setTheirIdentityKey(message.getIdentityKey())
parameters.setTheirPreKey(Optional.of(message.getBaseKey())); .setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
parameters.setTheirIdentityKey(message.getIdentityKey()); .setOurSignedPreKey(ourSignedPreKey)
.setOurRatchetKey(ourSignedPreKey);
parameters.setOurBaseKey(signedPreKeyStore.loadSignedPreKey(message.getSignedPreKeyId()).getKeyPair()); if (message.getPreKeyId() >= 0) {
parameters.setOurEphemeralKey(parameters.getOurBaseKey()); parameters.setOurOneTimePreKey(Optional.of(preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair()));
parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()); } else {
parameters.setOurOneTimePreKey(Optional.<ECKeyPair>absent());
if (message.getPreKeyId() >= 0) parameters.setOurPreKey(Optional.of(preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair())); }
else parameters.setOurPreKey(Optional.<ECKeyPair>absent());
if (!simultaneousInitiate) sessionRecord.reset(); if (!simultaneousInitiate) sessionRecord.reset();
else sessionRecord.archiveCurrentState(); else sessionRecord.archiveCurrentState();
@ -171,19 +173,18 @@ public class SessionBuilder {
return false; return false;
} }
SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage(); ECKeyPair ourPreKey = preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair();
AxolotlParameters.Builder parameters = RatchetingSession.AxolotlParameters.newBuilder(); boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage();
parameters.setTheirBaseKey(message.getBaseKey()); BobAxolotlParameters.Builder parameters = BobAxolotlParameters.newBuilder();
parameters.setTheirEphemeralKey(message.getWhisperMessage().getSenderEphemeral());
parameters.setTheirPreKey(Optional.<ECPublicKey>absent());
parameters.setTheirIdentityKey(message.getIdentityKey());
parameters.setOurBaseKey(preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair()); parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
parameters.setOurEphemeralKey(parameters.getOurBaseKey()); .setOurSignedPreKey(ourPreKey)
parameters.setOurPreKey(Optional.<ECKeyPair>absent()); .setOurRatchetKey(ourPreKey)
parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()); .setOurOneTimePreKey(Optional.<ECKeyPair>absent())
.setTheirIdentityKey(message.getIdentityKey())
.setTheirBaseKey(message.getBaseKey());
if (!simultaneousInitiate) sessionRecord.reset(); if (!simultaneousInitiate) sessionRecord.reset();
else sessionRecord.archiveCurrentState(); else sessionRecord.archiveCurrentState();
@ -195,12 +196,12 @@ public class SessionBuilder {
if (simultaneousInitiate) sessionRecord.getSessionState().setNeedsRefresh(true); if (simultaneousInitiate) sessionRecord.getSessionState().setNeedsRefresh(true);
sessionStore.storeSession(recipientId, deviceId, sessionRecord);
if (message.getPreKeyId() != Medium.MAX_VALUE) { if (message.getPreKeyId() != Medium.MAX_VALUE) {
preKeyStore.removePreKey(message.getPreKeyId()); preKeyStore.removePreKey(message.getPreKeyId());
} }
sessionStore.storeSession(recipientId, deviceId, sessionRecord);
return true; return true;
} }
@ -233,20 +234,21 @@ public class SessionBuilder {
throw new InvalidKeyException("Both signed and unsigned prekeys are absent!"); throw new InvalidKeyException("Both signed and unsigned prekeys are absent!");
} }
SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
AxolotlParameters.Builder parameters = AxolotlParameters.newBuilder(); ECKeyPair ourBaseKey = Curve.generateKeyPair(true);
ECKeyPair ourBaseKey = Curve.generateKeyPair(true); ECPublicKey theirSignedPreKey = preKey.getSignedPreKey() != null ? preKey.getSignedPreKey() :
preKey.getPreKey();
parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair()); AliceAxolotlParameters.Builder parameters = AliceAxolotlParameters.newBuilder();
parameters.setOurBaseKey(ourBaseKey);
parameters.setOurEphemeralKey(Curve.generateKeyPair(true));
parameters.setOurPreKey(Optional.of(parameters.getOurBaseKey()));
parameters.setTheirIdentityKey(preKey.getIdentityKey()); parameters.setOurBaseKey(ourBaseKey)
if (preKey.getSignedPreKey() == null) parameters.setTheirBaseKey(preKey.getPreKey()); .setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
else parameters.setTheirBaseKey(preKey.getSignedPreKey()); .setTheirIdentityKey(preKey.getIdentityKey())
parameters.setTheirEphemeralKey(parameters.getTheirBaseKey()); .setTheirSignedPreKey(theirSignedPreKey)
parameters.setTheirPreKey(Optional.fromNullable(preKey.getPreKey())); .setTheirRatchetKey(theirSignedPreKey)
.setTheirOneTimePreKey(preKey.getSignedPreKey() != null ?
Optional.fromNullable(preKey.getPreKey()) :
Optional.<ECPublicKey>absent());
if (sessionRecord.getSessionState().getNeedsRefresh()) sessionRecord.archiveCurrentState(); if (sessionRecord.getSessionState().getNeedsRefresh()) sessionRecord.archiveCurrentState();
else sessionRecord.reset(); else sessionRecord.reset();
@ -288,9 +290,8 @@ public class SessionBuilder {
} }
private KeyExchangeMessage processInitiate(KeyExchangeMessage message) throws InvalidKeyException { private KeyExchangeMessage processInitiate(KeyExchangeMessage message) throws InvalidKeyException {
AxolotlParameters.Builder parameters = AxolotlParameters.newBuilder(); int flags = KeyExchangeMessage.RESPONSE_FLAG;
int flags = KeyExchangeMessage.RESPONSE_FLAG; SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
if (message.getVersion() >= 3 && if (message.getVersion() >= 3 &&
!Curve.verifySignature(message.getIdentityKey().getPublicKey(), !Curve.verifySignature(message.getIdentityKey().getPublicKey(),
@ -300,41 +301,42 @@ public class SessionBuilder {
throw new InvalidKeyException("Bad signature!"); throw new InvalidKeyException("Bad signature!");
} }
SymmetricAxolotlParameters.Builder builder = SymmetricAxolotlParameters.newBuilder();
if (!sessionRecord.getSessionState().hasPendingKeyExchange()) { if (!sessionRecord.getSessionState().hasPendingKeyExchange()) {
Log.w(TAG, "We don't have a pending initiate..."); builder.setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
parameters.setOurBaseKey(Curve.generateKeyPair(true)); .setOurBaseKey(Curve.generateKeyPair(true))
parameters.setOurEphemeralKey(Curve.generateKeyPair(true)); .setOurRatchetKey(Curve.generateKeyPair(true));
parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair());
parameters.setOurPreKey(Optional.<ECKeyPair>absent());
} else { } else {
Log.w(TAG, "We already have a pending initiate, responding as simultaneous initiate..."); builder.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())
parameters.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey()); .setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())
parameters.setOurEphemeralKey(sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey()); .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey());
parameters.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey());
parameters.setOurPreKey(Optional.<ECKeyPair>absent());
flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG; flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG;
} }
parameters.setTheirBaseKey(message.getBaseKey()); builder.setTheirBaseKey(message.getBaseKey())
parameters.setTheirEphemeralKey(message.getEphemeralKey()); .setTheirRatchetKey(message.getRatchetKey())
parameters.setTheirPreKey(Optional.<ECPublicKey>absent()); .setTheirIdentityKey(message.getIdentityKey());
parameters.setTheirIdentityKey(message.getIdentityKey());
SymmetricAxolotlParameters parameters = builder.create();
sessionRecord.reset(); sessionRecord.reset();
RatchetingSession.initializeSession(sessionRecord.getSessionState(), RatchetingSession.initializeSession(sessionRecord.getSessionState(),
Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION), Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION),
parameters.create()); parameters);
sessionStore.storeSession(recipientId, deviceId, sessionRecord); sessionStore.storeSession(recipientId, deviceId, sessionRecord);
identityKeyStore.saveIdentity(recipientId, message.getIdentityKey()); identityKeyStore.saveIdentity(recipientId, message.getIdentityKey());
byte[] baseKeySignature = Curve.calculateSignature(parameters.getOurIdentityKey().getPrivateKey(),
parameters.getOurBaseKey().getPublicKey().serialize());
return new KeyExchangeMessage(sessionRecord.getSessionState().getSessionVersion(), return new KeyExchangeMessage(sessionRecord.getSessionState().getSessionVersion(),
message.getSequence(), flags, message.getSequence(), flags,
parameters.getOurBaseKey().getPublicKey(), null, parameters.getOurBaseKey().getPublicKey(),
parameters.getOurEphemeralKey().getPublicKey(), baseKeySignature, parameters.getOurRatchetKey().getPublicKey(),
parameters.getOurIdentityKey().getPublicKey(), parameters.getOurIdentityKey().getPublicKey());
sessionRecord.getSessionState().getVerification());
} }
private void processResponse(KeyExchangeMessage message) private void processResponse(KeyExchangeMessage message)
@ -351,29 +353,27 @@ public class SessionBuilder {
else return; else return;
} }
AxolotlParameters parameters = SymmetricAxolotlParameters.Builder parameters = SymmetricAxolotlParameters.newBuilder();
AxolotlParameters.newBuilder()
.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey()) parameters.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())
.setOurEphemeralKey(sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey()) .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey())
.setOurPreKey(Optional.<ECKeyPair>absent()) .setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())
.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey()) .setTheirBaseKey(message.getBaseKey())
.setTheirBaseKey(message.getBaseKey()) .setTheirRatchetKey(message.getRatchetKey())
.setTheirEphemeralKey(message.getEphemeralKey()) .setTheirIdentityKey(message.getIdentityKey());
.setTheirPreKey(Optional.<ECPublicKey>absent())
.setTheirIdentityKey(message.getIdentityKey())
.create();
sessionRecord.reset(); sessionRecord.reset();
RatchetingSession.initializeSession(sessionRecord.getSessionState(), RatchetingSession.initializeSession(sessionRecord.getSessionState(),
Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION), Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION),
parameters); parameters.create());
if (sessionRecord.getSessionState().getSessionVersion() >= 3 && if (sessionRecord.getSessionState().getSessionVersion() >= 3 &&
!MessageDigest.isEqual(message.getVerificationTag(), !Curve.verifySignature(message.getIdentityKey().getPublicKey(),
sessionRecord.getSessionState().getVerification())) 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); sessionStore.storeSession(recipientId, deviceId, sessionRecord);
@ -387,18 +387,23 @@ public class SessionBuilder {
* @return the KeyExchangeMessage to deliver. * @return the KeyExchangeMessage to deliver.
*/ */
public KeyExchangeMessage process() { public KeyExchangeMessage process() {
int sequence = KeyHelper.getRandomSequence(65534) + 1; try {
int flags = KeyExchangeMessage.INITIATE_FLAG; int sequence = KeyHelper.getRandomSequence(65534) + 1;
ECKeyPair baseKey = Curve.generateKeyPair(true); int flags = KeyExchangeMessage.INITIATE_FLAG;
ECKeyPair ephemeralKey = Curve.generateKeyPair(true); ECKeyPair baseKey = Curve.generateKeyPair(true);
IdentityKeyPair identityKey = identityKeyStore.getIdentityKeyPair(); ECKeyPair ratchetKey = Curve.generateKeyPair(true);
SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); 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); sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ratchetKey, identityKey);
sessionStore.storeSession(recipientId, deviceId, sessionRecord); sessionStore.storeSession(recipientId, deviceId, sessionRecord);
return new KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), null, return new KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), baseKeySignature,
ephemeralKey.getPublicKey(), identityKey.getPublicKey(), null); ratchetKey.getPublicKey(), identityKey.getPublicKey());
} catch (InvalidKeyException e) {
throw new AssertionError(e);
}
} }

View File

@ -98,7 +98,7 @@ public class SessionCipher {
SessionState sessionState = sessionRecord.getSessionState(); SessionState sessionState = sessionRecord.getSessionState();
ChainKey chainKey = sessionState.getSenderChainKey(); ChainKey chainKey = sessionState.getSenderChainKey();
MessageKeys messageKeys = chainKey.getMessageKeys(); MessageKeys messageKeys = chainKey.getMessageKeys();
ECPublicKey senderEphemeral = sessionState.getSenderEphemeral(); ECPublicKey senderEphemeral = sessionState.getSenderRatchetKey();
int previousCounter = sessionState.getPreviousCounter(); int previousCounter = sessionState.getPreviousCounter();
int sessionVersion = sessionState.getSessionVersion(); int sessionVersion = sessionState.getSessionVersion();
@ -223,7 +223,7 @@ public class SessionCipher {
sessionState.getSessionVersion())); sessionState.getSessionVersion()));
} }
ECPublicKey theirEphemeral = ciphertextMessage.getSenderEphemeral(); ECPublicKey theirEphemeral = ciphertextMessage.getSenderRatchetKey();
int counter = ciphertextMessage.getCounter(); int counter = ciphertextMessage.getCounter();
ChainKey chainKey = getOrCreateChainKey(sessionState, theirEphemeral); ChainKey chainKey = getOrCreateChainKey(sessionState, theirEphemeral);
MessageKeys messageKeys = getOrCreateMessageKeys(sessionState, theirEphemeral, MessageKeys messageKeys = getOrCreateMessageKeys(sessionState, theirEphemeral,
@ -254,7 +254,7 @@ public class SessionCipher {
return sessionState.getReceiverChainKey(theirEphemeral); return sessionState.getReceiverChainKey(theirEphemeral);
} else { } else {
RootKey rootKey = sessionState.getRootKey(); RootKey rootKey = sessionState.getRootKey();
ECKeyPair ourEphemeral = sessionState.getSenderEphemeralPair(); ECKeyPair ourEphemeral = sessionState.getSenderRatchetKeyPair();
Pair<RootKey, ChainKey> receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral); Pair<RootKey, ChainKey> receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral);
ECKeyPair ourNewEphemeral = Curve.generateKeyPair(true); ECKeyPair ourNewEphemeral = Curve.generateKeyPair(true);
Pair<RootKey, ChainKey> senderChain = receiverChain.first().createChain(theirEphemeral, ourNewEphemeral); Pair<RootKey, ChainKey> senderChain = receiverChain.first().createChain(theirEphemeral, ourNewEphemeral);

View File

@ -29,15 +29,14 @@ public class KeyExchangeMessage {
private final ECPublicKey baseKey; private final ECPublicKey baseKey;
private final byte[] baseKeySignature; private final byte[] baseKeySignature;
private final ECPublicKey ephemeralKey; private final ECPublicKey ratchetKey;
private final IdentityKey identityKey; private final IdentityKey identityKey;
private final byte[] verificationTag;
private final byte[] serialized; private final byte[] serialized;
public KeyExchangeMessage(int messageVersion, int sequence, int flags, public KeyExchangeMessage(int messageVersion, int sequence, int flags,
ECPublicKey baseKey, byte[] baseKeySignature, ECPublicKey baseKey, byte[] baseKeySignature,
ECPublicKey ephemeralKey, ECPublicKey ratchetKey,
IdentityKey identityKey, byte[] verificationTag) IdentityKey identityKey)
{ {
this.supportedVersion = CiphertextMessage.CURRENT_VERSION; this.supportedVersion = CiphertextMessage.CURRENT_VERSION;
this.version = messageVersion; this.version = messageVersion;
@ -45,25 +44,21 @@ public class KeyExchangeMessage {
this.flags = flags; this.flags = flags;
this.baseKey = baseKey; this.baseKey = baseKey;
this.baseKeySignature = baseKeySignature; this.baseKeySignature = baseKeySignature;
this.ephemeralKey = ephemeralKey; this.ratchetKey = ratchetKey;
this.identityKey = identityKey; this.identityKey = identityKey;
this.verificationTag = verificationTag;
byte[] version = {ByteUtil.intsToByteHighAndLow(this.version, this.supportedVersion)}; byte[] version = {ByteUtil.intsToByteHighAndLow(this.version, this.supportedVersion)};
Builder builder = WhisperProtos.KeyExchangeMessage.newBuilder() Builder builder = WhisperProtos.KeyExchangeMessage
.setId((sequence << 5) | flags) .newBuilder()
.setBaseKey(ByteString.copyFrom(baseKey.serialize())) .setId((sequence << 5) | flags)
.setEphemeralKey(ByteString.copyFrom(ephemeralKey.serialize())) .setBaseKey(ByteString.copyFrom(baseKey.serialize()))
.setIdentityKey(ByteString.copyFrom(identityKey.serialize())); .setRatchetKey(ByteString.copyFrom(ratchetKey.serialize()))
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()));
if (messageVersion >= 3 && baseKeySignature != null) { if (messageVersion >= 3) {
builder.setBaseKeySignature(ByteString.copyFrom(baseKeySignature)); builder.setBaseKeySignature(ByteString.copyFrom(baseKeySignature));
} }
if (messageVersion >=3 && verificationTag != null) {
builder.setVerification(ByteString.copyFrom(verificationTag));
}
this.serialized = ByteUtil.combine(version, builder.build().toByteArray()); this.serialized = ByteUtil.combine(version, builder.build().toByteArray());
} }
@ -86,9 +81,8 @@ public class KeyExchangeMessage {
WhisperProtos.KeyExchangeMessage message = WhisperProtos.KeyExchangeMessage.parseFrom(parts[1]); WhisperProtos.KeyExchangeMessage message = WhisperProtos.KeyExchangeMessage.parseFrom(parts[1]);
if (!message.hasId() || !message.hasBaseKey() || if (!message.hasId() || !message.hasBaseKey() ||
!message.hasEphemeralKey() || !message.hasIdentityKey() || !message.hasRatchetKey() || !message.hasIdentityKey() ||
(this.version >=3 && (((message.getId() & 0x1f) & INITIATE_FLAG) != 0) && !message.hasBaseKeySignature()) || (this.version >=3 && !message.hasBaseKeySignature()))
(this.version >=3 && (((message.getId() & 0x1f) & RESPONSE_FLAG) != 0) && !message.hasVerification()))
{ {
throw new InvalidMessageException("Some required fields missing!"); throw new InvalidMessageException("Some required fields missing!");
} }
@ -98,8 +92,7 @@ public class KeyExchangeMessage {
this.serialized = serialized; this.serialized = serialized;
this.baseKey = Curve.decodePoint(message.getBaseKey().toByteArray(), 0); this.baseKey = Curve.decodePoint(message.getBaseKey().toByteArray(), 0);
this.baseKeySignature = message.getBaseKeySignature().toByteArray(); this.baseKeySignature = message.getBaseKeySignature().toByteArray();
this.verificationTag = message.getVerification().toByteArray(); this.ratchetKey = Curve.decodePoint(message.getRatchetKey().toByteArray(), 0);
this.ephemeralKey = Curve.decodePoint(message.getEphemeralKey().toByteArray(), 0);
this.identityKey = new IdentityKey(message.getIdentityKey().toByteArray(), 0); this.identityKey = new IdentityKey(message.getIdentityKey().toByteArray(), 0);
} catch (InvalidKeyException | IOException e) { } catch (InvalidKeyException | IOException e) {
throw new InvalidMessageException(e); throw new InvalidMessageException(e);
@ -118,12 +111,8 @@ public class KeyExchangeMessage {
return baseKeySignature; return baseKeySignature;
} }
public byte[] getVerificationTag() { public ECPublicKey getRatchetKey() {
return verificationTag; return ratchetKey;
}
public ECPublicKey getEphemeralKey() {
return ephemeralKey;
} }
public IdentityKey getIdentityKey() { public IdentityKey getIdentityKey() {

View File

@ -38,7 +38,7 @@ public class WhisperMessage implements CiphertextMessage {
private static final int MAC_LENGTH = 8; private static final int MAC_LENGTH = 8;
private final int messageVersion; private final int messageVersion;
private final ECPublicKey senderEphemeral; private final ECPublicKey senderRatchetKey;
private final int counter; private final int counter;
private final int previousCounter; private final int previousCounter;
private final byte[] ciphertext; private final byte[] ciphertext;
@ -63,44 +63,44 @@ public class WhisperMessage implements CiphertextMessage {
if (!whisperMessage.hasCiphertext() || if (!whisperMessage.hasCiphertext() ||
!whisperMessage.hasCounter() || !whisperMessage.hasCounter() ||
!whisperMessage.hasEphemeralKey()) !whisperMessage.hasRatchetKey())
{ {
throw new InvalidMessageException("Incomplete message."); throw new InvalidMessageException("Incomplete message.");
} }
this.serialized = serialized; this.serialized = serialized;
this.senderEphemeral = Curve.decodePoint(whisperMessage.getEphemeralKey().toByteArray(), 0); this.senderRatchetKey = Curve.decodePoint(whisperMessage.getRatchetKey().toByteArray(), 0);
this.messageVersion = ByteUtil.highBitsToInt(version); this.messageVersion = ByteUtil.highBitsToInt(version);
this.counter = whisperMessage.getCounter(); this.counter = whisperMessage.getCounter();
this.previousCounter = whisperMessage.getPreviousCounter(); this.previousCounter = whisperMessage.getPreviousCounter();
this.ciphertext = whisperMessage.getCiphertext().toByteArray(); this.ciphertext = whisperMessage.getCiphertext().toByteArray();
} catch (InvalidProtocolBufferException | InvalidKeyException | ParseException e) { } catch (InvalidProtocolBufferException | InvalidKeyException | ParseException e) {
throw new InvalidMessageException(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) int counter, int previousCounter, byte[] ciphertext)
{ {
byte[] version = {ByteUtil.intsToByteHighAndLow(messageVersion, CURRENT_VERSION)}; byte[] version = {ByteUtil.intsToByteHighAndLow(messageVersion, CURRENT_VERSION)};
byte[] message = WhisperProtos.WhisperMessage.newBuilder() byte[] message = WhisperProtos.WhisperMessage.newBuilder()
.setEphemeralKey(ByteString.copyFrom(senderEphemeral.serialize())) .setRatchetKey(ByteString.copyFrom(senderRatchetKey.serialize()))
.setCounter(counter) .setCounter(counter)
.setPreviousCounter(previousCounter) .setPreviousCounter(previousCounter)
.setCiphertext(ByteString.copyFrom(ciphertext)) .setCiphertext(ByteString.copyFrom(ciphertext))
.build().toByteArray(); .build().toByteArray();
byte[] mac = getMac(macKey, ByteUtil.combine(version, message)); byte[] mac = getMac(macKey, ByteUtil.combine(version, message));
this.serialized = ByteUtil.combine(version, message, mac); this.serialized = ByteUtil.combine(version, message, mac);
this.senderEphemeral = senderEphemeral; this.senderRatchetKey = senderRatchetKey;
this.counter = counter; this.counter = counter;
this.previousCounter = previousCounter; this.previousCounter = previousCounter;
this.ciphertext = ciphertext; this.ciphertext = ciphertext;
this.messageVersion = messageVersion; this.messageVersion = messageVersion;
} }
public ECPublicKey getSenderEphemeral() { public ECPublicKey getSenderRatchetKey() {
return senderEphemeral; return senderRatchetKey;
} }
public int getMessageVersion() { public int getMessageVersion() {

View File

@ -11,15 +11,15 @@ public final class WhisperProtos {
public interface WhisperMessageOrBuilder public interface WhisperMessageOrBuilder
extends com.google.protobuf.MessageOrBuilder { extends com.google.protobuf.MessageOrBuilder {
// optional bytes ephemeralKey = 1; // optional bytes ratchetKey = 1;
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
boolean hasEphemeralKey(); boolean hasRatchetKey();
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
com.google.protobuf.ByteString getEphemeralKey(); com.google.protobuf.ByteString getRatchetKey();
// optional uint32 counter = 2; // optional uint32 counter = 2;
/** /**
@ -104,7 +104,7 @@ public final class WhisperProtos {
} }
case 10: { case 10: {
bitField0_ |= 0x00000001; bitField0_ |= 0x00000001;
ephemeralKey_ = input.readBytes(); ratchetKey_ = input.readBytes();
break; break;
} }
case 16: { case 16: {
@ -162,20 +162,20 @@ public final class WhisperProtos {
} }
private int bitField0_; private int bitField0_;
// optional bytes ephemeralKey = 1; // optional bytes ratchetKey = 1;
public static final int EPHEMERALKEY_FIELD_NUMBER = 1; public static final int RATCHETKEY_FIELD_NUMBER = 1;
private com.google.protobuf.ByteString ephemeralKey_; private com.google.protobuf.ByteString ratchetKey_;
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
public boolean hasEphemeralKey() { public boolean hasRatchetKey() {
return ((bitField0_ & 0x00000001) == 0x00000001); return ((bitField0_ & 0x00000001) == 0x00000001);
} }
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
public com.google.protobuf.ByteString getEphemeralKey() { public com.google.protobuf.ByteString getRatchetKey() {
return ephemeralKey_; return ratchetKey_;
} }
// optional uint32 counter = 2; // optional uint32 counter = 2;
@ -227,7 +227,7 @@ public final class WhisperProtos {
} }
private void initFields() { private void initFields() {
ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
counter_ = 0; counter_ = 0;
previousCounter_ = 0; previousCounter_ = 0;
ciphertext_ = com.google.protobuf.ByteString.EMPTY; ciphertext_ = com.google.protobuf.ByteString.EMPTY;
@ -245,7 +245,7 @@ public final class WhisperProtos {
throws java.io.IOException { throws java.io.IOException {
getSerializedSize(); getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) { if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBytes(1, ephemeralKey_); output.writeBytes(1, ratchetKey_);
} }
if (((bitField0_ & 0x00000002) == 0x00000002)) { if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeUInt32(2, counter_); output.writeUInt32(2, counter_);
@ -267,7 +267,7 @@ public final class WhisperProtos {
size = 0; size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) { if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, ephemeralKey_); .computeBytesSize(1, ratchetKey_);
} }
if (((bitField0_ & 0x00000002) == 0x00000002)) { if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
@ -397,7 +397,7 @@ public final class WhisperProtos {
public Builder clear() { public Builder clear() {
super.clear(); super.clear();
ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000001);
counter_ = 0; counter_ = 0;
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
@ -436,7 +436,7 @@ public final class WhisperProtos {
if (((from_bitField0_ & 0x00000001) == 0x00000001)) { if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001; to_bitField0_ |= 0x00000001;
} }
result.ephemeralKey_ = ephemeralKey_; result.ratchetKey_ = ratchetKey_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) { if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002; to_bitField0_ |= 0x00000002;
} }
@ -465,8 +465,8 @@ public final class WhisperProtos {
public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage other) { public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage other) {
if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.getDefaultInstance()) return this; if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.getDefaultInstance()) return this;
if (other.hasEphemeralKey()) { if (other.hasRatchetKey()) {
setEphemeralKey(other.getEphemeralKey()); setRatchetKey(other.getRatchetKey());
} }
if (other.hasCounter()) { if (other.hasCounter()) {
setCounter(other.getCounter()); setCounter(other.getCounter());
@ -504,38 +504,38 @@ public final class WhisperProtos {
} }
private int bitField0_; private int bitField0_;
// optional bytes ephemeralKey = 1; // optional bytes ratchetKey = 1;
private com.google.protobuf.ByteString ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
public boolean hasEphemeralKey() { public boolean hasRatchetKey() {
return ((bitField0_ & 0x00000001) == 0x00000001); return ((bitField0_ & 0x00000001) == 0x00000001);
} }
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
public com.google.protobuf.ByteString getEphemeralKey() { public com.google.protobuf.ByteString getRatchetKey() {
return ephemeralKey_; return ratchetKey_;
} }
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
public Builder setEphemeralKey(com.google.protobuf.ByteString value) { public Builder setRatchetKey(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
bitField0_ |= 0x00000001; bitField0_ |= 0x00000001;
ephemeralKey_ = value; ratchetKey_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>optional bytes ephemeralKey = 1;</code> * <code>optional bytes ratchetKey = 1;</code>
*/ */
public Builder clearEphemeralKey() { public Builder clearRatchetKey() {
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000001);
ephemeralKey_ = getDefaultInstance().getEphemeralKey(); ratchetKey_ = getDefaultInstance().getRatchetKey();
onChanged(); onChanged();
return this; return this;
} }
@ -1602,15 +1602,15 @@ public final class WhisperProtos {
*/ */
com.google.protobuf.ByteString getBaseKey(); com.google.protobuf.ByteString getBaseKey();
// optional bytes ephemeralKey = 3; // optional bytes ratchetKey = 3;
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
boolean hasEphemeralKey(); boolean hasRatchetKey();
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
com.google.protobuf.ByteString getEphemeralKey(); com.google.protobuf.ByteString getRatchetKey();
// optional bytes identityKey = 4; // optional bytes identityKey = 4;
/** /**
@ -1625,22 +1625,20 @@ public final class WhisperProtos {
// optional bytes baseKeySignature = 5; // optional bytes baseKeySignature = 5;
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
boolean hasBaseKeySignature(); boolean hasBaseKeySignature();
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
com.google.protobuf.ByteString getBaseKeySignature(); com.google.protobuf.ByteString getBaseKeySignature();
// optional bytes verification = 6;
/**
* <code>optional bytes verification = 6;</code>
*/
boolean hasVerification();
/**
* <code>optional bytes verification = 6;</code>
*/
com.google.protobuf.ByteString getVerification();
} }
/** /**
* Protobuf type {@code textsecure.KeyExchangeMessage} * Protobuf type {@code textsecure.KeyExchangeMessage}
@ -1705,7 +1703,7 @@ public final class WhisperProtos {
} }
case 26: { case 26: {
bitField0_ |= 0x00000004; bitField0_ |= 0x00000004;
ephemeralKey_ = input.readBytes(); ratchetKey_ = input.readBytes();
break; break;
} }
case 34: { case 34: {
@ -1718,11 +1716,6 @@ public final class WhisperProtos {
baseKeySignature_ = input.readBytes(); baseKeySignature_ = input.readBytes();
break; break;
} }
case 50: {
bitField0_ |= 0x00000020;
verification_ = input.readBytes();
break;
}
} }
} }
} catch (com.google.protobuf.InvalidProtocolBufferException e) { } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@ -1795,20 +1788,20 @@ public final class WhisperProtos {
return baseKey_; return baseKey_;
} }
// optional bytes ephemeralKey = 3; // optional bytes ratchetKey = 3;
public static final int EPHEMERALKEY_FIELD_NUMBER = 3; public static final int RATCHETKEY_FIELD_NUMBER = 3;
private com.google.protobuf.ByteString ephemeralKey_; private com.google.protobuf.ByteString ratchetKey_;
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
public boolean hasEphemeralKey() { public boolean hasRatchetKey() {
return ((bitField0_ & 0x00000004) == 0x00000004); return ((bitField0_ & 0x00000004) == 0x00000004);
} }
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
public com.google.protobuf.ByteString getEphemeralKey() { public com.google.protobuf.ByteString getRatchetKey() {
return ephemeralKey_; return ratchetKey_;
} }
// optional bytes identityKey = 4; // optional bytes identityKey = 4;
@ -1832,40 +1825,31 @@ public final class WhisperProtos {
private com.google.protobuf.ByteString baseKeySignature_; private com.google.protobuf.ByteString baseKeySignature_;
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
public boolean hasBaseKeySignature() { public boolean hasBaseKeySignature() {
return ((bitField0_ & 0x00000010) == 0x00000010); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
public com.google.protobuf.ByteString getBaseKeySignature() { public com.google.protobuf.ByteString getBaseKeySignature() {
return baseKeySignature_; return baseKeySignature_;
} }
// optional bytes verification = 6;
public static final int VERIFICATION_FIELD_NUMBER = 6;
private com.google.protobuf.ByteString verification_;
/**
* <code>optional bytes verification = 6;</code>
*/
public boolean hasVerification() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
/**
* <code>optional bytes verification = 6;</code>
*/
public com.google.protobuf.ByteString getVerification() {
return verification_;
}
private void initFields() { private void initFields() {
id_ = 0; id_ = 0;
baseKey_ = com.google.protobuf.ByteString.EMPTY; baseKey_ = com.google.protobuf.ByteString.EMPTY;
ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
identityKey_ = com.google.protobuf.ByteString.EMPTY; identityKey_ = com.google.protobuf.ByteString.EMPTY;
baseKeySignature_ = com.google.protobuf.ByteString.EMPTY; baseKeySignature_ = com.google.protobuf.ByteString.EMPTY;
verification_ = com.google.protobuf.ByteString.EMPTY;
} }
private byte memoizedIsInitialized = -1; private byte memoizedIsInitialized = -1;
public final boolean isInitialized() { public final boolean isInitialized() {
@ -1886,7 +1870,7 @@ public final class WhisperProtos {
output.writeBytes(2, baseKey_); output.writeBytes(2, baseKey_);
} }
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeBytes(3, ephemeralKey_); output.writeBytes(3, ratchetKey_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeBytes(4, identityKey_); output.writeBytes(4, identityKey_);
@ -1894,9 +1878,6 @@ public final class WhisperProtos {
if (((bitField0_ & 0x00000010) == 0x00000010)) { if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeBytes(5, baseKeySignature_); output.writeBytes(5, baseKeySignature_);
} }
if (((bitField0_ & 0x00000020) == 0x00000020)) {
output.writeBytes(6, verification_);
}
getUnknownFields().writeTo(output); getUnknownFields().writeTo(output);
} }
@ -1916,7 +1897,7 @@ public final class WhisperProtos {
} }
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(3, ephemeralKey_); .computeBytesSize(3, ratchetKey_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
@ -1926,10 +1907,6 @@ public final class WhisperProtos {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(5, baseKeySignature_); .computeBytesSize(5, baseKeySignature_);
} }
if (((bitField0_ & 0x00000020) == 0x00000020)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(6, verification_);
}
size += getUnknownFields().getSerializedSize(); size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size; memoizedSerializedSize = size;
return size; return size;
@ -2050,14 +2027,12 @@ public final class WhisperProtos {
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000001);
baseKey_ = com.google.protobuf.ByteString.EMPTY; baseKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000004);
identityKey_ = com.google.protobuf.ByteString.EMPTY; identityKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000008); bitField0_ = (bitField0_ & ~0x00000008);
baseKeySignature_ = com.google.protobuf.ByteString.EMPTY; baseKeySignature_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000010); bitField0_ = (bitField0_ & ~0x00000010);
verification_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000020);
return this; return this;
} }
@ -2097,7 +2072,7 @@ public final class WhisperProtos {
if (((from_bitField0_ & 0x00000004) == 0x00000004)) { if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004; to_bitField0_ |= 0x00000004;
} }
result.ephemeralKey_ = ephemeralKey_; result.ratchetKey_ = ratchetKey_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) { if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008; to_bitField0_ |= 0x00000008;
} }
@ -2106,10 +2081,6 @@ public final class WhisperProtos {
to_bitField0_ |= 0x00000010; to_bitField0_ |= 0x00000010;
} }
result.baseKeySignature_ = baseKeySignature_; result.baseKeySignature_ = baseKeySignature_;
if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
to_bitField0_ |= 0x00000020;
}
result.verification_ = verification_;
result.bitField0_ = to_bitField0_; result.bitField0_ = to_bitField0_;
onBuilt(); onBuilt();
return result; return result;
@ -2132,8 +2103,8 @@ public final class WhisperProtos {
if (other.hasBaseKey()) { if (other.hasBaseKey()) {
setBaseKey(other.getBaseKey()); setBaseKey(other.getBaseKey());
} }
if (other.hasEphemeralKey()) { if (other.hasRatchetKey()) {
setEphemeralKey(other.getEphemeralKey()); setRatchetKey(other.getRatchetKey());
} }
if (other.hasIdentityKey()) { if (other.hasIdentityKey()) {
setIdentityKey(other.getIdentityKey()); setIdentityKey(other.getIdentityKey());
@ -2141,9 +2112,6 @@ public final class WhisperProtos {
if (other.hasBaseKeySignature()) { if (other.hasBaseKeySignature()) {
setBaseKeySignature(other.getBaseKeySignature()); setBaseKeySignature(other.getBaseKeySignature());
} }
if (other.hasVerification()) {
setVerification(other.getVerification());
}
this.mergeUnknownFields(other.getUnknownFields()); this.mergeUnknownFields(other.getUnknownFields());
return this; return this;
} }
@ -2240,38 +2208,38 @@ public final class WhisperProtos {
return this; return this;
} }
// optional bytes ephemeralKey = 3; // optional bytes ratchetKey = 3;
private com.google.protobuf.ByteString ephemeralKey_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
public boolean hasEphemeralKey() { public boolean hasRatchetKey() {
return ((bitField0_ & 0x00000004) == 0x00000004); return ((bitField0_ & 0x00000004) == 0x00000004);
} }
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
public com.google.protobuf.ByteString getEphemeralKey() { public com.google.protobuf.ByteString getRatchetKey() {
return ephemeralKey_; return ratchetKey_;
} }
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
public Builder setEphemeralKey(com.google.protobuf.ByteString value) { public Builder setRatchetKey(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
bitField0_ |= 0x00000004; bitField0_ |= 0x00000004;
ephemeralKey_ = value; ratchetKey_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>optional bytes ephemeralKey = 3;</code> * <code>optional bytes ratchetKey = 3;</code>
*/ */
public Builder clearEphemeralKey() { public Builder clearRatchetKey() {
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000004);
ephemeralKey_ = getDefaultInstance().getEphemeralKey(); ratchetKey_ = getDefaultInstance().getRatchetKey();
onChanged(); onChanged();
return this; return this;
} }
@ -2316,18 +2284,30 @@ public final class WhisperProtos {
private com.google.protobuf.ByteString baseKeySignature_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString baseKeySignature_ = com.google.protobuf.ByteString.EMPTY;
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
public boolean hasBaseKeySignature() { public boolean hasBaseKeySignature() {
return ((bitField0_ & 0x00000010) == 0x00000010); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
public com.google.protobuf.ByteString getBaseKeySignature() { public com.google.protobuf.ByteString getBaseKeySignature() {
return baseKeySignature_; return baseKeySignature_;
} }
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
public Builder setBaseKeySignature(com.google.protobuf.ByteString value) { public Builder setBaseKeySignature(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
@ -2340,6 +2320,10 @@ public final class WhisperProtos {
} }
/** /**
* <code>optional bytes baseKeySignature = 5;</code> * <code>optional bytes baseKeySignature = 5;</code>
*
* <pre>
* optional bytes verification = 6;
* </pre>
*/ */
public Builder clearBaseKeySignature() { public Builder clearBaseKeySignature() {
bitField0_ = (bitField0_ & ~0x00000010); bitField0_ = (bitField0_ & ~0x00000010);
@ -2348,42 +2332,6 @@ public final class WhisperProtos {
return this; return this;
} }
// optional bytes verification = 6;
private com.google.protobuf.ByteString verification_ = com.google.protobuf.ByteString.EMPTY;
/**
* <code>optional bytes verification = 6;</code>
*/
public boolean hasVerification() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
/**
* <code>optional bytes verification = 6;</code>
*/
public com.google.protobuf.ByteString getVerification() {
return verification_;
}
/**
* <code>optional bytes verification = 6;</code>
*/
public Builder setVerification(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000020;
verification_ = value;
onChanged();
return this;
}
/**
* <code>optional bytes verification = 6;</code>
*/
public Builder clearVerification() {
bitField0_ = (bitField0_ & ~0x00000020);
verification_ = getDefaultInstance().getVerification();
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:textsecure.KeyExchangeMessage) // @@protoc_insertion_point(builder_scope:textsecure.KeyExchangeMessage)
} }
@ -2420,18 +2368,18 @@ public final class WhisperProtos {
static { static {
java.lang.String[] descriptorData = { java.lang.String[] descriptorData = {
"\n\031WhisperTextProtocol.proto\022\ntextsecure\"" + "\n\031WhisperTextProtocol.proto\022\ntextsecure\"" +
"d\n\016WhisperMessage\022\024\n\014ephemeralKey\030\001 \001(\014\022" + "b\n\016WhisperMessage\022\022\n\nratchetKey\030\001 \001(\014\022\017\n" +
"\017\n\007counter\030\002 \001(\r\022\027\n\017previousCounter\030\003 \001(" + "\007counter\030\002 \001(\r\022\027\n\017previousCounter\030\003 \001(\r\022" +
"\r\022\022\n\nciphertext\030\004 \001(\014\"\245\001\n\024PreKeyWhisperM" + "\022\n\nciphertext\030\004 \001(\014\"\245\001\n\024PreKeyWhisperMes" +
"essage\022\026\n\016registrationId\030\005 \001(\r\022\020\n\010preKey" + "sage\022\026\n\016registrationId\030\005 \001(\r\022\020\n\010preKeyId" +
"Id\030\001 \001(\r\022\026\n\016signedPreKeyId\030\006 \001(\r\022\017\n\007base" + "\030\001 \001(\r\022\026\n\016signedPreKeyId\030\006 \001(\r\022\017\n\007baseKe" +
"Key\030\002 \001(\014\022\023\n\013identityKey\030\003 \001(\014\022\024\n\014verifi" + "y\030\002 \001(\014\022\023\n\013identityKey\030\003 \001(\014\022\024\n\014verifica" +
"cation\030\007 \001(\014\022\017\n\007message\030\004 \001(\014\"\214\001\n\022KeyExc" + "tion\030\007 \001(\014\022\017\n\007message\030\004 \001(\014\"t\n\022KeyExchan" +
"hangeMessage\022\n\n\002id\030\001 \001(\r\022\017\n\007baseKey\030\002 \001(" + "geMessage\022\n\n\002id\030\001 \001(\r\022\017\n\007baseKey\030\002 \001(\014\022\022" +
"\014\022\024\n\014ephemeralKey\030\003 \001(\014\022\023\n\013identityKey\030\004", "\n\nratchetKey\030\003 \001(\014\022\023\n\013identityKey\030\004 \001(\014\022",
" \001(\014\022\030\n\020baseKeySignature\030\005 \001(\014\022\024\n\014verifi" + "\030\n\020baseKeySignature\030\005 \001(\014B7\n&org.whisper" +
"cation\030\006 \001(\014B7\n&org.whispersystems.libax" + "systems.libaxolotl.protocolB\rWhisperProt" +
"olotl.protocolB\rWhisperProtos" "os"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -2443,7 +2391,7 @@ public final class WhisperProtos {
internal_static_textsecure_WhisperMessage_fieldAccessorTable = new internal_static_textsecure_WhisperMessage_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_WhisperMessage_descriptor, 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 = internal_static_textsecure_PreKeyWhisperMessage_descriptor =
getDescriptor().getMessageTypes().get(1); getDescriptor().getMessageTypes().get(1);
internal_static_textsecure_PreKeyWhisperMessage_fieldAccessorTable = new internal_static_textsecure_PreKeyWhisperMessage_fieldAccessorTable = new
@ -2455,7 +2403,7 @@ public final class WhisperProtos {
internal_static_textsecure_KeyExchangeMessage_fieldAccessorTable = new internal_static_textsecure_KeyExchangeMessage_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_KeyExchangeMessage_descriptor, 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; return null;
} }
}; };

View File

@ -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<ECPublicKey> theirOneTimePreKey;
private final ECPublicKey theirRatchetKey;
private AliceAxolotlParameters(IdentityKeyPair ourIdentityKey, ECKeyPair ourBaseKey,
IdentityKey theirIdentityKey, ECPublicKey theirSignedPreKey,
ECPublicKey theirRatchetKey, Optional<ECPublicKey> 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<ECPublicKey> 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<ECPublicKey> 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<ECPublicKey> theirOneTimePreKey) {
this.theirOneTimePreKey = theirOneTimePreKey;
return this;
}
public AliceAxolotlParameters create() {
return new AliceAxolotlParameters(ourIdentityKey, ourBaseKey, theirIdentityKey,
theirSignedPreKey, theirRatchetKey, theirOneTimePreKey);
}
}
}

View File

@ -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<ECKeyPair> ourOneTimePreKey;
private final ECKeyPair ourRatchetKey;
private final IdentityKey theirIdentityKey;
private final ECPublicKey theirBaseKey;
BobAxolotlParameters(IdentityKeyPair ourIdentityKey, ECKeyPair ourSignedPreKey,
ECKeyPair ourRatchetKey, Optional<ECKeyPair> 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<ECKeyPair> 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<ECKeyPair> 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<ECKeyPair> 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);
}
}
}

View File

@ -16,8 +16,6 @@
*/ */
package org.whispersystems.libaxolotl.ratchet; package org.whispersystems.libaxolotl.ratchet;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.IdentityKeyPair;
import org.whispersystems.libaxolotl.InvalidKeyException; import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.ecc.Curve; import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair; import org.whispersystems.libaxolotl.ecc.ECKeyPair;
@ -37,288 +35,176 @@ public class RatchetingSession {
public static void initializeSession(SessionState sessionState, public static void initializeSession(SessionState sessionState,
int sessionVersion, int sessionVersion,
AxolotlParameters parameters) SymmetricAxolotlParameters parameters)
throws InvalidKeyException throws InvalidKeyException
{ {
if (isAlice(parameters)) initializeSessionAsAlice(sessionState, sessionVersion, parameters); if (isAlice(parameters.getOurBaseKey().getPublicKey(), parameters.getTheirBaseKey())) {
else initializeSessionAsBob(sessionState, sessionVersion, parameters); 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.<ECPublicKey>absent());
private static void initializeSessionAsAlice(SessionState sessionState, RatchetingSession.initializeSession(sessionState, sessionVersion, aliceParameters.create());
int sessionVersion, } else {
AxolotlParameters parameters) BobAxolotlParameters.Builder bobParameters = BobAxolotlParameters.newBuilder();
throws InvalidKeyException
{
sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey());
sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey());
ECKeyPair sendingKey = Curve.generateKeyPair(true); bobParameters.setOurIdentityKey(parameters.getOurIdentityKey())
DHEResult result = calculate4DHE(true, sessionVersion, parameters); .setOurRatchetKey(parameters.getOurRatchetKey())
.setOurSignedPreKey(parameters.getOurBaseKey())
.setOurOneTimePreKey(Optional.<ECKeyPair>absent())
.setTheirBaseKey(parameters.getTheirBaseKey())
.setTheirIdentityKey(parameters.getTheirIdentityKey());
Pair<RootKey, ChainKey> sendingChain = result.getRootKey().createChain(parameters.getTheirEphemeralKey(), sendingKey); RatchetingSession.initializeSession(sessionState, sessionVersion, bobParameters.create());
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));
} }
} }
private static void initializeSessionAsBob(SessionState sessionState, public static void initializeSession(SessionState sessionState,
int sessionVersion, int sessionVersion,
AxolotlParameters parameters) AliceAxolotlParameters 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)
throws InvalidKeyException throws InvalidKeyException
{ {
try { try {
HKDF kdf = HKDF.createFor(sessionVersion); sessionState.setSessionVersion(sessionVersion);
byte[] discontinuity = new byte[32]; sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey());
ByteArrayOutputStream secrets = new ByteArrayOutputStream(); sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey());
ECKeyPair sendingRatchetKey = Curve.generateKeyPair(true);
ByteArrayOutputStream secrets = new ByteArrayOutputStream();
if (sessionVersion >= 3) { if (sessionVersion >= 3) {
Arrays.fill(discontinuity, (byte) 0xFF); secrets.write(getDiscontinuityBytes());
secrets.write(discontinuity);
} }
if (isAlice) { secrets.write(Curve.calculateAgreement(parameters.getTheirSignedPreKey(),
secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(), parameters.getOurIdentityKey().getPrivateKey()));
parameters.getOurIdentityKey().getPrivateKey())); secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(),
secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), parameters.getOurBaseKey().getPrivateKey()));
parameters.getOurBaseKey().getPrivateKey())); secrets.write(Curve.calculateAgreement(parameters.getTheirSignedPreKey(),
} 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(),
parameters.getOurBaseKey().getPrivateKey())); parameters.getOurBaseKey().getPrivateKey()));
if (sessionVersion >= 3 && parameters.getTheirPreKey().isPresent() && parameters.getOurPreKey().isPresent()) { if (sessionVersion >= 3 & parameters.getTheirOneTimePreKey().isPresent()) {
secrets.write(Curve.calculateAgreement(parameters.getTheirPreKey().get(), parameters.getOurPreKey().get().getPrivateKey())); secrets.write(Curve.calculateAgreement(parameters.getTheirOneTimePreKey().get(),
parameters.getOurBaseKey().getPrivateKey()));
} }
byte[] derivedSecretBytes = kdf.deriveSecrets(secrets.toByteArray(), "WhisperText".getBytes(), 96); DerivedKeys derivedKeys = calculateDerivedKeys(sessionVersion, secrets.toByteArray());
byte[][] derivedSecrets = ByteUtil.split(derivedSecretBytes, 32, 32, 32); Pair<RootKey, ChainKey> sendingChain = derivedKeys.getRootKey().createChain(parameters.getTheirRatchetKey(), sendingRatchetKey);
return new DHEResult(new RootKey(kdf, derivedSecrets[0]), sessionState.addReceiverChain(parameters.getTheirRatchetKey(), derivedKeys.getChainKey());
new ChainKey(kdf, derivedSecrets[1], 0), sessionState.setSenderChain(sendingRatchetKey, sendingChain.second());
new VerifyKey(derivedSecrets[2])); sessionState.setRootKey(sendingChain.first());
} catch (IOException | ParseException e) { if (sessionVersion >= 3) {
sessionState.setVerification(calculateVerificationTag(derivedKeys.getVerifyKey(), parameters));
}
} catch (IOException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }
private static byte[] calculateVerificationTag(boolean isAlice, VerifyKey verifyKey, public static void initializeSession(SessionState sessionState,
AxolotlParameters parameters) int sessionVersion,
BobAxolotlParameters parameters)
throws InvalidKeyException
{ {
if (isAlice) {
return verifyKey.generateVerification(parameters.getOurBaseKey().getPublicKey(), try {
getPublicKey(parameters.getOurPreKey()), sessionState.setSessionVersion(sessionVersion);
parameters.getOurIdentityKey().getPublicKey().getPublicKey(), sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey());
parameters.getTheirBaseKey(), sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey());
parameters.getTheirPreKey(),
parameters.getTheirIdentityKey().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<ECPublicKey> ourOneTimePreKey;
if (parameters.getOurOneTimePreKey().isPresent()) {
ourOneTimePreKey = Optional.of(parameters.getOurOneTimePreKey().get().getPublicKey());
} else { } else {
return verifyKey.generateVerification(parameters.getTheirBaseKey(), ourOneTimePreKey = Optional.absent();
parameters.getTheirPreKey(), }
parameters.getTheirIdentityKey().getPublicKey(),
parameters.getOurBaseKey().getPublicKey(), return verifyKey.generateVerification(parameters.getTheirIdentityKey(),
getPublicKey(parameters.getOurPreKey()), parameters.getOurIdentityKey().getPublicKey(),
parameters.getOurIdentityKey().getPublicKey().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) private static boolean isAlice(ECPublicKey ourKey, ECPublicKey theirKey) {
{
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) {
return ourKey.compareTo(theirKey) < 0; return ourKey.compareTo(theirKey) < 0;
} }
private static Optional<ECPublicKey> getPublicKey(Optional<ECKeyPair> keyPair) {
if (keyPair.isPresent()) return Optional.of(keyPair.get().getPublicKey());
else return Optional.absent();
}
public static class AxolotlParameters { private static class DerivedKeys {
private final ECKeyPair ourBaseKey;
private final ECKeyPair ourEphemeralKey;
private final Optional<ECKeyPair> ourPreKey;
private final IdentityKeyPair ourIdentityKey;
private final ECPublicKey theirBaseKey;
private final ECPublicKey theirEphemeralKey;
private final Optional<ECPublicKey> theirPreKey;
private final IdentityKey theirIdentityKey;
public AxolotlParameters(ECKeyPair ourBaseKey, ECKeyPair ourEphemeralKey,
Optional<ECKeyPair> ourPreKey, IdentityKeyPair ourIdentityKey,
ECPublicKey theirBaseKey, ECPublicKey theirEphemeralKey,
Optional<ECPublicKey> 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<ECKeyPair> getOurPreKey() {
return ourPreKey;
}
public IdentityKeyPair getOurIdentityKey() {
return ourIdentityKey;
}
public ECPublicKey getTheirBaseKey() {
return theirBaseKey;
}
public ECPublicKey getTheirEphemeralKey() {
return theirEphemeralKey;
}
public Optional<ECPublicKey> 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<ECKeyPair> ourPreKey;
private IdentityKeyPair ourIdentityKey;
private ECPublicKey theirBaseKey;
private ECPublicKey theirEphemeralKey;
private Optional<ECPublicKey> 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<ECKeyPair> 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<ECPublicKey> 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 final RootKey rootKey; private final RootKey rootKey;
private final ChainKey chainKey; private final ChainKey chainKey;
private final VerifyKey verifyKey; private final VerifyKey verifyKey;
private DHEResult(RootKey rootKey, ChainKey chainKey, VerifyKey verifyKey) { private DerivedKeys(RootKey rootKey, ChainKey chainKey, VerifyKey verifyKey) {
this.rootKey = rootKey; this.rootKey = rootKey;
this.chainKey = chainKey; this.chainKey = chainKey;
this.verifyKey = verifyKey; this.verifyKey = verifyKey;
@ -336,5 +222,4 @@ public class RatchetingSession {
return verifyKey; return verifyKey;
} }
} }
} }

View File

@ -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);
}
}
}

View File

@ -1,5 +1,6 @@
package org.whispersystems.libaxolotl.ratchet; package org.whispersystems.libaxolotl.ratchet;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.ecc.ECPublicKey; import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.util.ByteUtil; import org.whispersystems.libaxolotl.util.ByteUtil;
import org.whispersystems.libaxolotl.util.guava.Optional; import org.whispersystems.libaxolotl.util.guava.Optional;
@ -24,29 +25,26 @@ public class VerifyKey {
return key; return key;
} }
public byte[] generateVerification(ECPublicKey aliceBaseKey, public byte[] generateVerification(IdentityKey aliceIdentity,
Optional<ECPublicKey> alicePreKey, IdentityKey bobIdentity,
ECPublicKey aliceIdentityKey, ECPublicKey aliceBaseKey,
ECPublicKey bobBaseKey, ECPublicKey bobSignedPreKey,
Optional<ECPublicKey> bobPreKey, Optional<ECPublicKey> bobOneTimePreKey)
ECPublicKey bobIdentityKey)
{ {
try { try {
Mac mac = Mac.getInstance("HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key, "HmacSHA256")); mac.init(new SecretKeySpec(key, "HmacSHA256"));
mac.update(VERIFICATION_INFO); mac.update(VERIFICATION_INFO);
mac.update(aliceIdentity.getPublicKey().serialize());
mac.update(bobIdentity.getPublicKey().serialize());
mac.update(aliceBaseKey.serialize()); mac.update(aliceBaseKey.serialize());
mac.update(aliceIdentityKey.serialize()); mac.update(bobSignedPreKey.serialize());
mac.update(bobBaseKey.serialize());
mac.update(bobIdentityKey.serialize());
if (alicePreKey.isPresent() && bobPreKey.isPresent()) { if (bobOneTimePreKey.isPresent()) {
mac.update(alicePreKey.get().serialize()); mac.update(bobOneTimePreKey.get().serialize());
mac.update(bobPreKey.get().serialize());
} }
return ByteUtil.trim(mac.doFinal(), 8); return ByteUtil.trim(mac.doFinal(), 8);
} catch (NoSuchAlgorithmException | InvalidKeyException e) { } catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new AssertionError(e); throw new AssertionError(e);

View File

@ -32,11 +32,10 @@ import org.whispersystems.libaxolotl.kdf.HKDF;
import org.whispersystems.libaxolotl.ratchet.ChainKey; import org.whispersystems.libaxolotl.ratchet.ChainKey;
import org.whispersystems.libaxolotl.ratchet.MessageKeys; import org.whispersystems.libaxolotl.ratchet.MessageKeys;
import org.whispersystems.libaxolotl.ratchet.RootKey; 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.Chain;
import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange; import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange;
import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey; import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey;
import org.whispersystems.libaxolotl.util.Pair;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@ -159,18 +158,18 @@ public class SessionState {
.build(); .build();
} }
public ECPublicKey getSenderEphemeral() { public ECPublicKey getSenderRatchetKey() {
try { try {
return Curve.decodePoint(sessionStructure.getSenderChain().getSenderEphemeral().toByteArray(), 0); return Curve.decodePoint(sessionStructure.getSenderChain().getSenderRatchetKey().toByteArray(), 0);
} catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }
public ECKeyPair getSenderEphemeralPair() { public ECKeyPair getSenderRatchetKeyPair() {
ECPublicKey publicKey = getSenderEphemeral(); ECPublicKey publicKey = getSenderRatchetKey();
ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getSenderChain() ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getSenderChain()
.getSenderEphemeralPrivate() .getSenderRatchetKeyPrivate()
.toByteArray()); .toByteArray());
return new ECKeyPair(publicKey, privateKey); return new ECKeyPair(publicKey, privateKey);
@ -190,9 +189,9 @@ public class SessionState {
for (Chain receiverChain : receiverChains) { for (Chain receiverChain : receiverChains) {
try { 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); return new Pair<>(receiverChain,index);
} }
} catch (InvalidKeyException e) { } 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() Chain.ChainKey chainKeyStructure = Chain.ChainKey.newBuilder()
.setKey(ByteString.copyFrom(chainKey.getKey())) .setKey(ByteString.copyFrom(chainKey.getKey()))
.setIndex(chainKey.getIndex()) .setIndex(chainKey.getIndex())
@ -226,7 +225,7 @@ public class SessionState {
Chain chain = Chain.newBuilder() Chain chain = Chain.newBuilder()
.setChainKey(chainKeyStructure) .setChainKey(chainKeyStructure)
.setSenderEphemeral(ByteString.copyFrom(senderEphemeral.serialize())) .setSenderRatchetKey(ByteString.copyFrom(senderRatchetKey.serialize()))
.build(); .build();
this.sessionStructure = this.sessionStructure.toBuilder().addReceiverChains(chain).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() Chain.ChainKey chainKeyStructure = Chain.ChainKey.newBuilder()
.setKey(ByteString.copyFrom(chainKey.getKey())) .setKey(ByteString.copyFrom(chainKey.getKey()))
.setIndex(chainKey.getIndex()) .setIndex(chainKey.getIndex())
.build(); .build();
Chain senderChain = Chain.newBuilder() Chain senderChain = Chain.newBuilder()
.setSenderEphemeral(ByteString.copyFrom(senderEphemeralPair.getPublicKey().serialize())) .setSenderRatchetKey(ByteString.copyFrom(senderRatchetKeyPair.getPublicKey().serialize()))
.setSenderEphemeralPrivate(ByteString.copyFrom(senderEphemeralPair.getPrivateKey().serialize())) .setSenderRatchetKeyPrivate(ByteString.copyFrom(senderRatchetKeyPair.getPrivateKey().serialize()))
.setChainKey(chainKeyStructure) .setChainKey(chainKeyStructure)
.build(); .build();
@ -363,7 +362,7 @@ public class SessionState {
public void setPendingKeyExchange(int sequence, public void setPendingKeyExchange(int sequence,
ECKeyPair ourBaseKey, ECKeyPair ourBaseKey,
ECKeyPair ourEphemeralKey, ECKeyPair ourRatchetKey,
IdentityKeyPair ourIdentityKey) IdentityKeyPair ourIdentityKey)
{ {
PendingKeyExchange structure = PendingKeyExchange structure =
@ -371,8 +370,8 @@ public class SessionState {
.setSequence(sequence) .setSequence(sequence)
.setLocalBaseKey(ByteString.copyFrom(ourBaseKey.getPublicKey().serialize())) .setLocalBaseKey(ByteString.copyFrom(ourBaseKey.getPublicKey().serialize()))
.setLocalBaseKeyPrivate(ByteString.copyFrom(ourBaseKey.getPrivateKey().serialize())) .setLocalBaseKeyPrivate(ByteString.copyFrom(ourBaseKey.getPrivateKey().serialize()))
.setLocalEphemeralKey(ByteString.copyFrom(ourEphemeralKey.getPublicKey().serialize())) .setLocalRatchetKey(ByteString.copyFrom(ourRatchetKey.getPublicKey().serialize()))
.setLocalEphemeralKeyPrivate(ByteString.copyFrom(ourEphemeralKey.getPrivateKey().serialize())) .setLocalRatchetKeyPrivate(ByteString.copyFrom(ourRatchetKey.getPrivateKey().serialize()))
.setLocalIdentityKey(ByteString.copyFrom(ourIdentityKey.getPublicKey().serialize())) .setLocalIdentityKey(ByteString.copyFrom(ourIdentityKey.getPublicKey().serialize()))
.setLocalIdentityKeyPrivate(ByteString.copyFrom(ourIdentityKey.getPrivateKey().serialize())) .setLocalIdentityKeyPrivate(ByteString.copyFrom(ourIdentityKey.getPrivateKey().serialize()))
.build(); .build();
@ -397,12 +396,12 @@ public class SessionState {
return new ECKeyPair(publicKey, privateKey); return new ECKeyPair(publicKey, privateKey);
} }
public ECKeyPair getPendingKeyExchangeEphemeralKey() throws InvalidKeyException { public ECKeyPair getPendingKeyExchangeRatchetKey() throws InvalidKeyException {
ECPublicKey publicKey = Curve.decodePoint(sessionStructure.getPendingKeyExchange() ECPublicKey publicKey = Curve.decodePoint(sessionStructure.getPendingKeyExchange()
.getLocalEphemeralKey().toByteArray(), 0); .getLocalRatchetKey().toByteArray(), 0);
ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getPendingKeyExchange() ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getPendingKeyExchange()
.getLocalEphemeralKeyPrivate() .getLocalRatchetKeyPrivate()
.toByteArray()); .toByteArray());
return new ECKeyPair(publicKey, privateKey); return new ECKeyPair(publicKey, privateKey);

View File

@ -371,25 +371,25 @@ public final class StorageProtos {
public interface ChainOrBuilder public interface ChainOrBuilder
extends com.google.protobuf.MessageOrBuilder { extends com.google.protobuf.MessageOrBuilder {
// optional bytes senderEphemeral = 1; // optional bytes senderRatchetKey = 1;
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
boolean hasSenderEphemeral(); boolean hasSenderRatchetKey();
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
com.google.protobuf.ByteString getSenderEphemeral(); com.google.protobuf.ByteString getSenderRatchetKey();
// optional bytes senderEphemeralPrivate = 2; // optional bytes senderRatchetKeyPrivate = 2;
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
boolean hasSenderEphemeralPrivate(); boolean hasSenderRatchetKeyPrivate();
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
com.google.protobuf.ByteString getSenderEphemeralPrivate(); com.google.protobuf.ByteString getSenderRatchetKeyPrivate();
// optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3; // optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;
/** /**
@ -483,12 +483,12 @@ public final class StorageProtos {
} }
case 10: { case 10: {
bitField0_ |= 0x00000001; bitField0_ |= 0x00000001;
senderEphemeral_ = input.readBytes(); senderRatchetKey_ = input.readBytes();
break; break;
} }
case 18: { case 18: {
bitField0_ |= 0x00000002; bitField0_ |= 0x00000002;
senderEphemeralPrivate_ = input.readBytes(); senderRatchetKeyPrivate_ = input.readBytes();
break; break;
} }
case 26: { case 26: {
@ -1599,36 +1599,36 @@ public final class StorageProtos {
} }
private int bitField0_; private int bitField0_;
// optional bytes senderEphemeral = 1; // optional bytes senderRatchetKey = 1;
public static final int SENDEREPHEMERAL_FIELD_NUMBER = 1; public static final int SENDERRATCHETKEY_FIELD_NUMBER = 1;
private com.google.protobuf.ByteString senderEphemeral_; private com.google.protobuf.ByteString senderRatchetKey_;
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
public boolean hasSenderEphemeral() { public boolean hasSenderRatchetKey() {
return ((bitField0_ & 0x00000001) == 0x00000001); return ((bitField0_ & 0x00000001) == 0x00000001);
} }
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
public com.google.protobuf.ByteString getSenderEphemeral() { public com.google.protobuf.ByteString getSenderRatchetKey() {
return senderEphemeral_; return senderRatchetKey_;
} }
// optional bytes senderEphemeralPrivate = 2; // optional bytes senderRatchetKeyPrivate = 2;
public static final int SENDEREPHEMERALPRIVATE_FIELD_NUMBER = 2; public static final int SENDERRATCHETKEYPRIVATE_FIELD_NUMBER = 2;
private com.google.protobuf.ByteString senderEphemeralPrivate_; private com.google.protobuf.ByteString senderRatchetKeyPrivate_;
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
public boolean hasSenderEphemeralPrivate() { public boolean hasSenderRatchetKeyPrivate() {
return ((bitField0_ & 0x00000002) == 0x00000002); return ((bitField0_ & 0x00000002) == 0x00000002);
} }
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
public com.google.protobuf.ByteString getSenderEphemeralPrivate() { public com.google.protobuf.ByteString getSenderRatchetKeyPrivate() {
return senderEphemeralPrivate_; return senderRatchetKeyPrivate_;
} }
// optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3; // optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;
@ -1690,8 +1690,8 @@ public final class StorageProtos {
} }
private void initFields() { private void initFields() {
senderEphemeral_ = com.google.protobuf.ByteString.EMPTY; senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
senderEphemeralPrivate_ = com.google.protobuf.ByteString.EMPTY; senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance(); chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance();
messageKeys_ = java.util.Collections.emptyList(); messageKeys_ = java.util.Collections.emptyList();
} }
@ -1708,10 +1708,10 @@ public final class StorageProtos {
throws java.io.IOException { throws java.io.IOException {
getSerializedSize(); getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) { if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBytes(1, senderEphemeral_); output.writeBytes(1, senderRatchetKey_);
} }
if (((bitField0_ & 0x00000002) == 0x00000002)) { if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBytes(2, senderEphemeralPrivate_); output.writeBytes(2, senderRatchetKeyPrivate_);
} }
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeMessage(3, chainKey_); output.writeMessage(3, chainKey_);
@ -1730,11 +1730,11 @@ public final class StorageProtos {
size = 0; size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) { if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, senderEphemeral_); .computeBytesSize(1, senderRatchetKey_);
} }
if (((bitField0_ & 0x00000002) == 0x00000002)) { if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(2, senderEphemeralPrivate_); .computeBytesSize(2, senderRatchetKeyPrivate_);
} }
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
@ -1862,9 +1862,9 @@ public final class StorageProtos {
public Builder clear() { public Builder clear() {
super.clear(); super.clear();
senderEphemeral_ = com.google.protobuf.ByteString.EMPTY; senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000001);
senderEphemeralPrivate_ = com.google.protobuf.ByteString.EMPTY; senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
if (chainKeyBuilder_ == null) { if (chainKeyBuilder_ == null) {
chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance(); chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance();
@ -1909,11 +1909,11 @@ public final class StorageProtos {
if (((from_bitField0_ & 0x00000001) == 0x00000001)) { if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001; to_bitField0_ |= 0x00000001;
} }
result.senderEphemeral_ = senderEphemeral_; result.senderRatchetKey_ = senderRatchetKey_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) { if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002; to_bitField0_ |= 0x00000002;
} }
result.senderEphemeralPrivate_ = senderEphemeralPrivate_; result.senderRatchetKeyPrivate_ = senderRatchetKeyPrivate_;
if (((from_bitField0_ & 0x00000004) == 0x00000004)) { if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004; to_bitField0_ |= 0x00000004;
} }
@ -1947,11 +1947,11 @@ public final class StorageProtos {
public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain other) { 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 == org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance()) return this;
if (other.hasSenderEphemeral()) { if (other.hasSenderRatchetKey()) {
setSenderEphemeral(other.getSenderEphemeral()); setSenderRatchetKey(other.getSenderRatchetKey());
} }
if (other.hasSenderEphemeralPrivate()) { if (other.hasSenderRatchetKeyPrivate()) {
setSenderEphemeralPrivate(other.getSenderEphemeralPrivate()); setSenderRatchetKeyPrivate(other.getSenderRatchetKeyPrivate());
} }
if (other.hasChainKey()) { if (other.hasChainKey()) {
mergeChainKey(other.getChainKey()); mergeChainKey(other.getChainKey());
@ -2009,74 +2009,74 @@ public final class StorageProtos {
} }
private int bitField0_; private int bitField0_;
// optional bytes senderEphemeral = 1; // optional bytes senderRatchetKey = 1;
private com.google.protobuf.ByteString senderEphemeral_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
public boolean hasSenderEphemeral() { public boolean hasSenderRatchetKey() {
return ((bitField0_ & 0x00000001) == 0x00000001); return ((bitField0_ & 0x00000001) == 0x00000001);
} }
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
public com.google.protobuf.ByteString getSenderEphemeral() { public com.google.protobuf.ByteString getSenderRatchetKey() {
return senderEphemeral_; return senderRatchetKey_;
} }
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
public Builder setSenderEphemeral(com.google.protobuf.ByteString value) { public Builder setSenderRatchetKey(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
bitField0_ |= 0x00000001; bitField0_ |= 0x00000001;
senderEphemeral_ = value; senderRatchetKey_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>optional bytes senderEphemeral = 1;</code> * <code>optional bytes senderRatchetKey = 1;</code>
*/ */
public Builder clearSenderEphemeral() { public Builder clearSenderRatchetKey() {
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000001);
senderEphemeral_ = getDefaultInstance().getSenderEphemeral(); senderRatchetKey_ = getDefaultInstance().getSenderRatchetKey();
onChanged(); onChanged();
return this; return this;
} }
// optional bytes senderEphemeralPrivate = 2; // optional bytes senderRatchetKeyPrivate = 2;
private com.google.protobuf.ByteString senderEphemeralPrivate_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
public boolean hasSenderEphemeralPrivate() { public boolean hasSenderRatchetKeyPrivate() {
return ((bitField0_ & 0x00000002) == 0x00000002); return ((bitField0_ & 0x00000002) == 0x00000002);
} }
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
public com.google.protobuf.ByteString getSenderEphemeralPrivate() { public com.google.protobuf.ByteString getSenderRatchetKeyPrivate() {
return senderEphemeralPrivate_; return senderRatchetKeyPrivate_;
} }
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
public Builder setSenderEphemeralPrivate(com.google.protobuf.ByteString value) { public Builder setSenderRatchetKeyPrivate(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
bitField0_ |= 0x00000002; bitField0_ |= 0x00000002;
senderEphemeralPrivate_ = value; senderRatchetKeyPrivate_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>optional bytes senderEphemeralPrivate = 2;</code> * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
*/ */
public Builder clearSenderEphemeralPrivate() { public Builder clearSenderRatchetKeyPrivate() {
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
senderEphemeralPrivate_ = getDefaultInstance().getSenderEphemeralPrivate(); senderRatchetKeyPrivate_ = getDefaultInstance().getSenderRatchetKeyPrivate();
onChanged(); onChanged();
return this; return this;
} }
@ -2482,25 +2482,25 @@ public final class StorageProtos {
*/ */
com.google.protobuf.ByteString getLocalBaseKeyPrivate(); com.google.protobuf.ByteString getLocalBaseKeyPrivate();
// optional bytes localEphemeralKey = 4; // optional bytes localRatchetKey = 4;
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
boolean hasLocalEphemeralKey(); boolean hasLocalRatchetKey();
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
com.google.protobuf.ByteString getLocalEphemeralKey(); com.google.protobuf.ByteString getLocalRatchetKey();
// optional bytes localEphemeralKeyPrivate = 5; // optional bytes localRatchetKeyPrivate = 5;
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
boolean hasLocalEphemeralKeyPrivate(); boolean hasLocalRatchetKeyPrivate();
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
com.google.protobuf.ByteString getLocalEphemeralKeyPrivate(); com.google.protobuf.ByteString getLocalRatchetKeyPrivate();
// optional bytes localIdentityKey = 7; // optional bytes localIdentityKey = 7;
/** /**
@ -2590,12 +2590,12 @@ public final class StorageProtos {
} }
case 34: { case 34: {
bitField0_ |= 0x00000008; bitField0_ |= 0x00000008;
localEphemeralKey_ = input.readBytes(); localRatchetKey_ = input.readBytes();
break; break;
} }
case 42: { case 42: {
bitField0_ |= 0x00000010; bitField0_ |= 0x00000010;
localEphemeralKeyPrivate_ = input.readBytes(); localRatchetKeyPrivate_ = input.readBytes();
break; break;
} }
case 58: { case 58: {
@ -2696,36 +2696,36 @@ public final class StorageProtos {
return localBaseKeyPrivate_; return localBaseKeyPrivate_;
} }
// optional bytes localEphemeralKey = 4; // optional bytes localRatchetKey = 4;
public static final int LOCALEPHEMERALKEY_FIELD_NUMBER = 4; public static final int LOCALRATCHETKEY_FIELD_NUMBER = 4;
private com.google.protobuf.ByteString localEphemeralKey_; private com.google.protobuf.ByteString localRatchetKey_;
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
public boolean hasLocalEphemeralKey() { public boolean hasLocalRatchetKey() {
return ((bitField0_ & 0x00000008) == 0x00000008); return ((bitField0_ & 0x00000008) == 0x00000008);
} }
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
public com.google.protobuf.ByteString getLocalEphemeralKey() { public com.google.protobuf.ByteString getLocalRatchetKey() {
return localEphemeralKey_; return localRatchetKey_;
} }
// optional bytes localEphemeralKeyPrivate = 5; // optional bytes localRatchetKeyPrivate = 5;
public static final int LOCALEPHEMERALKEYPRIVATE_FIELD_NUMBER = 5; public static final int LOCALRATCHETKEYPRIVATE_FIELD_NUMBER = 5;
private com.google.protobuf.ByteString localEphemeralKeyPrivate_; private com.google.protobuf.ByteString localRatchetKeyPrivate_;
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
public boolean hasLocalEphemeralKeyPrivate() { public boolean hasLocalRatchetKeyPrivate() {
return ((bitField0_ & 0x00000010) == 0x00000010); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
public com.google.protobuf.ByteString getLocalEphemeralKeyPrivate() { public com.google.protobuf.ByteString getLocalRatchetKeyPrivate() {
return localEphemeralKeyPrivate_; return localRatchetKeyPrivate_;
} }
// optional bytes localIdentityKey = 7; // optional bytes localIdentityKey = 7;
@ -2764,8 +2764,8 @@ public final class StorageProtos {
sequence_ = 0; sequence_ = 0;
localBaseKey_ = com.google.protobuf.ByteString.EMPTY; localBaseKey_ = com.google.protobuf.ByteString.EMPTY;
localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
localEphemeralKey_ = com.google.protobuf.ByteString.EMPTY; localRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
localEphemeralKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
localIdentityKey_ = com.google.protobuf.ByteString.EMPTY; localIdentityKey_ = com.google.protobuf.ByteString.EMPTY;
localIdentityKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; localIdentityKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
} }
@ -2791,10 +2791,10 @@ public final class StorageProtos {
output.writeBytes(3, localBaseKeyPrivate_); output.writeBytes(3, localBaseKeyPrivate_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeBytes(4, localEphemeralKey_); output.writeBytes(4, localRatchetKey_);
} }
if (((bitField0_ & 0x00000010) == 0x00000010)) { if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeBytes(5, localEphemeralKeyPrivate_); output.writeBytes(5, localRatchetKeyPrivate_);
} }
if (((bitField0_ & 0x00000020) == 0x00000020)) { if (((bitField0_ & 0x00000020) == 0x00000020)) {
output.writeBytes(7, localIdentityKey_); output.writeBytes(7, localIdentityKey_);
@ -2825,11 +2825,11 @@ public final class StorageProtos {
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(4, localEphemeralKey_); .computeBytesSize(4, localRatchetKey_);
} }
if (((bitField0_ & 0x00000010) == 0x00000010)) { if (((bitField0_ & 0x00000010) == 0x00000010)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(5, localEphemeralKeyPrivate_); .computeBytesSize(5, localRatchetKeyPrivate_);
} }
if (((bitField0_ & 0x00000020) == 0x00000020)) { if (((bitField0_ & 0x00000020) == 0x00000020)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
@ -2961,9 +2961,9 @@ public final class StorageProtos {
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000002);
localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000004);
localEphemeralKey_ = com.google.protobuf.ByteString.EMPTY; localRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000008); bitField0_ = (bitField0_ & ~0x00000008);
localEphemeralKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000010); bitField0_ = (bitField0_ & ~0x00000010);
localIdentityKey_ = com.google.protobuf.ByteString.EMPTY; localIdentityKey_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000020); bitField0_ = (bitField0_ & ~0x00000020);
@ -3012,11 +3012,11 @@ public final class StorageProtos {
if (((from_bitField0_ & 0x00000008) == 0x00000008)) { if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008; to_bitField0_ |= 0x00000008;
} }
result.localEphemeralKey_ = localEphemeralKey_; result.localRatchetKey_ = localRatchetKey_;
if (((from_bitField0_ & 0x00000010) == 0x00000010)) { if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000010; to_bitField0_ |= 0x00000010;
} }
result.localEphemeralKeyPrivate_ = localEphemeralKeyPrivate_; result.localRatchetKeyPrivate_ = localRatchetKeyPrivate_;
if (((from_bitField0_ & 0x00000020) == 0x00000020)) { if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
to_bitField0_ |= 0x00000020; to_bitField0_ |= 0x00000020;
} }
@ -3050,11 +3050,11 @@ public final class StorageProtos {
if (other.hasLocalBaseKeyPrivate()) { if (other.hasLocalBaseKeyPrivate()) {
setLocalBaseKeyPrivate(other.getLocalBaseKeyPrivate()); setLocalBaseKeyPrivate(other.getLocalBaseKeyPrivate());
} }
if (other.hasLocalEphemeralKey()) { if (other.hasLocalRatchetKey()) {
setLocalEphemeralKey(other.getLocalEphemeralKey()); setLocalRatchetKey(other.getLocalRatchetKey());
} }
if (other.hasLocalEphemeralKeyPrivate()) { if (other.hasLocalRatchetKeyPrivate()) {
setLocalEphemeralKeyPrivate(other.getLocalEphemeralKeyPrivate()); setLocalRatchetKeyPrivate(other.getLocalRatchetKeyPrivate());
} }
if (other.hasLocalIdentityKey()) { if (other.hasLocalIdentityKey()) {
setLocalIdentityKey(other.getLocalIdentityKey()); setLocalIdentityKey(other.getLocalIdentityKey());
@ -3194,74 +3194,74 @@ public final class StorageProtos {
return this; return this;
} }
// optional bytes localEphemeralKey = 4; // optional bytes localRatchetKey = 4;
private com.google.protobuf.ByteString localEphemeralKey_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString localRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
public boolean hasLocalEphemeralKey() { public boolean hasLocalRatchetKey() {
return ((bitField0_ & 0x00000008) == 0x00000008); return ((bitField0_ & 0x00000008) == 0x00000008);
} }
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
public com.google.protobuf.ByteString getLocalEphemeralKey() { public com.google.protobuf.ByteString getLocalRatchetKey() {
return localEphemeralKey_; return localRatchetKey_;
} }
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
public Builder setLocalEphemeralKey(com.google.protobuf.ByteString value) { public Builder setLocalRatchetKey(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
bitField0_ |= 0x00000008; bitField0_ |= 0x00000008;
localEphemeralKey_ = value; localRatchetKey_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>optional bytes localEphemeralKey = 4;</code> * <code>optional bytes localRatchetKey = 4;</code>
*/ */
public Builder clearLocalEphemeralKey() { public Builder clearLocalRatchetKey() {
bitField0_ = (bitField0_ & ~0x00000008); bitField0_ = (bitField0_ & ~0x00000008);
localEphemeralKey_ = getDefaultInstance().getLocalEphemeralKey(); localRatchetKey_ = getDefaultInstance().getLocalRatchetKey();
onChanged(); onChanged();
return this; return this;
} }
// optional bytes localEphemeralKeyPrivate = 5; // optional bytes localRatchetKeyPrivate = 5;
private com.google.protobuf.ByteString localEphemeralKeyPrivate_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
public boolean hasLocalEphemeralKeyPrivate() { public boolean hasLocalRatchetKeyPrivate() {
return ((bitField0_ & 0x00000010) == 0x00000010); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
public com.google.protobuf.ByteString getLocalEphemeralKeyPrivate() { public com.google.protobuf.ByteString getLocalRatchetKeyPrivate() {
return localEphemeralKeyPrivate_; return localRatchetKeyPrivate_;
} }
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
public Builder setLocalEphemeralKeyPrivate(com.google.protobuf.ByteString value) { public Builder setLocalRatchetKeyPrivate(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
bitField0_ |= 0x00000010; bitField0_ |= 0x00000010;
localEphemeralKeyPrivate_ = value; localRatchetKeyPrivate_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /**
* <code>optional bytes localEphemeralKeyPrivate = 5;</code> * <code>optional bytes localRatchetKeyPrivate = 5;</code>
*/ */
public Builder clearLocalEphemeralKeyPrivate() { public Builder clearLocalRatchetKeyPrivate() {
bitField0_ = (bitField0_ & ~0x00000010); bitField0_ = (bitField0_ & ~0x00000010);
localEphemeralKeyPrivate_ = getDefaultInstance().getLocalEphemeralKeyPrivate(); localRatchetKeyPrivate_ = getDefaultInstance().getLocalRatchetKeyPrivate();
onChanged(); onChanged();
return this; return this;
} }
@ -8333,7 +8333,7 @@ public final class StorageProtos {
static { static {
java.lang.String[] descriptorData = { java.lang.String[] descriptorData = {
"\n\032LocalStorageProtocol.proto\022\ntextsecure" + "\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" + "\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(" + "moteIdentityPublic\030\003 \001(\014\022\017\n\007rootKey\030\004 \001(" +
"\014\022\027\n\017previousCounter\030\005 \001(\r\0227\n\013senderChai" + "\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" + "gPreKey\022\034\n\024remoteRegistrationId\030\n \001(\r\022\033\n" +
"\023localRegistrationId\030\013 \001(\r\022\024\n\014needsRefre" + "\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" + "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" + "cation\030\016 \001(\014\032\255\002\n\005Chain\022\030\n\020senderRatchetK" +
"l\030\001 \001(\014\022\036\n\026senderEphemeralPrivate\030\002 \001(\014\022" + "ey\030\001 \001(\014\022\037\n\027senderRatchetKeyPrivate\030\002 \001(" +
"=\n\010chainKey\030\003 \001(\0132+.textsecure.SessionSt" + "\014\022=\n\010chainKey\030\003 \001(\0132+.textsecure.Session" +
"ructure.Chain.ChainKey\022B\n\013messageKeys\030\004 " + "Structure.Chain.ChainKey\022B\n\013messageKeys\030" +
"\003(\0132-.textsecure.SessionStructure.Chain." + "\004 \003(\0132-.textsecure.SessionStructure.Chai" +
"MessageKey\032&\n\010ChainKey\022\r\n\005index\030\001 \001(\r\022\013\n", "n.MessageKey\032&\n\010ChainKey\022\r\n\005index\030\001 \001(\r\022",
"\003key\030\002 \001(\014\032>\n\nMessageKey\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(" +
"\021\n\tcipherKey\030\002 \001(\014\022\016\n\006macKey\030\003 \001(\014\032\321\001\n\022P" + "\r\022\021\n\tcipherKey\030\002 \001(\014\022\016\n\006macKey\030\003 \001(\014\032\315\001\n" +
"endingKeyExchange\022\020\n\010sequence\030\001 \001(\r\022\024\n\014l" + "\022PendingKeyExchange\022\020\n\010sequence\030\001 \001(\r\022\024\n" +
"ocalBaseKey\030\002 \001(\014\022\033\n\023localBaseKeyPrivate" + "\014localBaseKey\030\002 \001(\014\022\033\n\023localBaseKeyPriva" +
"\030\003 \001(\014\022\031\n\021localEphemeralKey\030\004 \001(\014\022 \n\030loc" + "te\030\003 \001(\014\022\027\n\017localRatchetKey\030\004 \001(\014\022\036\n\026loc" +
"alEphemeralKeyPrivate\030\005 \001(\014\022\030\n\020localIden" + "alRatchetKeyPrivate\030\005 \001(\014\022\030\n\020localIdenti" +
"tityKey\030\007 \001(\014\022\037\n\027localIdentityKeyPrivate" + "tyKey\030\007 \001(\014\022\037\n\027localIdentityKeyPrivate\030\010" +
"\030\010 \001(\014\032J\n\rPendingPreKey\022\020\n\010preKeyId\030\001 \001(" + " \001(\014\032J\n\rPendingPreKey\022\020\n\010preKeyId\030\001 \001(\r\022" +
"\r\022\026\n\016signedPreKeyId\030\003 \001(\005\022\017\n\007baseKey\030\002 \001" + "\026\n\016signedPreKeyId\030\003 \001(\005\022\017\n\007baseKey\030\002 \001(\014" +
"(\014\"\177\n\017RecordStructure\0224\n\016currentSession\030", "\"\177\n\017RecordStructure\0224\n\016currentSession\030\001 ",
"\001 \001(\0132\034.textsecure.SessionStructure\0226\n\020p" + "\001(\0132\034.textsecure.SessionStructure\0226\n\020pre" +
"reviousSessions\030\002 \003(\0132\034.textsecure.Sessi" + "viousSessions\030\002 \003(\0132\034.textsecure.Session" +
"onStructure\"J\n\025PreKeyRecordStructure\022\n\n\002" + "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" + "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" + "y\030\003 \001(\014\022\021\n\tsignature\030\004 \001(\014\022\021\n\ttimestamp\030" +
"\n\002id\030\001 \001(\r\022\021\n\tpublicKey\030\002 \001(\014\022\022\n\nprivate" + "\005 \001(\006\"A\n\030IdentityKeyPairStructure\022\021\n\tpub" +
"Key\030\003 \001(\014\022\021\n\tsignature\030\004 \001(\014\022\021\n\ttimestam" + "licKey\030\001 \001(\014\022\022\n\nprivateKey\030\002 \001(\014B4\n#org." +
"p\030\005 \001(\006\"A\n\030IdentityKeyPairStructure\022\021\n\tp" + "whispersystems.libaxolotl.stateB\rStorage",
"ublicKey\030\001 \001(\014\022\022\n\nprivateKey\030\002 \001(\014B4\n#or" + "Protos"
"g.whispersystems.libaxolotl.stateB\rStora",
"geProtos"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -8390,7 +8390,7 @@ public final class StorageProtos {
internal_static_textsecure_SessionStructure_Chain_fieldAccessorTable = new internal_static_textsecure_SessionStructure_Chain_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_SessionStructure_Chain_descriptor, 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_ChainKey_descriptor =
internal_static_textsecure_SessionStructure_Chain_descriptor.getNestedTypes().get(0); internal_static_textsecure_SessionStructure_Chain_descriptor.getNestedTypes().get(0);
internal_static_textsecure_SessionStructure_Chain_ChainKey_fieldAccessorTable = new internal_static_textsecure_SessionStructure_Chain_ChainKey_fieldAccessorTable = new
@ -8408,7 +8408,7 @@ public final class StorageProtos {
internal_static_textsecure_SessionStructure_PendingKeyExchange_fieldAccessorTable = new internal_static_textsecure_SessionStructure_PendingKeyExchange_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor, 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_PendingPreKey_descriptor =
internal_static_textsecure_SessionStructure_descriptor.getNestedTypes().get(2); internal_static_textsecure_SessionStructure_descriptor.getNestedTypes().get(2);
internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable = new internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable = new