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