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