aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/androidTest/java/org/whispersystems/test/InMemoryAxolotlStore.java115
-rw-r--r--src/androidTest/java/org/whispersystems/test/InMemoryIdentityKeyStore.java53
-rw-r--r--src/androidTest/java/org/whispersystems/test/InMemoryPreKeyStore.java42
-rw-r--r--src/androidTest/java/org/whispersystems/test/InMemorySessionStore.java68
-rw-r--r--src/androidTest/java/org/whispersystems/test/InMemorySignedPreKeyStore.java59
-rw-r--r--src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java601
-rw-r--r--src/androidTest/java/org/whispersystems/test/SessionCipherTest.java206
-rw-r--r--src/androidTest/java/org/whispersystems/test/SimultaneousInitiateTests.java501
-rw-r--r--src/androidTest/java/org/whispersystems/test/ecc/Curve25519Test.java154
-rw-r--r--src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java151
-rw-r--r--src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java33
-rw-r--r--src/androidTest/java/org/whispersystems/test/kdf/HKDFTest.java139
-rw-r--r--src/androidTest/java/org/whispersystems/test/ratchet/ChainKeyTest.java59
-rw-r--r--src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java236
-rw-r--r--src/androidTest/java/org/whispersystems/test/ratchet/RootKeyTest.java84
-rw-r--r--src/main/AndroidManifest.xml7
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java7
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/IdentityKey.java66
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java66
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java34
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java27
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java28
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java40
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java23
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java7
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/NoSessionException.java11
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java411
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/SessionCipher.java469
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java4
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java4
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java78
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java98
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java41
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java66
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java37
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java23
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java27
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java146
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java38
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java49
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java38
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java64
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java144
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java6
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java61
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java26
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java93
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java8
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java8
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java35
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java153
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java147
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java56
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java121
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java172
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java3532
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java109
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java109
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java75
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java51
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java179
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java54
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java108
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java6
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java57
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java96
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java51
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java42
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java117
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/SessionState.java509
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java68
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java61
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java47
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java11779
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java248
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/Hex.java77
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java143
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/Medium.java5
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/Pair.java51
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java87
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java61
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java232
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java447
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java88
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java36
85 files changed, 23965 insertions, 0 deletions
diff --git a/src/androidTest/java/org/whispersystems/test/InMemoryAxolotlStore.java b/src/androidTest/java/org/whispersystems/test/InMemoryAxolotlStore.java
new file mode 100644
index 00000000..4e001865
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/InMemoryAxolotlStore.java
@@ -0,0 +1,115 @@
+package org.whispersystems.test;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+import org.whispersystems.libaxolotl.state.AxolotlStore;
+import org.whispersystems.libaxolotl.state.PreKeyRecord;
+import org.whispersystems.libaxolotl.state.SessionRecord;
+import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
+
+import java.util.List;
+
+public class InMemoryAxolotlStore implements AxolotlStore {
+
+ private final InMemoryIdentityKeyStore identityKeyStore = new InMemoryIdentityKeyStore();
+ private final InMemoryPreKeyStore preKeyStore = new InMemoryPreKeyStore();
+ private final InMemorySessionStore sessionStore = new InMemorySessionStore();
+ private final InMemorySignedPreKeyStore signedPreKeyStore = new InMemorySignedPreKeyStore();
+
+
+ @Override
+ public IdentityKeyPair getIdentityKeyPair() {
+ return identityKeyStore.getIdentityKeyPair();
+ }
+
+ @Override
+ public int getLocalRegistrationId() {
+ return identityKeyStore.getLocalRegistrationId();
+ }
+
+ @Override
+ public void saveIdentity(long recipientId, IdentityKey identityKey) {
+ identityKeyStore.saveIdentity(recipientId, identityKey);
+ }
+
+ @Override
+ public boolean isTrustedIdentity(long recipientId, IdentityKey identityKey) {
+ return identityKeyStore.isTrustedIdentity(recipientId, identityKey);
+ }
+
+ @Override
+ public PreKeyRecord loadPreKey(int preKeyId) throws InvalidKeyIdException {
+ return preKeyStore.loadPreKey(preKeyId);
+ }
+
+ @Override
+ public void storePreKey(int preKeyId, PreKeyRecord record) {
+ preKeyStore.storePreKey(preKeyId, record);
+ }
+
+ @Override
+ public boolean containsPreKey(int preKeyId) {
+ return preKeyStore.containsPreKey(preKeyId);
+ }
+
+ @Override
+ public void removePreKey(int preKeyId) {
+ preKeyStore.removePreKey(preKeyId);
+ }
+
+ @Override
+ public SessionRecord loadSession(long recipientId, int deviceId) {
+ return sessionStore.loadSession(recipientId, deviceId);
+ }
+
+ @Override
+ public List<Integer> getSubDeviceSessions(long recipientId) {
+ return sessionStore.getSubDeviceSessions(recipientId);
+ }
+
+ @Override
+ public void storeSession(long recipientId, int deviceId, SessionRecord record) {
+ sessionStore.storeSession(recipientId, deviceId, record);
+ }
+
+ @Override
+ public boolean containsSession(long recipientId, int deviceId) {
+ return sessionStore.containsSession(recipientId, deviceId);
+ }
+
+ @Override
+ public void deleteSession(long recipientId, int deviceId) {
+ sessionStore.deleteSession(recipientId, deviceId);
+ }
+
+ @Override
+ public void deleteAllSessions(long recipientId) {
+ sessionStore.deleteAllSessions(recipientId);
+ }
+
+ @Override
+ public SignedPreKeyRecord loadSignedPreKey(int signedPreKeyId) throws InvalidKeyIdException {
+ return signedPreKeyStore.loadSignedPreKey(signedPreKeyId);
+ }
+
+ @Override
+ public List<SignedPreKeyRecord> loadSignedPreKeys() {
+ return signedPreKeyStore.loadSignedPreKeys();
+ }
+
+ @Override
+ public void storeSignedPreKey(int signedPreKeyId, SignedPreKeyRecord record) {
+ signedPreKeyStore.storeSignedPreKey(signedPreKeyId, record);
+ }
+
+ @Override
+ public boolean containsSignedPreKey(int signedPreKeyId) {
+ return signedPreKeyStore.containsSignedPreKey(signedPreKeyId);
+ }
+
+ @Override
+ public void removeSignedPreKey(int signedPreKeyId) {
+ signedPreKeyStore.removeSignedPreKey(signedPreKeyId);
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/InMemoryIdentityKeyStore.java b/src/androidTest/java/org/whispersystems/test/InMemoryIdentityKeyStore.java
new file mode 100644
index 00000000..8a2e1d8f
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/InMemoryIdentityKeyStore.java
@@ -0,0 +1,53 @@
+package org.whispersystems.test;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.state.IdentityKeyStore;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+public class InMemoryIdentityKeyStore implements IdentityKeyStore {
+
+ private final Map<Long, IdentityKey> trustedKeys = new HashMap<>();
+
+ private final IdentityKeyPair identityKeyPair;
+ private final int localRegistrationId;
+
+ public InMemoryIdentityKeyStore() {
+ try {
+ ECKeyPair identityKeyPairKeys = Curve.generateKeyPair();
+
+ this.identityKeyPair = new IdentityKeyPair(new IdentityKey(identityKeyPairKeys.getPublicKey()),
+ identityKeyPairKeys.getPrivateKey());
+ this.localRegistrationId = SecureRandom.getInstance("SHA1PRNG").nextInt(16380) + 1;
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public IdentityKeyPair getIdentityKeyPair() {
+ return identityKeyPair;
+ }
+
+ @Override
+ public int getLocalRegistrationId() {
+ return localRegistrationId;
+ }
+
+ @Override
+ public void saveIdentity(long recipientId, IdentityKey identityKey) {
+ trustedKeys.put(recipientId, identityKey);
+ }
+
+ @Override
+ public boolean isTrustedIdentity(long recipientId, IdentityKey identityKey) {
+ IdentityKey trusted = trustedKeys.get(recipientId);
+ return (trusted == null || trusted.equals(identityKey));
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/InMemoryPreKeyStore.java b/src/androidTest/java/org/whispersystems/test/InMemoryPreKeyStore.java
new file mode 100644
index 00000000..7c3cea08
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/InMemoryPreKeyStore.java
@@ -0,0 +1,42 @@
+package org.whispersystems.test;
+
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+import org.whispersystems.libaxolotl.state.PreKeyRecord;
+import org.whispersystems.libaxolotl.state.PreKeyStore;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class InMemoryPreKeyStore implements PreKeyStore {
+
+ private final Map<Integer, byte[]> store = new HashMap<>();
+
+ @Override
+ public PreKeyRecord loadPreKey(int preKeyId) throws InvalidKeyIdException {
+ try {
+ if (!store.containsKey(preKeyId)) {
+ throw new InvalidKeyIdException("No such prekeyrecord!");
+ }
+
+ return new PreKeyRecord(store.get(preKeyId));
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public void storePreKey(int preKeyId, PreKeyRecord record) {
+ store.put(preKeyId, record.serialize());
+ }
+
+ @Override
+ public boolean containsPreKey(int preKeyId) {
+ return store.containsKey(preKeyId);
+ }
+
+ @Override
+ public void removePreKey(int preKeyId) {
+ store.remove(preKeyId);
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/InMemorySessionStore.java b/src/androidTest/java/org/whispersystems/test/InMemorySessionStore.java
new file mode 100644
index 00000000..0d148ab0
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/InMemorySessionStore.java
@@ -0,0 +1,68 @@
+package org.whispersystems.test;
+
+import org.whispersystems.libaxolotl.state.SessionRecord;
+import org.whispersystems.libaxolotl.state.SessionStore;
+import org.whispersystems.libaxolotl.util.Pair;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class InMemorySessionStore implements SessionStore {
+
+ private Map<Pair<Long, Integer>, byte[]> sessions = new HashMap<>();
+
+ public InMemorySessionStore() {}
+
+ @Override
+ public synchronized SessionRecord loadSession(long recipientId, int deviceId) {
+ try {
+ if (containsSession(recipientId, deviceId)) {
+ return new SessionRecord(sessions.get(new Pair<>(recipientId, deviceId)));
+ } else {
+ return new SessionRecord();
+ }
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public synchronized List<Integer> getSubDeviceSessions(long recipientId) {
+ List<Integer> deviceIds = new LinkedList<>();
+
+ for (Pair<Long, Integer> key : sessions.keySet()) {
+ if (key.first() == recipientId) {
+ deviceIds.add(key.second());
+ }
+ }
+
+ return deviceIds;
+ }
+
+ @Override
+ public synchronized void storeSession(long recipientId, int deviceId, SessionRecord record) {
+ sessions.put(new Pair<>(recipientId, deviceId), record.serialize());
+ }
+
+ @Override
+ public synchronized boolean containsSession(long recipientId, int deviceId) {
+ return sessions.containsKey(new Pair<>(recipientId, deviceId));
+ }
+
+ @Override
+ public synchronized void deleteSession(long recipientId, int deviceId) {
+ sessions.remove(new Pair<>(recipientId, deviceId));
+ }
+
+ @Override
+ public synchronized void deleteAllSessions(long recipientId) {
+ for (Pair<Long, Integer> key : sessions.keySet()) {
+ if (key.first() == recipientId) {
+ sessions.remove(key);
+ }
+ }
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/InMemorySignedPreKeyStore.java b/src/androidTest/java/org/whispersystems/test/InMemorySignedPreKeyStore.java
new file mode 100644
index 00000000..7449eece
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/InMemorySignedPreKeyStore.java
@@ -0,0 +1,59 @@
+package org.whispersystems.test;
+
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
+import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class InMemorySignedPreKeyStore implements SignedPreKeyStore {
+
+ private final Map<Integer, byte[]> store = new HashMap<>();
+
+ @Override
+ public SignedPreKeyRecord loadSignedPreKey(int signedPreKeyId) throws InvalidKeyIdException {
+ try {
+ if (!store.containsKey(signedPreKeyId)) {
+ throw new InvalidKeyIdException("No such signedprekeyrecord! " + signedPreKeyId);
+ }
+
+ return new SignedPreKeyRecord(store.get(signedPreKeyId));
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public List<SignedPreKeyRecord> loadSignedPreKeys() {
+ try {
+ List<SignedPreKeyRecord> results = new LinkedList<>();
+
+ for (byte[] serialized : store.values()) {
+ results.add(new SignedPreKeyRecord(serialized));
+ }
+
+ return results;
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public void storeSignedPreKey(int signedPreKeyId, SignedPreKeyRecord record) {
+ store.put(signedPreKeyId, record.serialize());
+ }
+
+ @Override
+ public boolean containsSignedPreKey(int signedPreKeyId) {
+ return store.containsKey(signedPreKeyId);
+ }
+
+ @Override
+ public void removeSignedPreKey(int signedPreKeyId) {
+ store.remove(signedPreKeyId);
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java b/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java
new file mode 100644
index 00000000..802f401d
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java
@@ -0,0 +1,601 @@
+package org.whispersystems.test;
+
+import android.test.AndroidTestCase;
+
+import org.whispersystems.libaxolotl.DuplicateMessageException;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.InvalidVersionException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.NoSessionException;
+import org.whispersystems.libaxolotl.SessionBuilder;
+import org.whispersystems.libaxolotl.SessionCipher;
+import org.whispersystems.libaxolotl.StaleKeyExchangeException;
+import org.whispersystems.libaxolotl.UntrustedIdentityException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
+import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage;
+import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
+import org.whispersystems.libaxolotl.protocol.WhisperMessage;
+import org.whispersystems.libaxolotl.state.AxolotlStore;
+import org.whispersystems.libaxolotl.state.IdentityKeyStore;
+import org.whispersystems.libaxolotl.state.PreKeyBundle;
+import org.whispersystems.libaxolotl.state.PreKeyRecord;
+import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
+import org.whispersystems.libaxolotl.util.Pair;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class SessionBuilderTest extends AndroidTestCase {
+
+ private static final long ALICE_RECIPIENT_ID = 5L;
+ private static final long BOB_RECIPIENT_ID = 2L;
+
+ public void testBasicPreKeyV2()
+ throws InvalidKeyException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, UntrustedIdentityException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 31337, bobPreKeyPair.getPublicKey(),
+ 0, null, null,
+ bobStore.getIdentityKeyPair().getPublicKey());
+
+ aliceSessionBuilder.process(bobPreKey);
+
+ assertTrue(aliceStore.containsSession(BOB_RECIPIENT_ID, 1));
+ assertTrue(aliceStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 2);
+
+ String originalMessage = "L'homme est condamné à être libre";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+ CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessage.serialize());
+ bobStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+ byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
+
+ assertTrue(bobStore.containsSession(ALICE_RECIPIENT_ID, 1));
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 2);
+ assertTrue(originalMessage.equals(new String(plaintext)));
+
+ CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
+ assertTrue(bobOutgoingMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt((WhisperMessage)bobOutgoingMessage);
+ assertTrue(new String(alicePlaintext).equals(originalMessage));
+
+ runInteraction(aliceStore, bobStore);
+
+ aliceStore = new InMemoryAxolotlStore();
+ aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+ aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ bobPreKeyPair = Curve.generateKeyPair();
+ bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(),
+ 1, 31338, bobPreKeyPair.getPublicKey(),
+ 0, null, null, bobStore.getIdentityKeyPair().getPublicKey());
+
+ bobStore.storePreKey(31338, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+ aliceSessionBuilder.process(bobPreKey);
+
+ outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ try {
+ bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize()));
+ throw new AssertionError("shouldn't be trusted!");
+ } catch (UntrustedIdentityException uie) {
+ bobStore.saveIdentity(ALICE_RECIPIENT_ID, new PreKeyWhisperMessage(outgoingMessage.serialize()).getIdentityKey());
+ }
+
+ plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize()));
+
+ assertTrue(new String(plaintext).equals(originalMessage));
+
+ bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 31337, Curve.generateKeyPair().getPublicKey(),
+ 0, null, null,
+ aliceStore.getIdentityKeyPair().getPublicKey());
+
+ try {
+ aliceSessionBuilder.process(bobPreKey);
+ throw new AssertionError("shoulnd't be trusted!");
+ } catch (UntrustedIdentityException uie) {
+ // good
+ }
+ }
+
+ public void testBasicPreKeyV3()
+ throws InvalidKeyException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, UntrustedIdentityException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ final AxolotlStore bobStore = new InMemoryAxolotlStore();
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
+ byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKeyPair.getPublicKey().serialize());
+
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 31337, bobPreKeyPair.getPublicKey(),
+ 22, bobSignedPreKeyPair.getPublicKey(),
+ bobSignedPreKeySignature,
+ bobStore.getIdentityKeyPair().getPublicKey());
+
+ aliceSessionBuilder.process(bobPreKey);
+
+ assertTrue(aliceStore.containsSession(BOB_RECIPIENT_ID, 1));
+ assertTrue(aliceStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ final String originalMessage = "L'homme est condamné à être libre";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+ CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessage.serialize());
+ bobStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+ bobStore.storeSignedPreKey(22, new SignedPreKeyRecord(22, System.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature));
+
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+ byte[] plaintext = bobSessionCipher.decrypt(incomingMessage, new SessionCipher.DecryptionCallback() {
+ @Override
+ public void handlePlaintext(byte[] plaintext) {
+ assertTrue(originalMessage.equals(new String(plaintext)));
+ assertFalse(bobStore.containsSession(ALICE_RECIPIENT_ID, 1));
+ }
+ });
+
+ assertTrue(bobStore.containsSession(ALICE_RECIPIENT_ID, 1));
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getAliceBaseKey() != null);
+ assertTrue(originalMessage.equals(new String(plaintext)));
+
+ CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
+ assertTrue(bobOutgoingMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobOutgoingMessage.serialize()));
+ assertTrue(new String(alicePlaintext).equals(originalMessage));
+
+ runInteraction(aliceStore, bobStore);
+
+ aliceStore = new InMemoryAxolotlStore();
+ aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+ aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ bobPreKeyPair = Curve.generateKeyPair();
+ bobSignedPreKeyPair = Curve.generateKeyPair();
+ bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(), bobSignedPreKeyPair.getPublicKey().serialize());
+ bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(),
+ 1, 31338, bobPreKeyPair.getPublicKey(),
+ 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
+ bobStore.getIdentityKeyPair().getPublicKey());
+
+ bobStore.storePreKey(31338, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+ bobStore.storeSignedPreKey(23, new SignedPreKeyRecord(23, System.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature));
+ aliceSessionBuilder.process(bobPreKey);
+
+ outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ try {
+ plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize()));
+ throw new AssertionError("shouldn't be trusted!");
+ } catch (UntrustedIdentityException uie) {
+ bobStore.saveIdentity(ALICE_RECIPIENT_ID, new PreKeyWhisperMessage(outgoingMessage.serialize()).getIdentityKey());
+ }
+
+ plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize()));
+ assertTrue(new String(plaintext).equals(originalMessage));
+
+ bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 31337, Curve.generateKeyPair().getPublicKey(),
+ 23, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
+ aliceStore.getIdentityKeyPair().getPublicKey());
+
+ try {
+ aliceSessionBuilder.process(bobPreKey);
+ throw new AssertionError("shoulnd't be trusted!");
+ } catch (UntrustedIdentityException uie) {
+ // good
+ }
+ }
+
+ public void testBadSignedPreKeySignature() throws InvalidKeyException, UntrustedIdentityException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
+
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
+ byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKeyPair.getPublicKey().serialize());
+
+
+ for (int i=0;i<bobSignedPreKeySignature.length * 8;i++) {
+ byte[] modifiedSignature = new byte[bobSignedPreKeySignature.length];
+ System.arraycopy(bobSignedPreKeySignature, 0, modifiedSignature, 0, modifiedSignature.length);
+
+ modifiedSignature[i/8] ^= (0x01 << (i % 8));
+
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
+ 31337, bobPreKeyPair.getPublicKey(),
+ 22, bobSignedPreKeyPair.getPublicKey(), modifiedSignature,
+ bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
+
+ try {
+ aliceSessionBuilder.process(bobPreKey);
+ throw new AssertionError("Accepted modified device key signature!");
+ } catch (InvalidKeyException ike) {
+ // good
+ }
+ }
+
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
+ 31337, bobPreKeyPair.getPublicKey(),
+ 22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
+ bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
+
+ aliceSessionBuilder.process(bobPreKey);
+ }
+
+ public void testRepeatBundleMessageV2() throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
+ byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKeyPair.getPublicKey().serialize());
+
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 31337, bobPreKeyPair.getPublicKey(),
+ 0, null, null,
+ bobStore.getIdentityKeyPair().getPublicKey());
+
+ bobStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+ bobStore.storeSignedPreKey(22, new SignedPreKeyRecord(22, System.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature));
+
+ aliceSessionBuilder.process(bobPreKey);
+
+ String originalMessage = "L'homme est condamné à être libre";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+ CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(originalMessage.getBytes());
+ CiphertextMessage outgoingMessageTwo = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(outgoingMessageOne.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessageOne.serialize());
+
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
+ assertTrue(originalMessage.equals(new String(plaintext)));
+
+ CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobOutgoingMessage.serialize()));
+ assertTrue(originalMessage.equals(new String(alicePlaintext)));
+
+ // The test
+
+ PreKeyWhisperMessage incomingMessageTwo = new PreKeyWhisperMessage(outgoingMessageTwo.serialize());
+
+ plaintext = bobSessionCipher.decrypt(incomingMessageTwo);
+ assertTrue(originalMessage.equals(new String(plaintext)));
+
+ bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
+ alicePlaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobOutgoingMessage.serialize()));
+ assertTrue(originalMessage.equals(new String(alicePlaintext)));
+
+ }
+
+ public void testRepeatBundleMessageV3() throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
+ byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKeyPair.getPublicKey().serialize());
+
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 31337, bobPreKeyPair.getPublicKey(),
+ 22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
+ bobStore.getIdentityKeyPair().getPublicKey());
+
+ bobStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+ bobStore.storeSignedPreKey(22, new SignedPreKeyRecord(22, System.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature));
+
+ aliceSessionBuilder.process(bobPreKey);
+
+ String originalMessage = "L'homme est condamné à être libre";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+ CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(originalMessage.getBytes());
+ CiphertextMessage outgoingMessageTwo = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(outgoingMessageOne.getType() == CiphertextMessage.PREKEY_TYPE);
+ assertTrue(outgoingMessageTwo.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessageOne.serialize());
+
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
+ assertTrue(originalMessage.equals(new String(plaintext)));
+
+ CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobOutgoingMessage.serialize()));
+ assertTrue(originalMessage.equals(new String(alicePlaintext)));
+
+ // The test
+
+ PreKeyWhisperMessage incomingMessageTwo = new PreKeyWhisperMessage(outgoingMessageTwo.serialize());
+
+ plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(incomingMessageTwo.serialize()));
+ assertTrue(originalMessage.equals(new String(plaintext)));
+
+ bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
+ alicePlaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobOutgoingMessage.serialize()));
+ assertTrue(originalMessage.equals(new String(alicePlaintext)));
+
+ }
+
+ public void testBadMessageBundle() throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException, InvalidMessageException, DuplicateMessageException, LegacyMessageException, InvalidKeyIdException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
+ byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKeyPair.getPublicKey().serialize());
+
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 31337, bobPreKeyPair.getPublicKey(),
+ 22, bobSignedPreKeyPair.getPublicKey(), bobSignedPreKeySignature,
+ bobStore.getIdentityKeyPair().getPublicKey());
+
+ bobStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+ bobStore.storeSignedPreKey(22, new SignedPreKeyRecord(22, System.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature));
+
+ aliceSessionBuilder.process(bobPreKey);
+
+ String originalMessage = "L'homme est condamné à être libre";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+ CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(outgoingMessageOne.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ byte[] goodMessage = outgoingMessageOne.serialize();
+ byte[] badMessage = new byte[goodMessage.length];
+ System.arraycopy(goodMessage, 0, badMessage, 0, badMessage.length);
+
+ badMessage[badMessage.length-10] ^= 0x01;
+
+ PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(badMessage);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ byte[] plaintext = new byte[0];
+
+ try {
+ plaintext = bobSessionCipher.decrypt(incomingMessage);
+ throw new AssertionError("Decrypt should have failed!");
+ } catch (InvalidMessageException e) {
+ // good.
+ }
+
+ assertTrue(bobStore.containsPreKey(31337));
+
+ plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(goodMessage));
+
+ assertTrue(originalMessage.equals(new String(plaintext)));
+ assertTrue(!bobStore.containsPreKey(31337));
+ }
+
+ public void testBasicKeyExchange() throws InvalidKeyException, LegacyMessageException, InvalidMessageException, DuplicateMessageException, UntrustedIdentityException, StaleKeyExchangeException, InvalidVersionException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ KeyExchangeMessage aliceKeyExchangeMessage = aliceSessionBuilder.process();
+ assertTrue(aliceKeyExchangeMessage != null);
+
+ byte[] aliceKeyExchangeMessageBytes = aliceKeyExchangeMessage.serialize();
+ KeyExchangeMessage bobKeyExchangeMessage = bobSessionBuilder.process(new KeyExchangeMessage(aliceKeyExchangeMessageBytes));
+
+ assertTrue(bobKeyExchangeMessage != null);
+
+ byte[] bobKeyExchangeMessageBytes = bobKeyExchangeMessage.serialize();
+ KeyExchangeMessage response = aliceSessionBuilder.process(new KeyExchangeMessage(bobKeyExchangeMessageBytes));
+
+ assertTrue(response == null);
+ assertTrue(aliceStore.containsSession(BOB_RECIPIENT_ID, 1));
+ assertTrue(bobStore.containsSession(ALICE_RECIPIENT_ID, 1));
+
+ runInteraction(aliceStore, bobStore);
+
+ aliceStore = new InMemoryAxolotlStore();
+ aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+ aliceKeyExchangeMessage = aliceSessionBuilder.process();
+
+ try {
+ bobKeyExchangeMessage = bobSessionBuilder.process(aliceKeyExchangeMessage);
+ throw new AssertionError("This identity shouldn't be trusted!");
+ } catch (UntrustedIdentityException uie) {
+ bobStore.saveIdentity(ALICE_RECIPIENT_ID, aliceKeyExchangeMessage.getIdentityKey());
+ bobKeyExchangeMessage = bobSessionBuilder.process(aliceKeyExchangeMessage);
+ }
+
+ assertTrue(aliceSessionBuilder.process(bobKeyExchangeMessage) == null);
+
+ runInteraction(aliceStore, bobStore);
+ }
+
+ public void testSimultaneousKeyExchange()
+ throws InvalidKeyException, DuplicateMessageException, LegacyMessageException, InvalidMessageException, UntrustedIdentityException, StaleKeyExchangeException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ KeyExchangeMessage aliceKeyExchange = aliceSessionBuilder.process();
+ KeyExchangeMessage bobKeyExchange = bobSessionBuilder.process();
+
+ assertTrue(aliceKeyExchange != null);
+ assertTrue(bobKeyExchange != null);
+
+ KeyExchangeMessage aliceResponse = aliceSessionBuilder.process(bobKeyExchange);
+ KeyExchangeMessage bobResponse = bobSessionBuilder.process(aliceKeyExchange);
+
+ assertTrue(aliceResponse != null);
+ assertTrue(bobResponse != null);
+
+ KeyExchangeMessage aliceAck = aliceSessionBuilder.process(bobResponse);
+ KeyExchangeMessage bobAck = bobSessionBuilder.process(aliceResponse);
+
+ assertTrue(aliceAck == null);
+ assertTrue(bobAck == null);
+
+ runInteraction(aliceStore, bobStore);
+ }
+
+ public void testOptionalOneTimePreKey() throws Exception {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPIENT_ID, 1);
+
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
+ byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKeyPair.getPublicKey().serialize());
+
+ PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
+ 0, null,
+ 22, bobSignedPreKeyPair.getPublicKey(),
+ bobSignedPreKeySignature,
+ bobStore.getIdentityKeyPair().getPublicKey());
+
+ aliceSessionBuilder.process(bobPreKey);
+
+ assertTrue(aliceStore.containsSession(BOB_RECIPIENT_ID, 1));
+ assertTrue(aliceStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ String originalMessage = "L'homme est condamné à être libre";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+ CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessage.serialize());
+ assertTrue(!incomingMessage.getPreKeyId().isPresent());
+
+ bobStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
+ bobStore.storeSignedPreKey(22, new SignedPreKeyRecord(22, System.currentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature));
+
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+ byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
+
+ assertTrue(bobStore.containsSession(ALICE_RECIPIENT_ID, 1));
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getAliceBaseKey() != null);
+ assertTrue(originalMessage.equals(new String(plaintext)));
+ }
+
+
+ private void runInteraction(AxolotlStore aliceStore, AxolotlStore bobStore)
+ throws DuplicateMessageException, LegacyMessageException, InvalidMessageException, NoSessionException
+ {
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPIENT_ID, 1);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ String originalMessage = "smert ze smert";
+ CiphertextMessage aliceMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(aliceMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] plaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceMessage.serialize()));
+ assertTrue(new String(plaintext).equals(originalMessage));
+
+ CiphertextMessage bobMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
+
+ assertTrue(bobMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ plaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobMessage.serialize()));
+ assertTrue(new String(plaintext).equals(originalMessage));
+
+ for (int i=0;i<10;i++) {
+ String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
+ "We mean that man first of all exists, encounters himself, " +
+ "surges up in the world--and defines himself aftward. " + i);
+ CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage.getBytes());
+
+ byte[] loopingPlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceLoopingMessage.serialize()));
+ assertTrue(new String(loopingPlaintext).equals(loopingMessage));
+ }
+
+ for (int i=0;i<10;i++) {
+ String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
+ "We mean that man first of all exists, encounters himself, " +
+ "surges up in the world--and defines himself aftward. " + i);
+ CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(loopingMessage.getBytes());
+
+ byte[] loopingPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobLoopingMessage.serialize()));
+ assertTrue(new String(loopingPlaintext).equals(loopingMessage));
+ }
+
+ Set<Pair<String, CiphertextMessage>> aliceOutOfOrderMessages = new HashSet<>();
+
+ for (int i=0;i<10;i++) {
+ String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
+ "We mean that man first of all exists, encounters himself, " +
+ "surges up in the world--and defines himself aftward. " + i);
+ CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage.getBytes());
+
+ aliceOutOfOrderMessages.add(new Pair<>(loopingMessage, aliceLoopingMessage));
+ }
+
+ for (int i=0;i<10;i++) {
+ String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
+ "We mean that man first of all exists, encounters himself, " +
+ "surges up in the world--and defines himself aftward. " + i);
+ CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage.getBytes());
+
+ byte[] loopingPlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceLoopingMessage.serialize()));
+ assertTrue(new String(loopingPlaintext).equals(loopingMessage));
+ }
+
+ for (int i=0;i<10;i++) {
+ String loopingMessage = ("You can only desire based on what you know: " + i);
+ CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(loopingMessage.getBytes());
+
+ byte[] loopingPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(bobLoopingMessage.serialize()));
+ assertTrue(new String(loopingPlaintext).equals(loopingMessage));
+ }
+
+ for (Pair<String, CiphertextMessage> aliceOutOfOrderMessage : aliceOutOfOrderMessages) {
+ byte[] outOfOrderPlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceOutOfOrderMessage.second().serialize()));
+ assertTrue(new String(outOfOrderPlaintext).equals(aliceOutOfOrderMessage.first()));
+ }
+ }
+
+
+}
diff --git a/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java b/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java
new file mode 100644
index 00000000..52b5fa89
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java
@@ -0,0 +1,206 @@
+package org.whispersystems.test;
+
+import android.test.AndroidTestCase;
+
+import org.whispersystems.libaxolotl.DuplicateMessageException;
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.NoSessionException;
+import org.whispersystems.libaxolotl.SessionCipher;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
+import org.whispersystems.libaxolotl.protocol.WhisperMessage;
+import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters;
+import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters;
+import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
+import org.whispersystems.libaxolotl.state.AxolotlStore;
+import org.whispersystems.libaxolotl.state.SessionRecord;
+import org.whispersystems.libaxolotl.state.SessionState;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+
+public class SessionCipherTest extends AndroidTestCase {
+
+ public void testBasicSessionV2()
+ throws InvalidKeyException, DuplicateMessageException,
+ LegacyMessageException, InvalidMessageException, NoSuchAlgorithmException, NoSessionException
+ {
+ SessionRecord aliceSessionRecord = new SessionRecord();
+ SessionRecord bobSessionRecord = new SessionRecord();
+
+ initializeSessionsV2(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState());
+ runInteraction(aliceSessionRecord, bobSessionRecord);
+ }
+
+ public void testBasicSessionV3()
+ throws InvalidKeyException, DuplicateMessageException,
+ LegacyMessageException, InvalidMessageException, NoSuchAlgorithmException, NoSessionException
+ {
+ SessionRecord aliceSessionRecord = new SessionRecord();
+ SessionRecord bobSessionRecord = new SessionRecord();
+
+ initializeSessionsV3(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState());
+ runInteraction(aliceSessionRecord, bobSessionRecord);
+ }
+
+ private void runInteraction(SessionRecord aliceSessionRecord, SessionRecord bobSessionRecord)
+ throws DuplicateMessageException, LegacyMessageException, InvalidMessageException, NoSuchAlgorithmException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ aliceStore.storeSession(2L, 1, aliceSessionRecord);
+ bobStore.storeSession(3L, 1, bobSessionRecord);
+
+ SessionCipher aliceCipher = new SessionCipher(aliceStore, 2L, 1);
+ SessionCipher bobCipher = new SessionCipher(bobStore, 3L, 1);
+
+ byte[] alicePlaintext = "This is a plaintext message.".getBytes();
+ CiphertextMessage message = aliceCipher.encrypt(alicePlaintext);
+ byte[] bobPlaintext = bobCipher.decrypt(new WhisperMessage(message.serialize()));
+
+ assertTrue(Arrays.equals(alicePlaintext, bobPlaintext));
+
+ byte[] bobReply = "This is a message from Bob.".getBytes();
+ CiphertextMessage reply = bobCipher.encrypt(bobReply);
+ byte[] receivedReply = aliceCipher.decrypt(new WhisperMessage(reply.serialize()));
+
+ assertTrue(Arrays.equals(bobReply, receivedReply));
+
+ List<CiphertextMessage> aliceCiphertextMessages = new ArrayList<>();
+ List<byte[]> alicePlaintextMessages = new ArrayList<>();
+
+ for (int i=0;i<50;i++) {
+ alicePlaintextMessages.add(("смерть за смерть " + i).getBytes());
+ aliceCiphertextMessages.add(aliceCipher.encrypt(("смерть за смерть " + i).getBytes()));
+ }
+
+ long seed = System.currentTimeMillis();
+
+ Collections.shuffle(aliceCiphertextMessages, new Random(seed));
+ Collections.shuffle(alicePlaintextMessages, new Random(seed));
+
+ for (int i=0;i<aliceCiphertextMessages.size() / 2;i++) {
+ byte[] receivedPlaintext = bobCipher.decrypt(new WhisperMessage(aliceCiphertextMessages.get(i).serialize()));
+ assertTrue(Arrays.equals(receivedPlaintext, alicePlaintextMessages.get(i)));
+ }
+
+ List<CiphertextMessage> bobCiphertextMessages = new ArrayList<>();
+ List<byte[]> bobPlaintextMessages = new ArrayList<>();
+
+ for (int i=0;i<20;i++) {
+ bobPlaintextMessages.add(("смерть за смерть " + i).getBytes());
+ bobCiphertextMessages.add(bobCipher.encrypt(("смерть за смерть " + i).getBytes()));
+ }
+
+ seed = System.currentTimeMillis();
+
+ Collections.shuffle(bobCiphertextMessages, new Random(seed));
+ Collections.shuffle(bobPlaintextMessages, new Random(seed));
+
+ for (int i=0;i<bobCiphertextMessages.size() / 2;i++) {
+ byte[] receivedPlaintext = aliceCipher.decrypt(new WhisperMessage(bobCiphertextMessages.get(i).serialize()));
+ assertTrue(Arrays.equals(receivedPlaintext, bobPlaintextMessages.get(i)));
+ }
+
+ for (int i=aliceCiphertextMessages.size()/2;i<aliceCiphertextMessages.size();i++) {
+ byte[] receivedPlaintext = bobCipher.decrypt(new WhisperMessage(aliceCiphertextMessages.get(i).serialize()));
+ assertTrue(Arrays.equals(receivedPlaintext, alicePlaintextMessages.get(i)));
+ }
+
+ for (int i=bobCiphertextMessages.size() / 2;i<bobCiphertextMessages.size();i++) {
+ byte[] receivedPlaintext = aliceCipher.decrypt(new WhisperMessage(bobCiphertextMessages.get(i).serialize()));
+ assertTrue(Arrays.equals(receivedPlaintext, bobPlaintextMessages.get(i)));
+ }
+ }
+
+
+ private void initializeSessionsV2(SessionState aliceSessionState, SessionState bobSessionState)
+ throws InvalidKeyException
+ {
+ ECKeyPair aliceIdentityKeyPair = Curve.generateKeyPair();
+ IdentityKeyPair aliceIdentityKey = new IdentityKeyPair(new IdentityKey(aliceIdentityKeyPair.getPublicKey()),
+ aliceIdentityKeyPair.getPrivateKey());
+ ECKeyPair aliceBaseKey = Curve.generateKeyPair();
+ ECKeyPair aliceEphemeralKey = Curve.generateKeyPair();
+
+ ECKeyPair bobIdentityKeyPair = Curve.generateKeyPair();
+ IdentityKeyPair bobIdentityKey = new IdentityKeyPair(new IdentityKey(bobIdentityKeyPair.getPublicKey()),
+ bobIdentityKeyPair.getPrivateKey());
+ ECKeyPair bobBaseKey = Curve.generateKeyPair();
+ ECKeyPair bobEphemeralKey = bobBaseKey;
+
+ AliceAxolotlParameters aliceParameters = AliceAxolotlParameters.newBuilder()
+ .setOurIdentityKey(aliceIdentityKey)
+ .setOurBaseKey(aliceBaseKey)
+ .setTheirIdentityKey(bobIdentityKey.getPublicKey())
+ .setTheirSignedPreKey(bobEphemeralKey.getPublicKey())
+ .setTheirRatchetKey(bobEphemeralKey.getPublicKey())
+ .setTheirOneTimePreKey(Optional.<ECPublicKey>absent())
+ .create();
+
+ BobAxolotlParameters bobParameters = BobAxolotlParameters.newBuilder()
+ .setOurIdentityKey(bobIdentityKey)
+ .setOurOneTimePreKey(Optional.<ECKeyPair>absent())
+ .setOurRatchetKey(bobEphemeralKey)
+ .setOurSignedPreKey(bobBaseKey)
+ .setTheirBaseKey(aliceBaseKey.getPublicKey())
+ .setTheirIdentityKey(aliceIdentityKey.getPublicKey())
+ .create();
+
+ RatchetingSession.initializeSession(aliceSessionState, 2, aliceParameters);
+ RatchetingSession.initializeSession(bobSessionState, 2, bobParameters);
+ }
+
+ private void initializeSessionsV3(SessionState aliceSessionState, SessionState bobSessionState)
+ throws InvalidKeyException
+ {
+ ECKeyPair aliceIdentityKeyPair = Curve.generateKeyPair();
+ IdentityKeyPair aliceIdentityKey = new IdentityKeyPair(new IdentityKey(aliceIdentityKeyPair.getPublicKey()),
+ aliceIdentityKeyPair.getPrivateKey());
+ ECKeyPair aliceBaseKey = Curve.generateKeyPair();
+ ECKeyPair aliceEphemeralKey = Curve.generateKeyPair();
+
+ ECKeyPair alicePreKey = aliceBaseKey;
+
+ ECKeyPair bobIdentityKeyPair = Curve.generateKeyPair();
+ IdentityKeyPair bobIdentityKey = new IdentityKeyPair(new IdentityKey(bobIdentityKeyPair.getPublicKey()),
+ bobIdentityKeyPair.getPrivateKey());
+ ECKeyPair bobBaseKey = Curve.generateKeyPair();
+ ECKeyPair bobEphemeralKey = bobBaseKey;
+
+ ECKeyPair bobPreKey = Curve.generateKeyPair();
+
+ AliceAxolotlParameters aliceParameters = AliceAxolotlParameters.newBuilder()
+ .setOurBaseKey(aliceBaseKey)
+ .setOurIdentityKey(aliceIdentityKey)
+ .setTheirOneTimePreKey(Optional.<ECPublicKey>absent())
+ .setTheirRatchetKey(bobEphemeralKey.getPublicKey())
+ .setTheirSignedPreKey(bobBaseKey.getPublicKey())
+ .setTheirIdentityKey(bobIdentityKey.getPublicKey())
+ .create();
+
+ BobAxolotlParameters bobParameters = BobAxolotlParameters.newBuilder()
+ .setOurRatchetKey(bobEphemeralKey)
+ .setOurSignedPreKey(bobBaseKey)
+ .setOurOneTimePreKey(Optional.<ECKeyPair>absent())
+ .setOurIdentityKey(bobIdentityKey)
+ .setTheirIdentityKey(aliceIdentityKey.getPublicKey())
+ .setTheirBaseKey(aliceBaseKey.getPublicKey())
+ .create();
+
+ RatchetingSession.initializeSession(aliceSessionState, 3, aliceParameters);
+ RatchetingSession.initializeSession(bobSessionState, 3, bobParameters);
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/SimultaneousInitiateTests.java b/src/androidTest/java/org/whispersystems/test/SimultaneousInitiateTests.java
new file mode 100644
index 00000000..dffde57c
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/SimultaneousInitiateTests.java
@@ -0,0 +1,501 @@
+package org.whispersystems.test;
+
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import org.whispersystems.libaxolotl.DuplicateMessageException;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.InvalidVersionException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.NoSessionException;
+import org.whispersystems.libaxolotl.SessionBuilder;
+import org.whispersystems.libaxolotl.SessionCipher;
+import org.whispersystems.libaxolotl.UntrustedIdentityException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
+import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
+import org.whispersystems.libaxolotl.protocol.WhisperMessage;
+import org.whispersystems.libaxolotl.state.AxolotlStore;
+import org.whispersystems.libaxolotl.state.PreKeyBundle;
+import org.whispersystems.libaxolotl.state.PreKeyRecord;
+import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
+import org.whispersystems.libaxolotl.util.Medium;
+
+import java.util.Arrays;
+import java.util.Random;
+
+public class SimultaneousInitiateTests extends AndroidTestCase {
+
+ private static final long BOB_RECIPENT_ID = 12345;
+ private static final long ALICE_RECIPIENT_ID = 6789;
+
+ private static final ECKeyPair aliceSignedPreKey = Curve.generateKeyPair();
+ private static final ECKeyPair bobSignedPreKey = Curve.generateKeyPair();
+
+ private static final int aliceSignedPreKeyId = new Random().nextInt(Medium.MAX_VALUE);
+ private static final int bobSignedPreKeyId = new Random().nextInt(Medium.MAX_VALUE);
+
+ public void testBasicSimultaneousInitiate()
+ throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
+ InvalidMessageException, DuplicateMessageException, LegacyMessageException,
+ InvalidKeyIdException, NoSessionException
+ {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ PreKeyBundle alicePreKeyBundle = createAlicePreKeyBundle(aliceStore);
+ PreKeyBundle bobPreKeyBundle = createBobPreKeyBundle(bobStore);
+
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ aliceSessionBuilder.process(bobPreKeyBundle);
+ bobSessionBuilder.process(alicePreKeyBundle);
+
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBob.getType() == CiphertextMessage.PREKEY_TYPE);
+ assertTrue(messageForAlice.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeyWhisperMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(messageForBob.serialize()));
+
+ assertTrue(new String(alicePlaintext).equals("sample message"));
+ assertTrue(new String(bobPlaintext).equals("hey there"));
+
+ assertTrue(aliceStore.loadSession(BOB_RECIPENT_ID, 1).getSessionState().getSessionVersion() == 3);
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage aliceResponse = aliceSessionCipher.encrypt("second message".getBytes());
+
+ assertTrue(aliceResponse.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] responsePlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceResponse.serialize()));
+
+ assertTrue(new String(responsePlaintext).equals("second message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage finalMessage = bobSessionCipher.encrypt("third message".getBytes());
+
+ assertTrue(finalMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] finalPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(finalMessage.serialize()));
+
+ assertTrue(new String(finalPlaintext).equals("third message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ public void testLostSimultaneousInitiate() throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException, InvalidMessageException, DuplicateMessageException, LegacyMessageException, InvalidKeyIdException, NoSessionException {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ PreKeyBundle alicePreKeyBundle = createAlicePreKeyBundle(aliceStore);
+ PreKeyBundle bobPreKeyBundle = createBobPreKeyBundle(bobStore);
+
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ aliceSessionBuilder.process(bobPreKeyBundle);
+ bobSessionBuilder.process(alicePreKeyBundle);
+
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBob.getType() == CiphertextMessage.PREKEY_TYPE);
+ assertTrue(messageForAlice.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(messageForBob.serialize()));
+
+ assertTrue(new String(bobPlaintext).equals("hey there"));
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ CiphertextMessage aliceResponse = aliceSessionCipher.encrypt("second message".getBytes());
+
+ assertTrue(aliceResponse.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ byte[] responsePlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(aliceResponse.serialize()));
+
+ assertTrue(new String(responsePlaintext).equals("second message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage finalMessage = bobSessionCipher.encrypt("third message".getBytes());
+
+ assertTrue(finalMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] finalPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(finalMessage.serialize()));
+
+ assertTrue(new String(finalPlaintext).equals("third message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ public void testSimultaneousInitiateLostMessage()
+ throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
+ InvalidMessageException, DuplicateMessageException, LegacyMessageException,
+ InvalidKeyIdException, NoSessionException
+ {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ PreKeyBundle alicePreKeyBundle = createAlicePreKeyBundle(aliceStore);
+ PreKeyBundle bobPreKeyBundle = createBobPreKeyBundle(bobStore);
+
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ aliceSessionBuilder.process(bobPreKeyBundle);
+ bobSessionBuilder.process(alicePreKeyBundle);
+
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBob.getType() == CiphertextMessage.PREKEY_TYPE);
+ assertTrue(messageForAlice.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeyWhisperMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(messageForBob.serialize()));
+
+ assertTrue(new String(alicePlaintext).equals("sample message"));
+ assertTrue(new String(bobPlaintext).equals("hey there"));
+
+ assertTrue(aliceStore.loadSession(BOB_RECIPENT_ID, 1).getSessionState().getSessionVersion() == 3);
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage aliceResponse = aliceSessionCipher.encrypt("second message".getBytes());
+
+ assertTrue(aliceResponse.getType() == CiphertextMessage.WHISPER_TYPE);
+
+// byte[] responsePlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceResponse.serialize()));
+//
+// assertTrue(new String(responsePlaintext).equals("second message"));
+// assertTrue(isSessionIdEqual(aliceStore, bobStore));
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage finalMessage = bobSessionCipher.encrypt("third message".getBytes());
+
+ assertTrue(finalMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] finalPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(finalMessage.serialize()));
+
+ assertTrue(new String(finalPlaintext).equals("third message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ public void testSimultaneousInitiateRepeatedMessages()
+ throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
+ InvalidMessageException, DuplicateMessageException, LegacyMessageException,
+ InvalidKeyIdException, NoSessionException
+ {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+ PreKeyBundle alicePreKeyBundle = createAlicePreKeyBundle(aliceStore);
+ PreKeyBundle bobPreKeyBundle = createBobPreKeyBundle(bobStore);
+
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ aliceSessionBuilder.process(bobPreKeyBundle);
+ bobSessionBuilder.process(alicePreKeyBundle);
+
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBob.getType() == CiphertextMessage.PREKEY_TYPE);
+ assertTrue(messageForAlice.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeyWhisperMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(messageForBob.serialize()));
+
+ assertTrue(new String(alicePlaintext).equals("sample message"));
+ assertTrue(new String(bobPlaintext).equals("hey there"));
+
+ assertTrue(aliceStore.loadSession(BOB_RECIPENT_ID, 1).getSessionState().getSessionVersion() == 3);
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ for (int i=0;i<50;i++) {
+ Log.w("SimultaneousInitiateTests", "Iteration: " + i);
+ CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBobRepeat.getType() == CiphertextMessage.WHISPER_TYPE);
+ assertTrue(messageForAliceRepeat.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintextRepeat = aliceSessionCipher.decrypt(new WhisperMessage(messageForAliceRepeat.serialize()));
+ byte[] bobPlaintextRepeat = bobSessionCipher.decrypt(new WhisperMessage(messageForBobRepeat.serialize()));
+
+ assertTrue(new String(alicePlaintextRepeat).equals("sample message"));
+ assertTrue(new String(bobPlaintextRepeat).equals("hey there"));
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ CiphertextMessage aliceResponse = aliceSessionCipher.encrypt("second message".getBytes());
+
+ assertTrue(aliceResponse.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] responsePlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceResponse.serialize()));
+
+ assertTrue(new String(responsePlaintext).equals("second message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage finalMessage = bobSessionCipher.encrypt("third message".getBytes());
+
+ assertTrue(finalMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] finalPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(finalMessage.serialize()));
+
+ assertTrue(new String(finalPlaintext).equals("third message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ public void testRepeatedSimultaneousInitiateRepeatedMessages()
+ throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
+ InvalidMessageException, DuplicateMessageException, LegacyMessageException,
+ InvalidKeyIdException, NoSessionException
+ {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ for (int i=0;i<15;i++) {
+ PreKeyBundle alicePreKeyBundle = createAlicePreKeyBundle(aliceStore);
+ PreKeyBundle bobPreKeyBundle = createBobPreKeyBundle(bobStore);
+
+ aliceSessionBuilder.process(bobPreKeyBundle);
+ bobSessionBuilder.process(alicePreKeyBundle);
+
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBob.getType() == CiphertextMessage.PREKEY_TYPE);
+ assertTrue(messageForAlice.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeyWhisperMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(messageForBob.serialize()));
+
+ assertTrue(new String(alicePlaintext).equals("sample message"));
+ assertTrue(new String(bobPlaintext).equals("hey there"));
+
+ assertTrue(aliceStore.loadSession(BOB_RECIPENT_ID, 1).getSessionState().getSessionVersion() == 3);
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ for (int i=0;i<50;i++) {
+ Log.w("SimultaneousInitiateTests", "Iteration: " + i);
+ CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBobRepeat.getType() == CiphertextMessage.WHISPER_TYPE);
+ assertTrue(messageForAliceRepeat.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintextRepeat = aliceSessionCipher.decrypt(new WhisperMessage(messageForAliceRepeat.serialize()));
+ byte[] bobPlaintextRepeat = bobSessionCipher.decrypt(new WhisperMessage(messageForBobRepeat.serialize()));
+
+ assertTrue(new String(alicePlaintextRepeat).equals("sample message"));
+ assertTrue(new String(bobPlaintextRepeat).equals("hey there"));
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ CiphertextMessage aliceResponse = aliceSessionCipher.encrypt("second message".getBytes());
+
+ assertTrue(aliceResponse.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] responsePlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceResponse.serialize()));
+
+ assertTrue(new String(responsePlaintext).equals("second message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage finalMessage = bobSessionCipher.encrypt("third message".getBytes());
+
+ assertTrue(finalMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] finalPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(finalMessage.serialize()));
+
+ assertTrue(new String(finalPlaintext).equals("third message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ public void testRepeatedSimultaneousInitiateLostMessageRepeatedMessages()
+ throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
+ InvalidMessageException, DuplicateMessageException, LegacyMessageException,
+ InvalidKeyIdException, NoSessionException
+ {
+ AxolotlStore aliceStore = new InMemoryAxolotlStore();
+ AxolotlStore bobStore = new InMemoryAxolotlStore();
+
+
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_RECIPIENT_ID, 1);
+
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_RECIPENT_ID, 1);
+ SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_RECIPIENT_ID, 1);
+
+// PreKeyBundle aliceLostPreKeyBundle = createAlicePreKeyBundle(aliceStore);
+ PreKeyBundle bobLostPreKeyBundle = createBobPreKeyBundle(bobStore);
+
+ aliceSessionBuilder.process(bobLostPreKeyBundle);
+// bobSessionBuilder.process(aliceLostPreKeyBundle);
+
+ CiphertextMessage lostMessageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+// CiphertextMessage lostMessageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
+
+ for (int i=0;i<15;i++) {
+ PreKeyBundle alicePreKeyBundle = createAlicePreKeyBundle(aliceStore);
+ PreKeyBundle bobPreKeyBundle = createBobPreKeyBundle(bobStore);
+
+ aliceSessionBuilder.process(bobPreKeyBundle);
+ bobSessionBuilder.process(alicePreKeyBundle);
+
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBob.getType() == CiphertextMessage.PREKEY_TYPE);
+ assertTrue(messageForAlice.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeyWhisperMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(messageForBob.serialize()));
+
+ assertTrue(new String(alicePlaintext).equals("sample message"));
+ assertTrue(new String(bobPlaintext).equals("hey there"));
+
+ assertTrue(aliceStore.loadSession(BOB_RECIPENT_ID, 1).getSessionState().getSessionVersion() == 3);
+ assertTrue(bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ for (int i=0;i<50;i++) {
+ Log.w("SimultaneousInitiateTests", "Iteration: " + i);
+ CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
+
+ assertTrue(messageForBobRepeat.getType() == CiphertextMessage.WHISPER_TYPE);
+ assertTrue(messageForAliceRepeat.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] alicePlaintextRepeat = aliceSessionCipher.decrypt(new WhisperMessage(messageForAliceRepeat.serialize()));
+ byte[] bobPlaintextRepeat = bobSessionCipher.decrypt(new WhisperMessage(messageForBobRepeat.serialize()));
+
+ assertTrue(new String(alicePlaintextRepeat).equals("sample message"));
+ assertTrue(new String(bobPlaintextRepeat).equals("hey there"));
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ CiphertextMessage aliceResponse = aliceSessionCipher.encrypt("second message".getBytes());
+
+ assertTrue(aliceResponse.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] responsePlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceResponse.serialize()));
+
+ assertTrue(new String(responsePlaintext).equals("second message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage finalMessage = bobSessionCipher.encrypt("third message".getBytes());
+
+ assertTrue(finalMessage.getType() == CiphertextMessage.WHISPER_TYPE);
+
+ byte[] finalPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(finalMessage.serialize()));
+
+ assertTrue(new String(finalPlaintext).equals("third message"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+
+ byte[] lostMessagePlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(lostMessageForBob.serialize()));
+ assertTrue(new String(lostMessagePlaintext).equals("hey there"));
+
+ assertFalse(isSessionIdEqual(aliceStore, bobStore));
+
+ CiphertextMessage blastFromThePast = bobSessionCipher.encrypt("unexpected!".getBytes());
+ byte[] blastFromThePastPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(blastFromThePast.serialize()));
+
+ assertTrue(new String(blastFromThePastPlaintext).equals("unexpected!"));
+ assertTrue(isSessionIdEqual(aliceStore, bobStore));
+ }
+
+ private boolean isSessionIdEqual(AxolotlStore aliceStore, AxolotlStore bobStore) {
+ return Arrays.equals(aliceStore.loadSession(BOB_RECIPENT_ID, 1).getSessionState().getAliceBaseKey(),
+ bobStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getAliceBaseKey());
+ }
+
+ private PreKeyBundle createAlicePreKeyBundle(AxolotlStore aliceStore) throws InvalidKeyException {
+ ECKeyPair aliceUnsignedPreKey = Curve.generateKeyPair();
+ int aliceUnsignedPreKeyId = new Random().nextInt(Medium.MAX_VALUE);
+ byte[] aliceSignature = Curve.calculateSignature(aliceStore.getIdentityKeyPair().getPrivateKey(),
+ aliceSignedPreKey.getPublicKey().serialize());
+
+ PreKeyBundle alicePreKeyBundle = new PreKeyBundle(1, 1,
+ aliceUnsignedPreKeyId, aliceUnsignedPreKey.getPublicKey(),
+ aliceSignedPreKeyId, aliceSignedPreKey.getPublicKey(),
+ aliceSignature, aliceStore.getIdentityKeyPair().getPublicKey());
+
+ aliceStore.storeSignedPreKey(aliceSignedPreKeyId, new SignedPreKeyRecord(aliceSignedPreKeyId, System.currentTimeMillis(), aliceSignedPreKey, aliceSignature));
+ aliceStore.storePreKey(aliceUnsignedPreKeyId, new PreKeyRecord(aliceUnsignedPreKeyId, aliceUnsignedPreKey));
+
+ return alicePreKeyBundle;
+ }
+
+ private PreKeyBundle createBobPreKeyBundle(AxolotlStore bobStore) throws InvalidKeyException {
+ ECKeyPair bobUnsignedPreKey = Curve.generateKeyPair();
+ int bobUnsignedPreKeyId = new Random().nextInt(Medium.MAX_VALUE);
+ byte[] bobSignature = Curve.calculateSignature(bobStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKey.getPublicKey().serialize());
+
+ PreKeyBundle bobPreKeyBundle = new PreKeyBundle(1, 1,
+ bobUnsignedPreKeyId, bobUnsignedPreKey.getPublicKey(),
+ bobSignedPreKeyId, bobSignedPreKey.getPublicKey(),
+ bobSignature, bobStore.getIdentityKeyPair().getPublicKey());
+
+ bobStore.storeSignedPreKey(bobSignedPreKeyId, new SignedPreKeyRecord(bobSignedPreKeyId, System.currentTimeMillis(), bobSignedPreKey, bobSignature));
+ bobStore.storePreKey(bobUnsignedPreKeyId, new PreKeyRecord(bobUnsignedPreKeyId, bobUnsignedPreKey));
+
+ return bobPreKeyBundle;
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/ecc/Curve25519Test.java b/src/androidTest/java/org/whispersystems/test/ecc/Curve25519Test.java
new file mode 100644
index 00000000..4b8ce2ea
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/ecc/Curve25519Test.java
@@ -0,0 +1,154 @@
+package org.whispersystems.test.ecc;
+
+import android.test.AndroidTestCase;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+
+import java.util.Arrays;
+
+
+public class Curve25519Test extends AndroidTestCase {
+
+ public void testAgreement() throws InvalidKeyException {
+
+ byte[] alicePublic = {(byte) 0x05, (byte) 0x1b, (byte) 0xb7, (byte) 0x59, (byte) 0x66,
+ (byte) 0xf2, (byte) 0xe9, (byte) 0x3a, (byte) 0x36, (byte) 0x91,
+ (byte) 0xdf, (byte) 0xff, (byte) 0x94, (byte) 0x2b, (byte) 0xb2,
+ (byte) 0xa4, (byte) 0x66, (byte) 0xa1, (byte) 0xc0, (byte) 0x8b,
+ (byte) 0x8d, (byte) 0x78, (byte) 0xca, (byte) 0x3f, (byte) 0x4d,
+ (byte) 0x6d, (byte) 0xf8, (byte) 0xb8, (byte) 0xbf, (byte) 0xa2,
+ (byte) 0xe4, (byte) 0xee, (byte) 0x28};
+
+ byte[] alicePrivate = {(byte) 0xc8, (byte) 0x06, (byte) 0x43, (byte) 0x9d, (byte) 0xc9,
+ (byte) 0xd2, (byte) 0xc4, (byte) 0x76, (byte) 0xff, (byte) 0xed,
+ (byte) 0x8f, (byte) 0x25, (byte) 0x80, (byte) 0xc0, (byte) 0x88,
+ (byte) 0x8d, (byte) 0x58, (byte) 0xab, (byte) 0x40, (byte) 0x6b,
+ (byte) 0xf7, (byte) 0xae, (byte) 0x36, (byte) 0x98, (byte) 0x87,
+ (byte) 0x90, (byte) 0x21, (byte) 0xb9, (byte) 0x6b, (byte) 0xb4,
+ (byte) 0xbf, (byte) 0x59};
+
+ byte[] bobPublic = {(byte) 0x05, (byte) 0x65, (byte) 0x36, (byte) 0x14, (byte) 0x99,
+ (byte) 0x3d, (byte) 0x2b, (byte) 0x15, (byte) 0xee, (byte) 0x9e,
+ (byte) 0x5f, (byte) 0xd3, (byte) 0xd8, (byte) 0x6c, (byte) 0xe7,
+ (byte) 0x19, (byte) 0xef, (byte) 0x4e, (byte) 0xc1, (byte) 0xda,
+ (byte) 0xae, (byte) 0x18, (byte) 0x86, (byte) 0xa8, (byte) 0x7b,
+ (byte) 0x3f, (byte) 0x5f, (byte) 0xa9, (byte) 0x56, (byte) 0x5a,
+ (byte) 0x27, (byte) 0xa2, (byte) 0x2f};
+
+ byte[] bobPrivate = {(byte) 0xb0, (byte) 0x3b, (byte) 0x34, (byte) 0xc3, (byte) 0x3a,
+ (byte) 0x1c, (byte) 0x44, (byte) 0xf2, (byte) 0x25, (byte) 0xb6,
+ (byte) 0x62, (byte) 0xd2, (byte) 0xbf, (byte) 0x48, (byte) 0x59,
+ (byte) 0xb8, (byte) 0x13, (byte) 0x54, (byte) 0x11, (byte) 0xfa,
+ (byte) 0x7b, (byte) 0x03, (byte) 0x86, (byte) 0xd4, (byte) 0x5f,
+ (byte) 0xb7, (byte) 0x5d, (byte) 0xc5, (byte) 0xb9, (byte) 0x1b,
+ (byte) 0x44, (byte) 0x66};
+
+ byte[] shared = {(byte) 0x32, (byte) 0x5f, (byte) 0x23, (byte) 0x93, (byte) 0x28,
+ (byte) 0x94, (byte) 0x1c, (byte) 0xed, (byte) 0x6e, (byte) 0x67,
+ (byte) 0x3b, (byte) 0x86, (byte) 0xba, (byte) 0x41, (byte) 0x01,
+ (byte) 0x74, (byte) 0x48, (byte) 0xe9, (byte) 0x9b, (byte) 0x64,
+ (byte) 0x9a, (byte) 0x9c, (byte) 0x38, (byte) 0x06, (byte) 0xc1,
+ (byte) 0xdd, (byte) 0x7c, (byte) 0xa4, (byte) 0xc4, (byte) 0x77,
+ (byte) 0xe6, (byte) 0x29};
+
+ ECPublicKey alicePublicKey = Curve.decodePoint(alicePublic, 0);
+ ECPrivateKey alicePrivateKey = Curve.decodePrivatePoint(alicePrivate);
+
+ ECPublicKey bobPublicKey = Curve.decodePoint(bobPublic, 0);
+ ECPrivateKey bobPrivateKey = Curve.decodePrivatePoint(bobPrivate);
+
+ byte[] sharedOne = Curve.calculateAgreement(alicePublicKey, bobPrivateKey);
+ byte[] sharedTwo = Curve.calculateAgreement(bobPublicKey, alicePrivateKey);
+
+ assertTrue(Arrays.equals(sharedOne, shared));
+ assertTrue(Arrays.equals(sharedTwo, shared));
+ }
+
+ public void testRandomAgreements() throws InvalidKeyException {
+ for (int i=0;i<50;i++) {
+ ECKeyPair alice = Curve.generateKeyPair();
+ ECKeyPair bob = Curve.generateKeyPair();
+
+ byte[] sharedAlice = Curve.calculateAgreement(bob.getPublicKey(), alice.getPrivateKey());
+ byte[] sharedBob = Curve.calculateAgreement(alice.getPublicKey(), bob.getPrivateKey());
+
+ assertTrue(Arrays.equals(sharedAlice, sharedBob));
+ }
+ }
+
+ public void testSignature() throws InvalidKeyException {
+ byte[] aliceIdentityPrivate = {(byte)0xc0, (byte)0x97, (byte)0x24, (byte)0x84, (byte)0x12,
+ (byte)0xe5, (byte)0x8b, (byte)0xf0, (byte)0x5d, (byte)0xf4,
+ (byte)0x87, (byte)0x96, (byte)0x82, (byte)0x05, (byte)0x13,
+ (byte)0x27, (byte)0x94, (byte)0x17, (byte)0x8e, (byte)0x36,
+ (byte)0x76, (byte)0x37, (byte)0xf5, (byte)0x81, (byte)0x8f,
+ (byte)0x81, (byte)0xe0, (byte)0xe6, (byte)0xce, (byte)0x73,
+ (byte)0xe8, (byte)0x65};
+
+ byte[] aliceIdentityPublic = {(byte)0x05, (byte)0xab, (byte)0x7e, (byte)0x71, (byte)0x7d,
+ (byte)0x4a, (byte)0x16, (byte)0x3b, (byte)0x7d, (byte)0x9a,
+ (byte)0x1d, (byte)0x80, (byte)0x71, (byte)0xdf, (byte)0xe9,
+ (byte)0xdc, (byte)0xf8, (byte)0xcd, (byte)0xcd, (byte)0x1c,
+ (byte)0xea, (byte)0x33, (byte)0x39, (byte)0xb6, (byte)0x35,
+ (byte)0x6b, (byte)0xe8, (byte)0x4d, (byte)0x88, (byte)0x7e,
+ (byte)0x32, (byte)0x2c, (byte)0x64};
+
+ byte[] aliceEphemeralPublic = {(byte)0x05, (byte)0xed, (byte)0xce, (byte)0x9d, (byte)0x9c,
+ (byte)0x41, (byte)0x5c, (byte)0xa7, (byte)0x8c, (byte)0xb7,
+ (byte)0x25, (byte)0x2e, (byte)0x72, (byte)0xc2, (byte)0xc4,
+ (byte)0xa5, (byte)0x54, (byte)0xd3, (byte)0xeb, (byte)0x29,
+ (byte)0x48, (byte)0x5a, (byte)0x0e, (byte)0x1d, (byte)0x50,
+ (byte)0x31, (byte)0x18, (byte)0xd1, (byte)0xa8, (byte)0x2d,
+ (byte)0x99, (byte)0xfb, (byte)0x4a};
+
+ byte[] aliceSignature = {(byte)0x5d, (byte)0xe8, (byte)0x8c, (byte)0xa9, (byte)0xa8,
+ (byte)0x9b, (byte)0x4a, (byte)0x11, (byte)0x5d, (byte)0xa7,
+ (byte)0x91, (byte)0x09, (byte)0xc6, (byte)0x7c, (byte)0x9c,
+ (byte)0x74, (byte)0x64, (byte)0xa3, (byte)0xe4, (byte)0x18,
+ (byte)0x02, (byte)0x74, (byte)0xf1, (byte)0xcb, (byte)0x8c,
+ (byte)0x63, (byte)0xc2, (byte)0x98, (byte)0x4e, (byte)0x28,
+ (byte)0x6d, (byte)0xfb, (byte)0xed, (byte)0xe8, (byte)0x2d,
+ (byte)0xeb, (byte)0x9d, (byte)0xcd, (byte)0x9f, (byte)0xae,
+ (byte)0x0b, (byte)0xfb, (byte)0xb8, (byte)0x21, (byte)0x56,
+ (byte)0x9b, (byte)0x3d, (byte)0x90, (byte)0x01, (byte)0xbd,
+ (byte)0x81, (byte)0x30, (byte)0xcd, (byte)0x11, (byte)0xd4,
+ (byte)0x86, (byte)0xce, (byte)0xf0, (byte)0x47, (byte)0xbd,
+ (byte)0x60, (byte)0xb8, (byte)0x6e, (byte)0x88};
+
+ ECPrivateKey alicePrivateKey = Curve.decodePrivatePoint(aliceIdentityPrivate);
+ ECPublicKey alicePublicKey = Curve.decodePoint(aliceIdentityPublic, 0);
+ ECPublicKey aliceEphemeral = Curve.decodePoint(aliceEphemeralPublic, 0);
+
+ if (!Curve.verifySignature(alicePublicKey, aliceEphemeral.serialize(), aliceSignature)) {
+ throw new AssertionError("Sig verification failed!");
+ }
+
+ for (int i=0;i<aliceSignature.length;i++) {
+ byte[] modifiedSignature = new byte[aliceSignature.length];
+ System.arraycopy(aliceSignature, 0, modifiedSignature, 0, modifiedSignature.length);
+
+ modifiedSignature[i] ^= 0x01;
+
+ if (Curve.verifySignature(alicePublicKey, aliceEphemeral.serialize(), modifiedSignature)) {
+ throw new AssertionError("Sig verification succeeded!");
+ }
+ }
+ }
+
+ public void testSignatureOverflow() throws InvalidKeyException {
+ ECKeyPair keys = Curve.generateKeyPair();
+ byte[] message = new byte[4096];
+
+ try {
+ byte[] signature = Curve.calculateSignature(keys.getPrivateKey(), message);
+ throw new InvalidKeyException("Should have asserted!");
+ } catch (AssertionError e) {
+ // Success!
+ }
+ }
+
+}
diff --git a/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java b/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java
new file mode 100644
index 00000000..6d93e921
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java
@@ -0,0 +1,151 @@
+package org.whispersystems.test.groups;
+
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import org.whispersystems.libaxolotl.DuplicateMessageException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.NoSessionException;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.groups.GroupCipher;
+import org.whispersystems.libaxolotl.groups.GroupSessionBuilder;
+import org.whispersystems.libaxolotl.protocol.SenderKeyDistributionMessage;
+import org.whispersystems.libaxolotl.util.KeyHelper;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+public class GroupCipherTest extends AndroidTestCase {
+
+ public void testBasicEncryptDecrypt()
+ throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
+ {
+ InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
+ InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
+
+ GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
+ GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
+
+ GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt");
+ GroupCipher bobGroupCipher = new GroupCipher(bobStore, "groupWithBobInIt::aliceUserName");
+
+ byte[] aliceSenderKey = KeyHelper.generateSenderKey();
+ ECKeyPair aliceSenderSigningKey = KeyHelper.generateSenderSigningKey();
+ int aliceSenderKeyId = KeyHelper.generateSenderKeyId();
+
+ SenderKeyDistributionMessage aliceDistributionMessage =
+ aliceSessionBuilder.process("groupWithBobInIt", aliceSenderKeyId, 0,
+ aliceSenderKey, aliceSenderSigningKey);
+
+ bobSessionBuilder.process("groupWithBobInIt::aliceUserName", aliceDistributionMessage);
+
+ byte[] ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert".getBytes());
+ byte[] plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice);
+
+ assertTrue(new String(plaintextFromAlice).equals("smert ze smert"));
+ }
+
+ public void testBasicRatchet()
+ throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
+ {
+ InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
+ InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
+
+ GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
+ GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
+
+ GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt");
+ GroupCipher bobGroupCipher = new GroupCipher(bobStore, "groupWithBobInIt::aliceUserName");
+
+ byte[] aliceSenderKey = KeyHelper.generateSenderKey();
+ ECKeyPair aliceSenderSigningKey = KeyHelper.generateSenderSigningKey();
+ int aliceSenderKeyId = KeyHelper.generateSenderKeyId();
+
+ SenderKeyDistributionMessage aliceDistributionMessage =
+ aliceSessionBuilder.process("groupWithBobInIt", aliceSenderKeyId, 0,
+ aliceSenderKey, aliceSenderSigningKey);
+
+ bobSessionBuilder.process("groupWithBobInIt::aliceUserName", aliceDistributionMessage);
+
+ byte[] ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert".getBytes());
+ byte[] ciphertextFromAlice2 = aliceGroupCipher.encrypt("smert ze smert2".getBytes());
+ byte[] ciphertextFromAlice3 = aliceGroupCipher.encrypt("smert ze smert3".getBytes());
+
+ byte[] plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice);
+
+ try {
+ bobGroupCipher.decrypt(ciphertextFromAlice);
+ throw new AssertionError("Should have ratcheted forward!");
+ } catch (DuplicateMessageException dme) {
+ // good
+ }
+
+ byte[] plaintextFromAlice2 = bobGroupCipher.decrypt(ciphertextFromAlice2);
+ byte[] plaintextFromAlice3 = bobGroupCipher.decrypt(ciphertextFromAlice3);
+
+ assertTrue(new String(plaintextFromAlice).equals("smert ze smert"));
+ assertTrue(new String(plaintextFromAlice2).equals("smert ze smert2"));
+ assertTrue(new String(plaintextFromAlice3).equals("smert ze smert3"));
+ }
+
+ public void testOutOfOrder()
+ throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
+ {
+ InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
+ InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
+
+ GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
+ GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
+
+ GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt");
+ GroupCipher bobGroupCipher = new GroupCipher(bobStore, "groupWithBobInIt::aliceUserName");
+
+ byte[] aliceSenderKey = KeyHelper.generateSenderKey();
+ ECKeyPair aliceSenderSigningKey = KeyHelper.generateSenderSigningKey();
+ int aliceSenderKeyId = KeyHelper.generateSenderKeyId();
+
+ SenderKeyDistributionMessage aliceDistributionMessage =
+ aliceSessionBuilder.process("groupWithBobInIt", aliceSenderKeyId, 0,
+ aliceSenderKey, aliceSenderSigningKey);
+
+ bobSessionBuilder.process("groupWithBobInIt::aliceUserName", aliceDistributionMessage);
+
+
+ ArrayList<byte[]> ciphertexts = new ArrayList<>(100);
+
+ for (int i=0;i<100;i++) {
+ ciphertexts.add(aliceGroupCipher.encrypt("up the punks".getBytes()));
+ }
+
+ while (ciphertexts.size() > 0) {
+ int index = randomInt() % ciphertexts.size();
+ byte[] ciphertext = ciphertexts.remove(index);
+ byte[] plaintext = bobGroupCipher.decrypt(ciphertext);
+
+ assertTrue(new String(plaintext).equals("up the punks"));
+ }
+ }
+
+ public void testEncryptNoSession() {
+ InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
+ GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt");
+ try {
+ aliceGroupCipher.encrypt("up the punks".getBytes());
+ throw new AssertionError("Should have failed!");
+ } catch (NoSessionException nse) {
+ // good
+ }
+ }
+
+ private int randomInt() {
+ try {
+ return SecureRandom.getInstance("SHA1PRNG").nextInt(Integer.MAX_VALUE);
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java b/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java
new file mode 100644
index 00000000..450d802d
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java
@@ -0,0 +1,33 @@
+package org.whispersystems.test.groups;
+
+import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord;
+import org.whispersystems.libaxolotl.groups.state.SenderKeyStore;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class InMemorySenderKeyStore implements SenderKeyStore {
+
+ private final Map<String, SenderKeyRecord> store = new HashMap<>();
+
+ @Override
+ public void storeSenderKey(String senderKeyId, SenderKeyRecord record) {
+ store.put(senderKeyId, record);
+ }
+
+ @Override
+ public SenderKeyRecord loadSenderKey(String senderKeyId) {
+ try {
+ SenderKeyRecord record = store.get(senderKeyId);
+
+ if (record == null) {
+ return new SenderKeyRecord();
+ } else {
+ return new SenderKeyRecord(record.serialize());
+ }
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/kdf/HKDFTest.java b/src/androidTest/java/org/whispersystems/test/kdf/HKDFTest.java
new file mode 100644
index 00000000..079bc4fa
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/kdf/HKDFTest.java
@@ -0,0 +1,139 @@
+package org.whispersystems.test.kdf;
+
+import android.test.AndroidTestCase;
+
+import org.whispersystems.libaxolotl.kdf.HKDF;
+
+import java.util.Arrays;
+
+public class HKDFTest extends AndroidTestCase {
+
+ public void testVectorV3() {
+ byte[] ikm = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b};
+
+ byte[] salt = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c};
+
+ byte[] info = {(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4,
+ (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9};
+
+ byte[] okm = {(byte) 0x3c, (byte) 0xb2, (byte) 0x5f, (byte) 0x25, (byte) 0xfa,
+ (byte) 0xac, (byte) 0xd5, (byte) 0x7a, (byte) 0x90, (byte) 0x43,
+ (byte) 0x4f, (byte) 0x64, (byte) 0xd0, (byte) 0x36, (byte) 0x2f,
+ (byte) 0x2a, (byte) 0x2d, (byte) 0x2d, (byte) 0x0a, (byte) 0x90,
+ (byte) 0xcf, (byte) 0x1a, (byte) 0x5a, (byte) 0x4c, (byte) 0x5d,
+ (byte) 0xb0, (byte) 0x2d, (byte) 0x56, (byte) 0xec, (byte) 0xc4,
+ (byte) 0xc5, (byte) 0xbf, (byte) 0x34, (byte) 0x00, (byte) 0x72,
+ (byte) 0x08, (byte) 0xd5, (byte) 0xb8, (byte) 0x87, (byte) 0x18,
+ (byte) 0x58, (byte) 0x65};
+
+ byte[] actualOutput = HKDF.createFor(3).deriveSecrets(ikm, salt, info, 42);
+
+ assertTrue(Arrays.equals(okm, actualOutput));
+ }
+
+ public void testVectorLongV3() {
+ byte[] ikm = {(byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09,
+ (byte) 0x0a, (byte) 0x0b, (byte) 0x0c, (byte) 0x0d, (byte) 0x0e,
+ (byte) 0x0f, (byte) 0x10, (byte) 0x11, (byte) 0x12, (byte) 0x13,
+ (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17, (byte) 0x18,
+ (byte) 0x19, (byte) 0x1a, (byte) 0x1b, (byte) 0x1c, (byte) 0x1d,
+ (byte) 0x1e, (byte) 0x1f, (byte) 0x20, (byte) 0x21, (byte) 0x22,
+ (byte) 0x23, (byte) 0x24, (byte) 0x25, (byte) 0x26, (byte) 0x27,
+ (byte) 0x28, (byte) 0x29, (byte) 0x2a, (byte) 0x2b, (byte) 0x2c,
+ (byte) 0x2d, (byte) 0x2e, (byte) 0x2f, (byte) 0x30, (byte) 0x31,
+ (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x36,
+ (byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3a, (byte) 0x3b,
+ (byte) 0x3c, (byte) 0x3d, (byte) 0x3e, (byte) 0x3f, (byte) 0x40,
+ (byte) 0x41, (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45,
+ (byte) 0x46, (byte) 0x47, (byte) 0x48, (byte) 0x49, (byte) 0x4a,
+ (byte) 0x4b, (byte) 0x4c, (byte) 0x4d, (byte) 0x4e, (byte) 0x4f};
+
+ byte[] salt = {(byte) 0x60, (byte) 0x61, (byte) 0x62, (byte) 0x63, (byte) 0x64,
+ (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68, (byte) 0x69,
+ (byte) 0x6a, (byte) 0x6b, (byte) 0x6c, (byte) 0x6d, (byte) 0x6e,
+ (byte) 0x6f, (byte) 0x70, (byte) 0x71, (byte) 0x72, (byte) 0x73,
+ (byte) 0x74, (byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78,
+ (byte) 0x79, (byte) 0x7a, (byte) 0x7b, (byte) 0x7c, (byte) 0x7d,
+ (byte) 0x7e, (byte) 0x7f, (byte) 0x80, (byte) 0x81, (byte) 0x82,
+ (byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87,
+ (byte) 0x88, (byte) 0x89, (byte) 0x8a, (byte) 0x8b, (byte) 0x8c,
+ (byte) 0x8d, (byte) 0x8e, (byte) 0x8f, (byte) 0x90, (byte) 0x91,
+ (byte) 0x92, (byte) 0x93, (byte) 0x94, (byte) 0x95, (byte) 0x96,
+ (byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9a, (byte) 0x9b,
+ (byte) 0x9c, (byte) 0x9d, (byte) 0x9e, (byte) 0x9f, (byte) 0xa0,
+ (byte) 0xa1, (byte) 0xa2, (byte) 0xa3, (byte) 0xa4, (byte) 0xa5,
+ (byte) 0xa6, (byte) 0xa7, (byte) 0xa8, (byte) 0xa9, (byte) 0xaa,
+ (byte) 0xab, (byte) 0xac, (byte) 0xad, (byte) 0xae, (byte) 0xaf};
+
+ byte[] info = {(byte) 0xb0, (byte) 0xb1, (byte) 0xb2, (byte) 0xb3, (byte) 0xb4,
+ (byte) 0xb5, (byte) 0xb6, (byte) 0xb7, (byte) 0xb8, (byte) 0xb9,
+ (byte) 0xba, (byte) 0xbb, (byte) 0xbc, (byte) 0xbd, (byte) 0xbe,
+ (byte) 0xbf, (byte) 0xc0, (byte) 0xc1, (byte) 0xc2, (byte) 0xc3,
+ (byte) 0xc4, (byte) 0xc5, (byte) 0xc6, (byte) 0xc7, (byte) 0xc8,
+ (byte) 0xc9, (byte) 0xca, (byte) 0xcb, (byte) 0xcc, (byte) 0xcd,
+ (byte) 0xce, (byte) 0xcf, (byte) 0xd0, (byte) 0xd1, (byte) 0xd2,
+ (byte) 0xd3, (byte) 0xd4, (byte) 0xd5, (byte) 0xd6, (byte) 0xd7,
+ (byte) 0xd8, (byte) 0xd9, (byte) 0xda, (byte) 0xdb, (byte) 0xdc,
+ (byte) 0xdd, (byte) 0xde, (byte) 0xdf, (byte) 0xe0, (byte) 0xe1,
+ (byte) 0xe2, (byte) 0xe3, (byte) 0xe4, (byte) 0xe5, (byte) 0xe6,
+ (byte) 0xe7, (byte) 0xe8, (byte) 0xe9, (byte) 0xea, (byte) 0xeb,
+ (byte) 0xec, (byte) 0xed, (byte) 0xee, (byte) 0xef, (byte) 0xf0,
+ (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4, (byte) 0xf5,
+ (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9, (byte) 0xfa,
+ (byte) 0xfb, (byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0xff};
+
+ byte[] okm = {(byte) 0xb1, (byte) 0x1e, (byte) 0x39, (byte) 0x8d, (byte) 0xc8,
+ (byte) 0x03, (byte) 0x27, (byte) 0xa1, (byte) 0xc8, (byte) 0xe7,
+ (byte) 0xf7, (byte) 0x8c, (byte) 0x59, (byte) 0x6a, (byte) 0x49,
+ (byte) 0x34, (byte) 0x4f, (byte) 0x01, (byte) 0x2e, (byte) 0xda,
+ (byte) 0x2d, (byte) 0x4e, (byte) 0xfa, (byte) 0xd8, (byte) 0xa0,
+ (byte) 0x50, (byte) 0xcc, (byte) 0x4c, (byte) 0x19, (byte) 0xaf,
+ (byte) 0xa9, (byte) 0x7c, (byte) 0x59, (byte) 0x04, (byte) 0x5a,
+ (byte) 0x99, (byte) 0xca, (byte) 0xc7, (byte) 0x82, (byte) 0x72,
+ (byte) 0x71, (byte) 0xcb, (byte) 0x41, (byte) 0xc6, (byte) 0x5e,
+ (byte) 0x59, (byte) 0x0e, (byte) 0x09, (byte) 0xda, (byte) 0x32,
+ (byte) 0x75, (byte) 0x60, (byte) 0x0c, (byte) 0x2f, (byte) 0x09,
+ (byte) 0xb8, (byte) 0x36, (byte) 0x77, (byte) 0x93, (byte) 0xa9,
+ (byte) 0xac, (byte) 0xa3, (byte) 0xdb, (byte) 0x71, (byte) 0xcc,
+ (byte) 0x30, (byte) 0xc5, (byte) 0x81, (byte) 0x79, (byte) 0xec,
+ (byte) 0x3e, (byte) 0x87, (byte) 0xc1, (byte) 0x4c, (byte) 0x01,
+ (byte) 0xd5, (byte) 0xc1, (byte) 0xf3, (byte) 0x43, (byte) 0x4f,
+ (byte) 0x1d, (byte) 0x87};
+
+ byte[] actualOutput = HKDF.createFor(3).deriveSecrets(ikm, salt, info, 82);
+ assertTrue(Arrays.equals(okm, actualOutput));
+ }
+
+ public void testVectorV2() {
+ byte[] ikm = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b};
+
+ byte[] salt = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c};
+
+ byte[] info = {(byte)0xf0, (byte)0xf1, (byte)0xf2, (byte)0xf3, (byte)0xf4,
+ (byte)0xf5, (byte)0xf6, (byte)0xf7, (byte)0xf8, (byte)0xf9};
+
+ byte[] okm = {(byte)0x6e, (byte)0xc2, (byte)0x55, (byte)0x6d, (byte)0x5d,
+ (byte)0x7b, (byte)0x1d, (byte)0x81, (byte)0xde, (byte)0xe4,
+ (byte)0x22, (byte)0x2a, (byte)0xd7, (byte)0x48, (byte)0x36,
+ (byte)0x95, (byte)0xdd, (byte)0xc9, (byte)0x8f, (byte)0x4f,
+ (byte)0x5f, (byte)0xab, (byte)0xc0, (byte)0xe0, (byte)0x20,
+ (byte)0x5d, (byte)0xc2, (byte)0xef, (byte)0x87, (byte)0x52,
+ (byte)0xd4, (byte)0x1e, (byte)0x04, (byte)0xe2, (byte)0xe2,
+ (byte)0x11, (byte)0x01, (byte)0xc6, (byte)0x8f, (byte)0xf0,
+ (byte)0x93, (byte)0x94, (byte)0xb8, (byte)0xad, (byte)0x0b,
+ (byte)0xdc, (byte)0xb9, (byte)0x60, (byte)0x9c, (byte)0xd4,
+ (byte)0xee, (byte)0x82, (byte)0xac, (byte)0x13, (byte)0x19,
+ (byte)0x9b, (byte)0x4a, (byte)0xa9, (byte)0xfd, (byte)0xa8,
+ (byte)0x99, (byte)0xda, (byte)0xeb, (byte)0xec};
+
+ byte[] actualOutput = HKDF.createFor(2).deriveSecrets(ikm, salt, info, 64);
+ assertTrue(Arrays.equals(okm, actualOutput));
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/ratchet/ChainKeyTest.java b/src/androidTest/java/org/whispersystems/test/ratchet/ChainKeyTest.java
new file mode 100644
index 00000000..1197f3eb
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/ratchet/ChainKeyTest.java
@@ -0,0 +1,59 @@
+package org.whispersystems.test.ratchet;
+
+import android.test.AndroidTestCase;
+
+import org.whispersystems.libaxolotl.kdf.HKDF;
+import org.whispersystems.libaxolotl.ratchet.ChainKey;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+public class ChainKeyTest extends AndroidTestCase {
+
+ public void testChainKeyDerivationV2() throws NoSuchAlgorithmException {
+
+ byte[] seed = {(byte) 0x8a, (byte) 0xb7, (byte) 0x2d, (byte) 0x6f, (byte) 0x4c,
+ (byte) 0xc5, (byte) 0xac, (byte) 0x0d, (byte) 0x38, (byte) 0x7e,
+ (byte) 0xaf, (byte) 0x46, (byte) 0x33, (byte) 0x78, (byte) 0xdd,
+ (byte) 0xb2, (byte) 0x8e, (byte) 0xdd, (byte) 0x07, (byte) 0x38,
+ (byte) 0x5b, (byte) 0x1c, (byte) 0xb0, (byte) 0x12, (byte) 0x50,
+ (byte) 0xc7, (byte) 0x15, (byte) 0x98, (byte) 0x2e, (byte) 0x7a,
+ (byte) 0xd4, (byte) 0x8f};
+
+ byte[] messageKey = {(byte) 0x02, (byte) 0xa9, (byte) 0xaa, (byte) 0x6c, (byte) 0x7d,
+ (byte) 0xbd, (byte) 0x64, (byte) 0xf9, (byte) 0xd3, (byte) 0xaa,
+ (byte) 0x92, (byte) 0xf9, (byte) 0x2a, (byte) 0x27, (byte) 0x7b,
+ (byte) 0xf5, (byte) 0x46, (byte) 0x09, (byte) 0xda, (byte) 0xdf,
+ (byte) 0x0b, (byte) 0x00, (byte) 0x82, (byte) 0x8a, (byte) 0xcf,
+ (byte) 0xc6, (byte) 0x1e, (byte) 0x3c, (byte) 0x72, (byte) 0x4b,
+ (byte) 0x84, (byte) 0xa7};
+
+ byte[] macKey = {(byte) 0xbf, (byte) 0xbe, (byte) 0x5e, (byte) 0xfb, (byte) 0x60,
+ (byte) 0x30, (byte) 0x30, (byte) 0x52, (byte) 0x67, (byte) 0x42,
+ (byte) 0xe3, (byte) 0xee, (byte) 0x89, (byte) 0xc7, (byte) 0x02,
+ (byte) 0x4e, (byte) 0x88, (byte) 0x4e, (byte) 0x44, (byte) 0x0f,
+ (byte) 0x1f, (byte) 0xf3, (byte) 0x76, (byte) 0xbb, (byte) 0x23,
+ (byte) 0x17, (byte) 0xb2, (byte) 0xd6, (byte) 0x4d, (byte) 0xeb,
+ (byte) 0x7c, (byte) 0x83};
+
+ byte[] nextChainKey = {(byte) 0x28, (byte) 0xe8, (byte) 0xf8, (byte) 0xfe, (byte) 0xe5,
+ (byte) 0x4b, (byte) 0x80, (byte) 0x1e, (byte) 0xef, (byte) 0x7c,
+ (byte) 0x5c, (byte) 0xfb, (byte) 0x2f, (byte) 0x17, (byte) 0xf3,
+ (byte) 0x2c, (byte) 0x7b, (byte) 0x33, (byte) 0x44, (byte) 0x85,
+ (byte) 0xbb, (byte) 0xb7, (byte) 0x0f, (byte) 0xac, (byte) 0x6e,
+ (byte) 0xc1, (byte) 0x03, (byte) 0x42, (byte) 0xa2, (byte) 0x46,
+ (byte) 0xd1, (byte) 0x5d};
+
+ ChainKey chainKey = new ChainKey(HKDF.createFor(2), seed, 0);
+
+ assertTrue(Arrays.equals(chainKey.getKey(), seed));
+ assertTrue(Arrays.equals(chainKey.getMessageKeys().getCipherKey().getEncoded(), messageKey));
+ assertTrue(Arrays.equals(chainKey.getMessageKeys().getMacKey().getEncoded(), macKey));
+ assertTrue(Arrays.equals(chainKey.getNextChainKey().getKey(), nextChainKey));
+ assertTrue(chainKey.getIndex() == 0);
+ assertTrue(chainKey.getMessageKeys().getCounter() == 0);
+ assertTrue(chainKey.getNextChainKey().getIndex() == 1);
+ assertTrue(chainKey.getNextChainKey().getMessageKeys().getCounter() == 1);
+ }
+
+}
diff --git a/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java b/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java
new file mode 100644
index 00000000..311aff90
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java
@@ -0,0 +1,236 @@
+package org.whispersystems.test.ratchet;
+
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters;
+import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters;
+import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
+import org.whispersystems.libaxolotl.state.SessionState;
+import org.whispersystems.libaxolotl.util.Hex;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+import java.util.Arrays;
+
+public class RatchetingSessionTest extends AndroidTestCase {
+
+ public void testRatchetingSessionAsBob() throws InvalidKeyException {
+ byte[] bobPublic = {(byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97,
+ (byte) 0x76, (byte) 0xb8, (byte) 0x77, (byte) 0x02,
+ (byte) 0x05, (byte) 0x74, (byte) 0x5a, (byte) 0x3a,
+ (byte) 0x6e, (byte) 0x24, (byte) 0xf5, (byte) 0x79,
+ (byte) 0xcd, (byte) 0xb4, (byte) 0xba, (byte) 0x7a,
+ (byte) 0x89, (byte) 0x04, (byte) 0x10, (byte) 0x05,
+ (byte) 0x92, (byte) 0x8e, (byte) 0xbb, (byte) 0xad,
+ (byte) 0xc9, (byte) 0xc0, (byte) 0x5a, (byte) 0xd4,
+ (byte) 0x58};
+
+ byte[] bobPrivate = {(byte) 0xa1, (byte) 0xca, (byte) 0xb4, (byte) 0x8f,
+ (byte) 0x7c, (byte) 0x89, (byte) 0x3f, (byte) 0xaf,
+ (byte) 0xa9, (byte) 0x88, (byte) 0x0a, (byte) 0x28,
+ (byte) 0xc3, (byte) 0xb4, (byte) 0x99, (byte) 0x9d,
+ (byte) 0x28, (byte) 0xd6, (byte) 0x32, (byte) 0x95,
+ (byte) 0x62, (byte) 0xd2, (byte) 0x7a, (byte) 0x4e,
+ (byte) 0xa4, (byte) 0xe2, (byte) 0x2e, (byte) 0x9f,
+ (byte) 0xf1, (byte) 0xbd, (byte) 0xd6, (byte) 0x5a};
+
+ byte[] bobIdentityPublic = {(byte) 0x05, (byte) 0xf1, (byte) 0xf4, (byte) 0x38,
+ (byte) 0x74, (byte) 0xf6, (byte) 0x96, (byte) 0x69,
+ (byte) 0x56, (byte) 0xc2, (byte) 0xdd, (byte) 0x47,
+ (byte) 0x3f, (byte) 0x8f, (byte) 0xa1, (byte) 0x5a,
+ (byte) 0xde, (byte) 0xb7, (byte) 0x1d, (byte) 0x1c,
+ (byte) 0xb9, (byte) 0x91, (byte) 0xb2, (byte) 0x34,
+ (byte) 0x16, (byte) 0x92, (byte) 0x32, (byte) 0x4c,
+ (byte) 0xef, (byte) 0xb1, (byte) 0xc5, (byte) 0xe6,
+ (byte) 0x26};
+
+ byte[] bobIdentityPrivate = {(byte) 0x48, (byte) 0x75, (byte) 0xcc, (byte) 0x69,
+ (byte) 0xdd, (byte) 0xf8, (byte) 0xea, (byte) 0x07,
+ (byte) 0x19, (byte) 0xec, (byte) 0x94, (byte) 0x7d,
+ (byte) 0x61, (byte) 0x08, (byte) 0x11, (byte) 0x35,
+ (byte) 0x86, (byte) 0x8d, (byte) 0x5f, (byte) 0xd8,
+ (byte) 0x01, (byte) 0xf0, (byte) 0x2c, (byte) 0x02,
+ (byte) 0x25, (byte) 0xe5, (byte) 0x16, (byte) 0xdf,
+ (byte) 0x21, (byte) 0x56, (byte) 0x60, (byte) 0x5e};
+
+ byte[] aliceBasePublic = {(byte) 0x05, (byte) 0x47, (byte) 0x2d, (byte) 0x1f,
+ (byte) 0xb1, (byte) 0xa9, (byte) 0x86, (byte) 0x2c,
+ (byte) 0x3a, (byte) 0xf6, (byte) 0xbe, (byte) 0xac,
+ (byte) 0xa8, (byte) 0x92, (byte) 0x02, (byte) 0x77,
+ (byte) 0xe2, (byte) 0xb2, (byte) 0x6f, (byte) 0x4a,
+ (byte) 0x79, (byte) 0x21, (byte) 0x3e, (byte) 0xc7,
+ (byte) 0xc9, (byte) 0x06, (byte) 0xae, (byte) 0xb3,
+ (byte) 0x5e, (byte) 0x03, (byte) 0xcf, (byte) 0x89,
+ (byte) 0x50};
+
+ byte[] aliceEphemeralPublic = {(byte) 0x05, (byte) 0x6c, (byte) 0x3e, (byte) 0x0d,
+ (byte) 0x1f, (byte) 0x52, (byte) 0x02, (byte) 0x83,
+ (byte) 0xef, (byte) 0xcc, (byte) 0x55, (byte) 0xfc,
+ (byte) 0xa5, (byte) 0xe6, (byte) 0x70, (byte) 0x75,
+ (byte) 0xb9, (byte) 0x04, (byte) 0x00, (byte) 0x7f,
+ (byte) 0x18, (byte) 0x81, (byte) 0xd1, (byte) 0x51,
+ (byte) 0xaf, (byte) 0x76, (byte) 0xdf, (byte) 0x18,
+ (byte) 0xc5, (byte) 0x1d, (byte) 0x29, (byte) 0xd3,
+ (byte) 0x4b};
+
+ byte[] aliceIdentityPublic = {(byte) 0x05, (byte) 0xb4, (byte) 0xa8, (byte) 0x45,
+ (byte) 0x56, (byte) 0x60, (byte) 0xad, (byte) 0xa6,
+ (byte) 0x5b, (byte) 0x40, (byte) 0x10, (byte) 0x07,
+ (byte) 0xf6, (byte) 0x15, (byte) 0xe6, (byte) 0x54,
+ (byte) 0x04, (byte) 0x17, (byte) 0x46, (byte) 0x43,
+ (byte) 0x2e, (byte) 0x33, (byte) 0x39, (byte) 0xc6,
+ (byte) 0x87, (byte) 0x51, (byte) 0x49, (byte) 0xbc,
+ (byte) 0xee, (byte) 0xfc, (byte) 0xb4, (byte) 0x2b,
+ (byte) 0x4a};
+
+ byte[] senderChain = {(byte)0xd2, (byte)0x2f, (byte)0xd5, (byte)0x6d, (byte)0x3f,
+ (byte)0xec, (byte)0x81, (byte)0x9c, (byte)0xf4, (byte)0xc3,
+ (byte)0xd5, (byte)0x0c, (byte)0x56, (byte)0xed, (byte)0xfb,
+ (byte)0x1c, (byte)0x28, (byte)0x0a, (byte)0x1b, (byte)0x31,
+ (byte)0x96, (byte)0x45, (byte)0x37, (byte)0xf1, (byte)0xd1,
+ (byte)0x61, (byte)0xe1, (byte)0xc9, (byte)0x31, (byte)0x48,
+ (byte)0xe3, (byte)0x6b};
+
+ IdentityKey bobIdentityKeyPublic = new IdentityKey(bobIdentityPublic, 0);
+ ECPrivateKey bobIdentityKeyPrivate = Curve.decodePrivatePoint(bobIdentityPrivate);
+ IdentityKeyPair bobIdentityKey = new IdentityKeyPair(bobIdentityKeyPublic, bobIdentityKeyPrivate);
+ ECPublicKey bobEphemeralPublicKey = Curve.decodePoint(bobPublic, 0);
+ ECPrivateKey bobEphemeralPrivateKey = Curve.decodePrivatePoint(bobPrivate);
+ ECKeyPair bobEphemeralKey = new ECKeyPair(bobEphemeralPublicKey, bobEphemeralPrivateKey);
+ ECKeyPair bobBaseKey = bobEphemeralKey;
+
+ ECPublicKey aliceBasePublicKey = Curve.decodePoint(aliceBasePublic, 0);
+ ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0);
+ IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0);
+
+ BobAxolotlParameters parameters = BobAxolotlParameters.newBuilder()
+ .setOurIdentityKey(bobIdentityKey)
+ .setOurSignedPreKey(bobBaseKey)
+ .setOurRatchetKey(bobEphemeralKey)
+ .setOurOneTimePreKey(Optional.<ECKeyPair>absent())
+ .setTheirIdentityKey(aliceIdentityPublicKey)
+ .setTheirBaseKey(aliceBasePublicKey)
+ .create();
+
+ SessionState session = new SessionState();
+
+ RatchetingSession.initializeSession(session, 2, parameters);
+
+ assertTrue(session.getLocalIdentityKey().equals(bobIdentityKey.getPublicKey()));
+ assertTrue(session.getRemoteIdentityKey().equals(aliceIdentityPublicKey));
+ assertTrue(Arrays.equals(session.getSenderChainKey().getKey(), senderChain));
+ }
+
+ public void testRatchetingSessionAsAlice() throws InvalidKeyException {
+ byte[] bobPublic = {(byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97, (byte) 0x76,
+ (byte) 0xb8, (byte) 0x77, (byte) 0x02, (byte) 0x05, (byte) 0x74,
+ (byte) 0x5a, (byte) 0x3a, (byte) 0x6e, (byte) 0x24, (byte) 0xf5,
+ (byte) 0x79, (byte) 0xcd, (byte) 0xb4, (byte) 0xba, (byte) 0x7a,
+ (byte) 0x89, (byte) 0x04, (byte) 0x10, (byte) 0x05, (byte) 0x92,
+ (byte) 0x8e, (byte) 0xbb, (byte) 0xad, (byte) 0xc9, (byte) 0xc0,
+ (byte) 0x5a, (byte) 0xd4, (byte) 0x58};
+
+ byte[] bobIdentityPublic = {(byte) 0x05, (byte) 0xf1, (byte) 0xf4, (byte) 0x38, (byte) 0x74,
+ (byte) 0xf6, (byte) 0x96, (byte) 0x69, (byte) 0x56, (byte) 0xc2,
+ (byte) 0xdd, (byte) 0x47, (byte) 0x3f, (byte) 0x8f, (byte) 0xa1,
+ (byte) 0x5a, (byte) 0xde, (byte) 0xb7, (byte) 0x1d, (byte) 0x1c,
+ (byte) 0xb9, (byte) 0x91, (byte) 0xb2, (byte) 0x34, (byte) 0x16,
+ (byte) 0x92, (byte) 0x32, (byte) 0x4c, (byte) 0xef, (byte) 0xb1,
+ (byte) 0xc5, (byte) 0xe6, (byte) 0x26};
+
+ byte[] aliceBasePublic = {(byte) 0x05, (byte) 0x47, (byte) 0x2d, (byte) 0x1f, (byte) 0xb1,
+ (byte) 0xa9, (byte) 0x86, (byte) 0x2c, (byte) 0x3a, (byte) 0xf6,
+ (byte) 0xbe, (byte) 0xac, (byte) 0xa8, (byte) 0x92, (byte) 0x02,
+ (byte) 0x77, (byte) 0xe2, (byte) 0xb2, (byte) 0x6f, (byte) 0x4a,
+ (byte) 0x79, (byte) 0x21, (byte) 0x3e, (byte) 0xc7, (byte) 0xc9,
+ (byte) 0x06, (byte) 0xae, (byte) 0xb3, (byte) 0x5e, (byte) 0x03,
+ (byte) 0xcf, (byte) 0x89, (byte) 0x50};
+
+ byte[] aliceBasePrivate = {(byte) 0x11, (byte) 0xae, (byte) 0x7c, (byte) 0x64, (byte) 0xd1,
+ (byte) 0xe6, (byte) 0x1c, (byte) 0xd5, (byte) 0x96, (byte) 0xb7,
+ (byte) 0x6a, (byte) 0x0d, (byte) 0xb5, (byte) 0x01, (byte) 0x26,
+ (byte) 0x73, (byte) 0x39, (byte) 0x1c, (byte) 0xae, (byte) 0x66,
+ (byte) 0xed, (byte) 0xbf, (byte) 0xcf, (byte) 0x07, (byte) 0x3b,
+ (byte) 0x4d, (byte) 0xa8, (byte) 0x05, (byte) 0x16, (byte) 0xa4,
+ (byte) 0x74, (byte) 0x49};
+
+ byte[] aliceEphemeralPublic = {(byte) 0x05, (byte) 0x6c, (byte) 0x3e, (byte) 0x0d, (byte) 0x1f,
+ (byte) 0x52, (byte) 0x02, (byte) 0x83, (byte) 0xef, (byte) 0xcc,
+ (byte) 0x55, (byte) 0xfc, (byte) 0xa5, (byte) 0xe6, (byte) 0x70,
+ (byte) 0x75, (byte) 0xb9, (byte) 0x04, (byte) 0x00, (byte) 0x7f,
+ (byte) 0x18, (byte) 0x81, (byte) 0xd1, (byte) 0x51, (byte) 0xaf,
+ (byte) 0x76, (byte) 0xdf, (byte) 0x18, (byte) 0xc5, (byte) 0x1d,
+ (byte) 0x29, (byte) 0xd3, (byte) 0x4b};
+
+ byte[] aliceEphemeralPrivate = {(byte) 0xd1, (byte) 0xba, (byte) 0x38, (byte) 0xce, (byte) 0xa9,
+ (byte) 0x17, (byte) 0x43, (byte) 0xd3, (byte) 0x39, (byte) 0x39,
+ (byte) 0xc3, (byte) 0x3c, (byte) 0x84, (byte) 0x98, (byte) 0x65,
+ (byte) 0x09, (byte) 0x28, (byte) 0x01, (byte) 0x61, (byte) 0xb8,
+ (byte) 0xb6, (byte) 0x0f, (byte) 0xc7, (byte) 0x87, (byte) 0x0c,
+ (byte) 0x59, (byte) 0x9c, (byte) 0x1d, (byte) 0x46, (byte) 0x20,
+ (byte) 0x12, (byte) 0x48};
+
+ byte[] aliceIdentityPublic = {(byte) 0x05, (byte) 0xb4, (byte) 0xa8, (byte) 0x45, (byte) 0x56,
+ (byte) 0x60, (byte) 0xad, (byte) 0xa6, (byte) 0x5b, (byte) 0x40,
+ (byte) 0x10, (byte) 0x07, (byte) 0xf6, (byte) 0x15, (byte) 0xe6,
+ (byte) 0x54, (byte) 0x04, (byte) 0x17, (byte) 0x46, (byte) 0x43,
+ (byte) 0x2e, (byte) 0x33, (byte) 0x39, (byte) 0xc6, (byte) 0x87,
+ (byte) 0x51, (byte) 0x49, (byte) 0xbc, (byte) 0xee, (byte) 0xfc,
+ (byte) 0xb4, (byte) 0x2b, (byte) 0x4a};
+
+ byte[] aliceIdentityPrivate = {(byte) 0x90, (byte) 0x40, (byte) 0xf0, (byte) 0xd4, (byte) 0xe0,
+ (byte) 0x9c, (byte) 0xf3, (byte) 0x8f, (byte) 0x6d, (byte) 0xc7,
+ (byte) 0xc1, (byte) 0x37, (byte) 0x79, (byte) 0xc9, (byte) 0x08,
+ (byte) 0xc0, (byte) 0x15, (byte) 0xa1, (byte) 0xda, (byte) 0x4f,
+ (byte) 0xa7, (byte) 0x87, (byte) 0x37, (byte) 0xa0, (byte) 0x80,
+ (byte) 0xeb, (byte) 0x0a, (byte) 0x6f, (byte) 0x4f, (byte) 0x5f,
+ (byte) 0x8f, (byte) 0x58};
+
+ byte[] receiverChain = {(byte) 0xd2, (byte) 0x2f, (byte) 0xd5, (byte) 0x6d, (byte) 0x3f,
+ (byte) 0xec, (byte) 0x81, (byte) 0x9c, (byte) 0xf4, (byte) 0xc3,
+ (byte) 0xd5, (byte) 0x0c, (byte) 0x56, (byte) 0xed, (byte) 0xfb,
+ (byte) 0x1c, (byte) 0x28, (byte) 0x0a, (byte) 0x1b, (byte) 0x31,
+ (byte) 0x96, (byte) 0x45, (byte) 0x37, (byte) 0xf1, (byte) 0xd1,
+ (byte) 0x61, (byte) 0xe1, (byte) 0xc9, (byte) 0x31, (byte) 0x48,
+ (byte) 0xe3, (byte) 0x6b};
+
+ IdentityKey bobIdentityKey = new IdentityKey(bobIdentityPublic, 0);
+ ECPublicKey bobEphemeralPublicKey = Curve.decodePoint(bobPublic, 0);
+ ECPublicKey bobBasePublicKey = bobEphemeralPublicKey;
+ ECPublicKey aliceBasePublicKey = Curve.decodePoint(aliceBasePublic, 0);
+ ECPrivateKey aliceBasePrivateKey = Curve.decodePrivatePoint(aliceBasePrivate);
+ ECKeyPair aliceBaseKey = new ECKeyPair(aliceBasePublicKey, aliceBasePrivateKey);
+ ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0);
+ ECPrivateKey aliceEphemeralPrivateKey = Curve.decodePrivatePoint(aliceEphemeralPrivate);
+ ECKeyPair aliceEphemeralKey = new ECKeyPair(aliceEphemeralPublicKey, aliceEphemeralPrivateKey);
+ IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0);
+ ECPrivateKey aliceIdentityPrivateKey = Curve.decodePrivatePoint(aliceIdentityPrivate);
+ IdentityKeyPair aliceIdentityKey = new IdentityKeyPair(aliceIdentityPublicKey, aliceIdentityPrivateKey);
+
+ SessionState session = new SessionState();
+
+ AliceAxolotlParameters parameters = AliceAxolotlParameters.newBuilder()
+ .setOurBaseKey(aliceBaseKey)
+ .setOurIdentityKey(aliceIdentityKey)
+ .setTheirIdentityKey(bobIdentityKey)
+ .setTheirSignedPreKey(bobBasePublicKey)
+ .setTheirRatchetKey(bobEphemeralPublicKey)
+ .setTheirOneTimePreKey(Optional.<ECPublicKey>absent())
+ .create();
+
+ RatchetingSession.initializeSession(session, 2, parameters);
+
+ assertTrue(session.getLocalIdentityKey().equals(aliceIdentityKey.getPublicKey()));
+ assertTrue(session.getRemoteIdentityKey().equals(bobIdentityKey));
+ assertTrue(Arrays.equals(session.getReceiverChainKey(bobEphemeralPublicKey).getKey(),
+ receiverChain));
+
+ }
+}
diff --git a/src/androidTest/java/org/whispersystems/test/ratchet/RootKeyTest.java b/src/androidTest/java/org/whispersystems/test/ratchet/RootKeyTest.java
new file mode 100644
index 00000000..c48ef23d
--- /dev/null
+++ b/src/androidTest/java/org/whispersystems/test/ratchet/RootKeyTest.java
@@ -0,0 +1,84 @@
+package org.whispersystems.test.ratchet;
+
+import android.test.AndroidTestCase;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.kdf.HKDF;
+import org.whispersystems.libaxolotl.ratchet.ChainKey;
+import org.whispersystems.libaxolotl.ratchet.RootKey;
+import org.whispersystems.libaxolotl.util.Pair;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+public class RootKeyTest extends AndroidTestCase {
+
+ public void testRootKeyDerivationV2() throws NoSuchAlgorithmException, InvalidKeyException {
+ byte[] rootKeySeed = {(byte) 0x7b, (byte) 0xa6, (byte) 0xde, (byte) 0xbc, (byte) 0x2b,
+ (byte) 0xc1, (byte) 0xbb, (byte) 0xf9, (byte) 0x1a, (byte) 0xbb,
+ (byte) 0xc1, (byte) 0x36, (byte) 0x74, (byte) 0x04, (byte) 0x17,
+ (byte) 0x6c, (byte) 0xa6, (byte) 0x23, (byte) 0x09, (byte) 0x5b,
+ (byte) 0x7e, (byte) 0xc6, (byte) 0x6b, (byte) 0x45, (byte) 0xf6,
+ (byte) 0x02, (byte) 0xd9, (byte) 0x35, (byte) 0x38, (byte) 0x94,
+ (byte) 0x2d, (byte) 0xcc};
+
+ byte[] alicePublic = {(byte) 0x05, (byte) 0xee, (byte) 0x4f, (byte) 0xa6, (byte) 0xcd,
+ (byte) 0xc0, (byte) 0x30, (byte) 0xdf, (byte) 0x49, (byte) 0xec,
+ (byte) 0xd0, (byte) 0xba, (byte) 0x6c, (byte) 0xfc, (byte) 0xff,
+ (byte) 0xb2, (byte) 0x33, (byte) 0xd3, (byte) 0x65, (byte) 0xa2,
+ (byte) 0x7f, (byte) 0xad, (byte) 0xbe, (byte) 0xff, (byte) 0x77,
+ (byte) 0xe9, (byte) 0x63, (byte) 0xfc, (byte) 0xb1, (byte) 0x62,
+ (byte) 0x22, (byte) 0xe1, (byte) 0x3a};
+
+ byte[] alicePrivate = {(byte) 0x21, (byte) 0x68, (byte) 0x22, (byte) 0xec, (byte) 0x67,
+ (byte) 0xeb, (byte) 0x38, (byte) 0x04, (byte) 0x9e, (byte) 0xba,
+ (byte) 0xe7, (byte) 0xb9, (byte) 0x39, (byte) 0xba, (byte) 0xea,
+ (byte) 0xeb, (byte) 0xb1, (byte) 0x51, (byte) 0xbb, (byte) 0xb3,
+ (byte) 0x2d, (byte) 0xb8, (byte) 0x0f, (byte) 0xd3, (byte) 0x89,
+ (byte) 0x24, (byte) 0x5a, (byte) 0xc3, (byte) 0x7a, (byte) 0x94,
+ (byte) 0x8e, (byte) 0x50};
+
+ byte[] bobPublic = {(byte) 0x05, (byte) 0xab, (byte) 0xb8, (byte) 0xeb, (byte) 0x29,
+ (byte) 0xcc, (byte) 0x80, (byte) 0xb4, (byte) 0x71, (byte) 0x09,
+ (byte) 0xa2, (byte) 0x26, (byte) 0x5a, (byte) 0xbe, (byte) 0x97,
+ (byte) 0x98, (byte) 0x48, (byte) 0x54, (byte) 0x06, (byte) 0xe3,
+ (byte) 0x2d, (byte) 0xa2, (byte) 0x68, (byte) 0x93, (byte) 0x4a,
+ (byte) 0x95, (byte) 0x55, (byte) 0xe8, (byte) 0x47, (byte) 0x57,
+ (byte) 0x70, (byte) 0x8a, (byte) 0x30};
+
+ byte[] nextRoot = {(byte) 0xb1, (byte) 0x14, (byte) 0xf5, (byte) 0xde, (byte) 0x28,
+ (byte) 0x01, (byte) 0x19, (byte) 0x85, (byte) 0xe6, (byte) 0xeb,
+ (byte) 0xa2, (byte) 0x5d, (byte) 0x50, (byte) 0xe7, (byte) 0xec,
+ (byte) 0x41, (byte) 0xa9, (byte) 0xb0, (byte) 0x2f, (byte) 0x56,
+ (byte) 0x93, (byte) 0xc5, (byte) 0xc7, (byte) 0x88, (byte) 0xa6,
+ (byte) 0x3a, (byte) 0x06, (byte) 0xd2, (byte) 0x12, (byte) 0xa2,
+ (byte) 0xf7, (byte) 0x31};
+
+ byte[] nextChain = {(byte) 0x9d, (byte) 0x7d, (byte) 0x24, (byte) 0x69, (byte) 0xbc,
+ (byte) 0x9a, (byte) 0xe5, (byte) 0x3e, (byte) 0xe9, (byte) 0x80,
+ (byte) 0x5a, (byte) 0xa3, (byte) 0x26, (byte) 0x4d, (byte) 0x24,
+ (byte) 0x99, (byte) 0xa3, (byte) 0xac, (byte) 0xe8, (byte) 0x0f,
+ (byte) 0x4c, (byte) 0xca, (byte) 0xe2, (byte) 0xda, (byte) 0x13,
+ (byte) 0x43, (byte) 0x0c, (byte) 0x5c, (byte) 0x55, (byte) 0xb5,
+ (byte) 0xca, (byte) 0x5f};
+
+ ECPublicKey alicePublicKey = Curve.decodePoint(alicePublic, 0);
+ ECPrivateKey alicePrivateKey = Curve.decodePrivatePoint(alicePrivate);
+ ECKeyPair aliceKeyPair = new ECKeyPair(alicePublicKey, alicePrivateKey);
+
+ ECPublicKey bobPublicKey = Curve.decodePoint(bobPublic, 0);
+ RootKey rootKey = new RootKey(HKDF.createFor(2), rootKeySeed);
+
+ Pair<RootKey, ChainKey> rootKeyChainKeyPair = rootKey.createChain(bobPublicKey, aliceKeyPair);
+ RootKey nextRootKey = rootKeyChainKeyPair.first();
+ ChainKey nextChainKey = rootKeyChainKeyPair.second();
+
+ assertTrue(Arrays.equals(rootKey.getKeyBytes(), rootKeySeed));
+ assertTrue(Arrays.equals(nextRootKey.getKeyBytes(), nextRoot));
+ assertTrue(Arrays.equals(nextChainKey.getKey(), nextChain));
+ }
+}
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..28d28168
--- /dev/null
+++ b/src/main/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.whispersystems.libaxolotl"
+ android:versionCode="1"
+ android:versionName="0.1">
+ <application />
+</manifest>
diff --git a/src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java b/src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java
new file mode 100644
index 00000000..913c0121
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java
@@ -0,0 +1,7 @@
+package org.whispersystems.libaxolotl;
+
+public class DuplicateMessageException extends Exception {
+ public DuplicateMessageException(String s) {
+ super(s);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/IdentityKey.java b/src/main/java/org/whispersystems/libaxolotl/IdentityKey.java
new file mode 100644
index 00000000..35af3394
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/IdentityKey.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.Hex;
+
+/**
+ * A class for representing an identity key.
+ *
+ * @author Moxie Marlinspike
+ */
+
+public class IdentityKey {
+
+ private final ECPublicKey publicKey;
+
+ public IdentityKey(ECPublicKey publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public IdentityKey(byte[] bytes, int offset) throws InvalidKeyException {
+ this.publicKey = Curve.decodePoint(bytes, offset);
+ }
+
+ public ECPublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ public byte[] serialize() {
+ return publicKey.serialize();
+ }
+
+ public String getFingerprint() {
+ return Hex.toString(publicKey.serialize());
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) return false;
+ if (!(other instanceof IdentityKey)) return false;
+
+ return publicKey.equals(((IdentityKey) other).getPublicKey());
+ }
+
+ @Override
+ public int hashCode() {
+ return publicKey.hashCode();
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java b/src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java
new file mode 100644
index 00000000..c47df4bc
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+
+import static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure;
+
+/**
+ * Holder for public and private identity key pair.
+ *
+ * @author Moxie Marlinspike
+ */
+public class IdentityKeyPair {
+
+ private final IdentityKey publicKey;
+ private final ECPrivateKey privateKey;
+
+ public IdentityKeyPair(IdentityKey publicKey, ECPrivateKey privateKey) {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ public IdentityKeyPair(byte[] serialized) throws InvalidKeyException {
+ try {
+ IdentityKeyPairStructure structure = IdentityKeyPairStructure.parseFrom(serialized);
+ this.publicKey = new IdentityKey(structure.getPublicKey().toByteArray(), 0);
+ this.privateKey = Curve.decodePrivatePoint(structure.getPrivateKey().toByteArray());
+ } catch (InvalidProtocolBufferException e) {
+ throw new InvalidKeyException(e);
+ }
+ }
+
+ public IdentityKey getPublicKey() {
+ return publicKey;
+ }
+
+ public ECPrivateKey getPrivateKey() {
+ return privateKey;
+ }
+
+ public byte[] serialize() {
+ return IdentityKeyPairStructure.newBuilder()
+ .setPublicKey(ByteString.copyFrom(publicKey.serialize()))
+ .setPrivateKey(ByteString.copyFrom(privateKey.serialize()))
+ .build().toByteArray();
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java b/src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java
new file mode 100644
index 00000000..bb70df16
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+public class InvalidKeyException extends Exception {
+
+ public InvalidKeyException() {}
+
+ public InvalidKeyException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public InvalidKeyException(Throwable throwable) {
+ super(throwable);
+ }
+
+ public InvalidKeyException(String detailMessage, Throwable throwable) {
+ super(detailMessage, throwable);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java b/src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java
new file mode 100644
index 00000000..c7c6bc01
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+public class InvalidKeyIdException extends Exception {
+ public InvalidKeyIdException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public InvalidKeyIdException(Throwable throwable) {
+ super(throwable);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java b/src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java
new file mode 100644
index 00000000..0afc6996
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+public class InvalidMacException extends Exception {
+
+ public InvalidMacException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public InvalidMacException(Throwable throwable) {
+ super(throwable);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java b/src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java
new file mode 100644
index 00000000..063eb594
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+import java.util.List;
+
+public class InvalidMessageException extends Exception {
+
+ public InvalidMessageException() {}
+
+ public InvalidMessageException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public InvalidMessageException(Throwable throwable) {
+ super(throwable);
+ }
+
+ public InvalidMessageException(String detailMessage, Throwable throwable) {
+ super(detailMessage, throwable);
+ }
+
+ public InvalidMessageException(String detailMessage, List<Exception> exceptions) {
+ super(detailMessage, exceptions.get(0));
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java b/src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java
new file mode 100644
index 00000000..a1324443
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java
@@ -0,0 +1,23 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+public class InvalidVersionException extends Exception {
+ public InvalidVersionException(String detailMessage) {
+ super(detailMessage);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java b/src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java
new file mode 100644
index 00000000..dadde754
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java
@@ -0,0 +1,7 @@
+package org.whispersystems.libaxolotl;
+
+public class LegacyMessageException extends Exception {
+ public LegacyMessageException(String s) {
+ super(s);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java b/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java
new file mode 100644
index 00000000..16203554
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java
@@ -0,0 +1,11 @@
+package org.whispersystems.libaxolotl;
+
+public class NoSessionException extends Exception {
+ public NoSessionException(String s) {
+ super(s);
+ }
+
+ public NoSessionException(Exception nested) {
+ super(nested);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java b/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java
new file mode 100644
index 00000000..2d1c8969
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java
@@ -0,0 +1,411 @@
+package org.whispersystems.libaxolotl;
+
+import android.util.Log;
+
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
+import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage;
+import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
+import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters;
+import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters;
+import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
+import org.whispersystems.libaxolotl.ratchet.SymmetricAxolotlParameters;
+import org.whispersystems.libaxolotl.state.AxolotlStore;
+import org.whispersystems.libaxolotl.state.IdentityKeyStore;
+import org.whispersystems.libaxolotl.state.PreKeyBundle;
+import org.whispersystems.libaxolotl.state.PreKeyStore;
+import org.whispersystems.libaxolotl.state.SessionRecord;
+import org.whispersystems.libaxolotl.state.SessionState;
+import org.whispersystems.libaxolotl.state.SessionStore;
+import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
+import org.whispersystems.libaxolotl.util.KeyHelper;
+import org.whispersystems.libaxolotl.util.Medium;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+/**
+ * SessionBuilder is responsible for setting up encrypted sessions.
+ * Once a session has been established, {@link org.whispersystems.libaxolotl.SessionCipher}
+ * can be used to encrypt/decrypt messages in that session.
+ * <p>
+ * Sessions are built from one of three different possible vectors:
+ * <ol>
+ * <li>A {@link org.whispersystems.libaxolotl.state.PreKeyBundle} retrieved from a server.</li>
+ * <li>A {@link org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage} received from a client.</li>
+ * <li>A {@link org.whispersystems.libaxolotl.protocol.KeyExchangeMessage} sent to or received from a client.</li>
+ * </ol>
+ *
+ * Sessions are constructed per recipientId + deviceId tuple. Remote logical users are identified
+ * by their recipientId, and each logical recipientId can have multiple physical devices.
+ *
+ * @author Moxie Marlinspike
+ */
+public class SessionBuilder {
+
+ private static final String TAG = SessionBuilder.class.getSimpleName();
+
+ private final SessionStore sessionStore;
+ private final PreKeyStore preKeyStore;
+ private final SignedPreKeyStore signedPreKeyStore;
+ private final IdentityKeyStore identityKeyStore;
+ private final long recipientId;
+ private final int deviceId;
+
+ /**
+ * Constructs a SessionBuilder.
+ *
+ * @param sessionStore The {@link org.whispersystems.libaxolotl.state.SessionStore} to store the constructed session in.
+ * @param preKeyStore The {@link org.whispersystems.libaxolotl.state.PreKeyStore} where the client's local {@link org.whispersystems.libaxolotl.state.PreKeyRecord}s are stored.
+ * @param identityKeyStore The {@link org.whispersystems.libaxolotl.state.IdentityKeyStore} containing the client's identity key information.
+ * @param recipientId The recipient ID of the remote user to build a session with.
+ * @param deviceId The device ID of the remote user's physical device.
+ */
+ public SessionBuilder(SessionStore sessionStore,
+ PreKeyStore preKeyStore,
+ SignedPreKeyStore signedPreKeyStore,
+ IdentityKeyStore identityKeyStore,
+ long recipientId, int deviceId)
+ {
+ this.sessionStore = sessionStore;
+ this.preKeyStore = preKeyStore;
+ this.signedPreKeyStore = signedPreKeyStore;
+ this.identityKeyStore = identityKeyStore;
+ this.recipientId = recipientId;
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * Constructs a SessionBuilder
+ * @param store The {@link org.whispersystems.libaxolotl.state.AxolotlStore} to store all state information in.
+ * @param recipientId The recipient ID of the remote user to build a session with.
+ * @param deviceId The device ID of the remote user's physical device.
+ */
+ public SessionBuilder(AxolotlStore store, long recipientId, int deviceId) {
+ this(store, store, store, store, recipientId, deviceId);
+ }
+
+ /**
+ * Build a new session from a received {@link org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage}.
+ *
+ * After a session is constructed in this way, the embedded {@link org.whispersystems.libaxolotl.protocol.WhisperMessage}
+ * can be decrypted.
+ *
+ * @param message The received {@link org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage}.
+ * @throws org.whispersystems.libaxolotl.InvalidKeyIdException when there is no local
+ * {@link org.whispersystems.libaxolotl.state.PreKeyRecord}
+ * that corresponds to the PreKey ID in
+ * the message.
+ * @throws org.whispersystems.libaxolotl.InvalidKeyException when the message is formatted incorrectly.
+ * @throws org.whispersystems.libaxolotl.UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
+ */
+ /*package*/ Optional<Integer> process(SessionRecord sessionRecord, PreKeyWhisperMessage message)
+ throws InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
+ {
+ int messageVersion = message.getMessageVersion();
+ IdentityKey theirIdentityKey = message.getIdentityKey();
+
+ Optional<Integer> unsignedPreKeyId;
+
+ if (!identityKeyStore.isTrustedIdentity(recipientId, theirIdentityKey)) {
+ throw new UntrustedIdentityException();
+ }
+
+ switch (messageVersion) {
+ case 2: unsignedPreKeyId = processV2(sessionRecord, message); break;
+ case 3: unsignedPreKeyId = processV3(sessionRecord, message); break;
+ default: throw new AssertionError("Unknown version: " + messageVersion);
+ }
+
+ identityKeyStore.saveIdentity(recipientId, theirIdentityKey);
+ return unsignedPreKeyId;
+ }
+
+ private Optional<Integer> processV3(SessionRecord sessionRecord, PreKeyWhisperMessage message)
+ throws UntrustedIdentityException, InvalidKeyIdException, InvalidKeyException
+ {
+
+ if (sessionRecord.hasSessionState(message.getMessageVersion(), message.getBaseKey().serialize())) {
+ Log.w(TAG, "We've already setup a session for this V3 message, letting bundled message fall through...");
+ return Optional.absent();
+ }
+
+ ECKeyPair ourSignedPreKey = signedPreKeyStore.loadSignedPreKey(message.getSignedPreKeyId()).getKeyPair();
+
+ BobAxolotlParameters.Builder parameters = BobAxolotlParameters.newBuilder();
+
+ parameters.setTheirBaseKey(message.getBaseKey())
+ .setTheirIdentityKey(message.getIdentityKey())
+ .setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
+ .setOurSignedPreKey(ourSignedPreKey)
+ .setOurRatchetKey(ourSignedPreKey);
+
+ if (message.getPreKeyId().isPresent()) {
+ parameters.setOurOneTimePreKey(Optional.of(preKeyStore.loadPreKey(message.getPreKeyId().get()).getKeyPair()));
+ } else {
+ parameters.setOurOneTimePreKey(Optional.<ECKeyPair>absent());
+ }
+
+ if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(), message.getMessageVersion(), parameters.create());
+
+ sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.getLocalRegistrationId());
+ sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId());
+ sessionRecord.getSessionState().setAliceBaseKey(message.getBaseKey().serialize());
+
+ if (message.getPreKeyId().isPresent() && message.getPreKeyId().get() != Medium.MAX_VALUE) {
+ return message.getPreKeyId();
+ } else {
+ return Optional.absent();
+ }
+ }
+
+ private Optional<Integer> processV2(SessionRecord sessionRecord, PreKeyWhisperMessage message)
+ throws UntrustedIdentityException, InvalidKeyIdException, InvalidKeyException
+ {
+ if (!message.getPreKeyId().isPresent()) {
+ throw new InvalidKeyIdException("V2 message requires one time prekey id!");
+ }
+
+ if (!preKeyStore.containsPreKey(message.getPreKeyId().get()) &&
+ sessionStore.containsSession(recipientId, deviceId))
+ {
+ Log.w(TAG, "We've already processed the prekey part of this V2 session, letting bundled message fall through...");
+ return Optional.absent();
+ }
+
+ ECKeyPair ourPreKey = preKeyStore.loadPreKey(message.getPreKeyId().get()).getKeyPair();
+
+ BobAxolotlParameters.Builder parameters = BobAxolotlParameters.newBuilder();
+
+ parameters.setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
+ .setOurSignedPreKey(ourPreKey)
+ .setOurRatchetKey(ourPreKey)
+ .setOurOneTimePreKey(Optional.<ECKeyPair>absent())
+ .setTheirIdentityKey(message.getIdentityKey())
+ .setTheirBaseKey(message.getBaseKey());
+
+ if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(), message.getMessageVersion(), parameters.create());
+
+ sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.getLocalRegistrationId());
+ sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId());
+ sessionRecord.getSessionState().setAliceBaseKey(message.getBaseKey().serialize());
+
+ if (message.getPreKeyId().get() != Medium.MAX_VALUE) {
+ return message.getPreKeyId();
+ } else {
+ return Optional.absent();
+ }
+ }
+
+ /**
+ * Build a new session from a {@link org.whispersystems.libaxolotl.state.PreKeyBundle} retrieved from
+ * a server.
+ *
+ * @param preKey A PreKey for the destination recipient, retrieved from a server.
+ * @throws InvalidKeyException when the {@link org.whispersystems.libaxolotl.state.PreKeyBundle} is
+ * badly formatted.
+ * @throws org.whispersystems.libaxolotl.UntrustedIdentityException when the sender's
+ * {@link IdentityKey} is not
+ * trusted.
+ */
+ public void process(PreKeyBundle preKey) throws InvalidKeyException, UntrustedIdentityException {
+ synchronized (SessionCipher.SESSION_LOCK) {
+ if (!identityKeyStore.isTrustedIdentity(recipientId, preKey.getIdentityKey())) {
+ throw new UntrustedIdentityException();
+ }
+
+ if (preKey.getSignedPreKey() != null &&
+ !Curve.verifySignature(preKey.getIdentityKey().getPublicKey(),
+ preKey.getSignedPreKey().serialize(),
+ preKey.getSignedPreKeySignature()))
+ {
+ throw new InvalidKeyException("Invalid signature on device key!");
+ }
+
+ if (preKey.getSignedPreKey() == null && preKey.getPreKey() == null) {
+ throw new InvalidKeyException("Both signed and unsigned prekeys are absent!");
+ }
+
+ boolean supportsV3 = preKey.getSignedPreKey() != null;
+ SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
+ ECKeyPair ourBaseKey = Curve.generateKeyPair();
+ ECPublicKey theirSignedPreKey = supportsV3 ? preKey.getSignedPreKey() : preKey.getPreKey();
+ Optional<ECPublicKey> theirOneTimePreKey = Optional.fromNullable(preKey.getPreKey());
+ Optional<Integer> theirOneTimePreKeyId = theirOneTimePreKey.isPresent() ? Optional.of(preKey.getPreKeyId()) :
+ Optional.<Integer>absent();
+
+ AliceAxolotlParameters.Builder parameters = AliceAxolotlParameters.newBuilder();
+
+ parameters.setOurBaseKey(ourBaseKey)
+ .setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
+ .setTheirIdentityKey(preKey.getIdentityKey())
+ .setTheirSignedPreKey(theirSignedPreKey)
+ .setTheirRatchetKey(theirSignedPreKey)
+ .setTheirOneTimePreKey(supportsV3 ? theirOneTimePreKey : Optional.<ECPublicKey>absent());
+
+ if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(),
+ supportsV3 ? 3 : 2,
+ parameters.create());
+
+ sessionRecord.getSessionState().setUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey());
+ sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.getLocalRegistrationId());
+ sessionRecord.getSessionState().setRemoteRegistrationId(preKey.getRegistrationId());
+ sessionRecord.getSessionState().setAliceBaseKey(ourBaseKey.getPublicKey().serialize());
+
+ sessionStore.storeSession(recipientId, deviceId, sessionRecord);
+ identityKeyStore.saveIdentity(recipientId, preKey.getIdentityKey());
+ }
+ }
+
+ /**
+ * Build a new session from a {@link org.whispersystems.libaxolotl.protocol.KeyExchangeMessage}
+ * received from a remote client.
+ *
+ * @param message The received KeyExchangeMessage.
+ * @return The KeyExchangeMessage to respond with, or null if no response is necessary.
+ * @throws InvalidKeyException if the received KeyExchangeMessage is badly formatted.
+ */
+ public KeyExchangeMessage process(KeyExchangeMessage message)
+ throws InvalidKeyException, UntrustedIdentityException, StaleKeyExchangeException
+ {
+ synchronized (SessionCipher.SESSION_LOCK) {
+ if (!identityKeyStore.isTrustedIdentity(recipientId, message.getIdentityKey())) {
+ throw new UntrustedIdentityException();
+ }
+
+ KeyExchangeMessage responseMessage = null;
+
+ if (message.isInitiate()) responseMessage = processInitiate(message);
+ else processResponse(message);
+
+ return responseMessage;
+ }
+ }
+
+ private KeyExchangeMessage processInitiate(KeyExchangeMessage message) throws InvalidKeyException {
+ int flags = KeyExchangeMessage.RESPONSE_FLAG;
+ SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
+
+ if (message.getVersion() >= 3 &&
+ !Curve.verifySignature(message.getIdentityKey().getPublicKey(),
+ message.getBaseKey().serialize(),
+ message.getBaseKeySignature()))
+ {
+ throw new InvalidKeyException("Bad signature!");
+ }
+
+ SymmetricAxolotlParameters.Builder builder = SymmetricAxolotlParameters.newBuilder();
+
+ if (!sessionRecord.getSessionState().hasPendingKeyExchange()) {
+ builder.setOurIdentityKey(identityKeyStore.getIdentityKeyPair())
+ .setOurBaseKey(Curve.generateKeyPair())
+ .setOurRatchetKey(Curve.generateKeyPair());
+ } else {
+ builder.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())
+ .setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())
+ .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey());
+ flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG;
+ }
+
+ builder.setTheirBaseKey(message.getBaseKey())
+ .setTheirRatchetKey(message.getRatchetKey())
+ .setTheirIdentityKey(message.getIdentityKey());
+
+ SymmetricAxolotlParameters parameters = builder.create();
+
+ if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(),
+ Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION),
+ parameters);
+
+ sessionStore.storeSession(recipientId, deviceId, sessionRecord);
+ identityKeyStore.saveIdentity(recipientId, message.getIdentityKey());
+
+ byte[] baseKeySignature = Curve.calculateSignature(parameters.getOurIdentityKey().getPrivateKey(),
+ parameters.getOurBaseKey().getPublicKey().serialize());
+
+ return new KeyExchangeMessage(sessionRecord.getSessionState().getSessionVersion(),
+ message.getSequence(), flags,
+ parameters.getOurBaseKey().getPublicKey(),
+ baseKeySignature, parameters.getOurRatchetKey().getPublicKey(),
+ parameters.getOurIdentityKey().getPublicKey());
+ }
+
+ private void processResponse(KeyExchangeMessage message)
+ throws StaleKeyExchangeException, InvalidKeyException
+ {
+ SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
+ SessionState sessionState = sessionRecord.getSessionState();
+ boolean hasPendingKeyExchange = sessionState.hasPendingKeyExchange();
+ boolean isSimultaneousInitiateResponse = message.isResponseForSimultaneousInitiate();
+
+ if (!hasPendingKeyExchange || sessionState.getPendingKeyExchangeSequence() != message.getSequence()) {
+ Log.w(TAG, "No matching sequence for response. Is simultaneous initiate response: " + isSimultaneousInitiateResponse);
+ if (!isSimultaneousInitiateResponse) throw new StaleKeyExchangeException();
+ else return;
+ }
+
+ SymmetricAxolotlParameters.Builder parameters = SymmetricAxolotlParameters.newBuilder();
+
+ parameters.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())
+ .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey())
+ .setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())
+ .setTheirBaseKey(message.getBaseKey())
+ .setTheirRatchetKey(message.getRatchetKey())
+ .setTheirIdentityKey(message.getIdentityKey());
+
+ if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(),
+ Math.min(message.getMaxVersion(), CiphertextMessage.CURRENT_VERSION),
+ parameters.create());
+
+ if (sessionRecord.getSessionState().getSessionVersion() >= 3 &&
+ !Curve.verifySignature(message.getIdentityKey().getPublicKey(),
+ message.getBaseKey().serialize(),
+ message.getBaseKeySignature()))
+ {
+ throw new InvalidKeyException("Base key signature doesn't match!");
+ }
+
+ sessionStore.storeSession(recipientId, deviceId, sessionRecord);
+ identityKeyStore.saveIdentity(recipientId, message.getIdentityKey());
+
+ }
+
+ /**
+ * Initiate a new session by sending an initial KeyExchangeMessage to the recipient.
+ *
+ * @return the KeyExchangeMessage to deliver.
+ */
+ public KeyExchangeMessage process() {
+ synchronized (SessionCipher.SESSION_LOCK) {
+ try {
+ int sequence = KeyHelper.getRandomSequence(65534) + 1;
+ int flags = KeyExchangeMessage.INITIATE_FLAG;
+ ECKeyPair baseKey = Curve.generateKeyPair();
+ ECKeyPair ratchetKey = Curve.generateKeyPair();
+ IdentityKeyPair identityKey = identityKeyStore.getIdentityKeyPair();
+ byte[] baseKeySignature = Curve.calculateSignature(identityKey.getPrivateKey(), baseKey.getPublicKey().serialize());
+ SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
+
+ sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ratchetKey, identityKey);
+ sessionStore.storeSession(recipientId, deviceId, sessionRecord);
+
+ return new KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), baseKeySignature,
+ ratchetKey.getPublicKey(), identityKey.getPublicKey());
+ } catch (InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java b/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java
new file mode 100644
index 00000000..381dedb8
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java
@@ -0,0 +1,469 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl;
+
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
+import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
+import org.whispersystems.libaxolotl.protocol.WhisperMessage;
+import org.whispersystems.libaxolotl.ratchet.ChainKey;
+import org.whispersystems.libaxolotl.ratchet.MessageKeys;
+import org.whispersystems.libaxolotl.ratchet.RootKey;
+import org.whispersystems.libaxolotl.state.AxolotlStore;
+import org.whispersystems.libaxolotl.state.IdentityKeyStore;
+import org.whispersystems.libaxolotl.state.PreKeyStore;
+import org.whispersystems.libaxolotl.state.SessionRecord;
+import org.whispersystems.libaxolotl.state.SessionState;
+import org.whispersystems.libaxolotl.state.SessionStore;
+import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+import org.whispersystems.libaxolotl.util.Pair;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import static org.whispersystems.libaxolotl.state.SessionState.UnacknowledgedPreKeyMessageItems;
+
+/**
+ * The main entry point for Axolotl encrypt/decrypt operations.
+ *
+ * Once a session has been established with {@link SessionBuilder},
+ * this class can be used for all encrypt/decrypt operations within
+ * that session.
+ *
+ * @author Moxie Marlinspike
+ */
+public class SessionCipher {
+
+ public static final Object SESSION_LOCK = new Object();
+
+ private final SessionStore sessionStore;
+ private final SessionBuilder sessionBuilder;
+ private final PreKeyStore preKeyStore;
+ private final long recipientId;
+ private final int deviceId;
+
+ /**
+ * Construct a SessionCipher for encrypt/decrypt operations on a session.
+ * In order to use SessionCipher, a session must have already been created
+ * and stored using {@link SessionBuilder}.
+ *
+ * @param sessionStore The {@link SessionStore} that contains a session for this recipient.
+ * @param recipientId The remote ID that messages will be encrypted to or decrypted from.
+ * @param deviceId The device corresponding to the recipientId.
+ */
+ public SessionCipher(SessionStore sessionStore, PreKeyStore preKeyStore,
+ SignedPreKeyStore signedPreKeyStore, IdentityKeyStore identityKeyStore,
+ long recipientId, int deviceId)
+ {
+ this.sessionStore = sessionStore;
+ this.recipientId = recipientId;
+ this.deviceId = deviceId;
+ this.preKeyStore = preKeyStore;
+ this.sessionBuilder = new SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
+ identityKeyStore, recipientId, deviceId);
+ }
+
+ public SessionCipher(AxolotlStore store, long recipientId, int deviceId) {
+ this(store, store, store, store, recipientId, deviceId);
+ }
+
+ /**
+ * Encrypt a message.
+ *
+ * @param paddedMessage The plaintext message bytes, optionally padded to a constant multiple.
+ * @return A ciphertext message encrypted to the recipient+device tuple.
+ */
+ public CiphertextMessage encrypt(byte[] paddedMessage) {
+ synchronized (SESSION_LOCK) {
+ SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
+ SessionState sessionState = sessionRecord.getSessionState();
+ ChainKey chainKey = sessionState.getSenderChainKey();
+ MessageKeys messageKeys = chainKey.getMessageKeys();
+ ECPublicKey senderEphemeral = sessionState.getSenderRatchetKey();
+ int previousCounter = sessionState.getPreviousCounter();
+ int sessionVersion = sessionState.getSessionVersion();
+
+ byte[] ciphertextBody = getCiphertext(sessionVersion, messageKeys, paddedMessage);
+ CiphertextMessage ciphertextMessage = new WhisperMessage(sessionVersion, messageKeys.getMacKey(),
+ senderEphemeral, chainKey.getIndex(),
+ previousCounter, ciphertextBody,
+ sessionState.getLocalIdentityKey(),
+ sessionState.getRemoteIdentityKey());
+
+ if (sessionState.hasUnacknowledgedPreKeyMessage()) {
+ UnacknowledgedPreKeyMessageItems items = sessionState.getUnacknowledgedPreKeyMessageItems();
+ int localRegistrationId = sessionState.getLocalRegistrationId();
+
+ ciphertextMessage = new PreKeyWhisperMessage(sessionVersion, localRegistrationId, items.getPreKeyId(),
+ items.getSignedPreKeyId(), items.getBaseKey(),
+ sessionState.getLocalIdentityKey(),
+ (WhisperMessage) ciphertextMessage);
+ }
+
+ sessionState.setSenderChainKey(chainKey.getNextChainKey());
+ sessionStore.storeSession(recipientId, deviceId, sessionRecord);
+ return ciphertextMessage;
+ }
+ }
+
+ /**
+ * Decrypt a message.
+ *
+ * @param ciphertext The {@link PreKeyWhisperMessage} to decrypt.
+ *
+ * @return The plaintext.
+ * @throws InvalidMessageException if the input is not valid ciphertext.
+ * @throws DuplicateMessageException if the input is a message that has already been received.
+ * @throws LegacyMessageException if the input is a message formatted by a protocol version that
+ * is no longer supported.
+ * @throws InvalidKeyIdException when there is no local {@link org.whispersystems.libaxolotl.state.PreKeyRecord}
+ * that corresponds to the PreKey ID in the message.
+ * @throws InvalidKeyException when the message is formatted incorrectly.
+ * @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
+ */
+ public byte[] decrypt(PreKeyWhisperMessage ciphertext)
+ throws DuplicateMessageException, LegacyMessageException, InvalidMessageException,
+ InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
+ {
+ return decrypt(ciphertext, new NullDecryptionCallback());
+ }
+
+ /**
+ * Decrypt a message.
+ *
+ * @param ciphertext The {@link PreKeyWhisperMessage} to decrypt.
+ * @param callback A callback that is triggered after decryption is complete,
+ * but before the updated session state has been committed to the session
+ * DB. This allows some implementations to store the committed plaintext
+ * to a DB first, in case they are concerned with a crash happening between
+ * the time the session state is updated but before they're able to store
+ * the plaintext to disk.
+ *
+ * @return The plaintext.
+ * @throws InvalidMessageException if the input is not valid ciphertext.
+ * @throws DuplicateMessageException if the input is a message that has already been received.
+ * @throws LegacyMessageException if the input is a message formatted by a protocol version that
+ * is no longer supported.
+ * @throws InvalidKeyIdException when there is no local {@link org.whispersystems.libaxolotl.state.PreKeyRecord}
+ * that corresponds to the PreKey ID in the message.
+ * @throws InvalidKeyException when the message is formatted incorrectly.
+ * @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
+ */
+ public byte[] decrypt(PreKeyWhisperMessage ciphertext, DecryptionCallback callback)
+ throws DuplicateMessageException, LegacyMessageException, InvalidMessageException,
+ InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
+ {
+ synchronized (SESSION_LOCK) {
+ SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
+ Optional<Integer> unsignedPreKeyId = sessionBuilder.process(sessionRecord, ciphertext);
+ byte[] plaintext = decrypt(sessionRecord, ciphertext.getWhisperMessage());
+
+ callback.handlePlaintext(plaintext);
+
+ sessionStore.storeSession(recipientId, deviceId, sessionRecord);
+
+ if (unsignedPreKeyId.isPresent()) {
+ preKeyStore.removePreKey(unsignedPreKeyId.get());
+ }
+
+ return plaintext;
+ }
+ }
+
+ /**
+ * Decrypt a message.
+ *
+ * @param ciphertext The {@link WhisperMessage} to decrypt.
+ *
+ * @return The plaintext.
+ * @throws InvalidMessageException if the input is not valid ciphertext.
+ * @throws DuplicateMessageException if the input is a message that has already been received.
+ * @throws LegacyMessageException if the input is a message formatted by a protocol version that
+ * is no longer supported.
+ * @throws NoSessionException if there is no established session for this contact.
+ */
+ public byte[] decrypt(WhisperMessage ciphertext)
+ throws InvalidMessageException, DuplicateMessageException, LegacyMessageException,
+ NoSessionException
+ {
+ return decrypt(ciphertext, new NullDecryptionCallback());
+ }
+
+ /**
+ * Decrypt a message.
+ *
+ * @param ciphertext The {@link WhisperMessage} to decrypt.
+ * @param callback A callback that is triggered after decryption is complete,
+ * but before the updated session state has been committed to the session
+ * DB. This allows some implementations to store the committed plaintext
+ * to a DB first, in case they are concerned with a crash happening between
+ * the time the session state is updated but before they're able to store
+ * the plaintext to disk.
+ *
+ * @return The plaintext.
+ * @throws InvalidMessageException if the input is not valid ciphertext.
+ * @throws DuplicateMessageException if the input is a message that has already been received.
+ * @throws LegacyMessageException if the input is a message formatted by a protocol version that
+ * is no longer supported.
+ * @throws NoSessionException if there is no established session for this contact.
+ */
+ public byte[] decrypt(WhisperMessage ciphertext, DecryptionCallback callback)
+ throws InvalidMessageException, DuplicateMessageException, LegacyMessageException,
+ NoSessionException
+ {
+ synchronized (SESSION_LOCK) {
+
+ if (!sessionStore.containsSession(recipientId, deviceId)) {
+ throw new NoSessionException("No session for: " + recipientId + ", " + deviceId);
+ }
+
+ SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId);
+ byte[] plaintext = decrypt(sessionRecord, ciphertext);
+
+ callback.handlePlaintext(plaintext);
+
+ sessionStore.storeSession(recipientId, deviceId, sessionRecord);
+
+ return plaintext;
+ }
+ }
+
+ private byte[] decrypt(SessionRecord sessionRecord, WhisperMessage ciphertext)
+ throws DuplicateMessageException, LegacyMessageException, InvalidMessageException
+ {
+ synchronized (SESSION_LOCK) {
+ Iterator<SessionState> previousStates = sessionRecord.getPreviousSessionStates().iterator();
+ List<Exception> exceptions = new LinkedList<>();
+
+ try {
+ SessionState sessionState = new SessionState(sessionRecord.getSessionState());
+ byte[] plaintext = decrypt(sessionState, ciphertext);
+
+ sessionRecord.setState(sessionState);
+ return plaintext;
+ } catch (InvalidMessageException e) {
+ exceptions.add(e);
+ }
+
+ while (previousStates.hasNext()) {
+ try {
+ SessionState promotedState = new SessionState(previousStates.next());
+ byte[] plaintext = decrypt(promotedState, ciphertext);
+
+ previousStates.remove();
+ sessionRecord.promoteState(promotedState);
+
+ return plaintext;
+ } catch (InvalidMessageException e) {
+ exceptions.add(e);
+ }
+ }
+
+ throw new InvalidMessageException("No valid sessions.", exceptions);
+ }
+ }
+
+ private byte[] decrypt(SessionState sessionState, WhisperMessage ciphertextMessage)
+ throws InvalidMessageException, DuplicateMessageException, LegacyMessageException
+ {
+ if (!sessionState.hasSenderChain()) {
+ throw new InvalidMessageException("Uninitialized session!");
+ }
+
+ if (ciphertextMessage.getMessageVersion() != sessionState.getSessionVersion()) {
+ throw new InvalidMessageException(String.format("Message version %d, but session version %d",
+ ciphertextMessage.getMessageVersion(),
+ sessionState.getSessionVersion()));
+ }
+
+ int messageVersion = ciphertextMessage.getMessageVersion();
+ ECPublicKey theirEphemeral = ciphertextMessage.getSenderRatchetKey();
+ int counter = ciphertextMessage.getCounter();
+ ChainKey chainKey = getOrCreateChainKey(sessionState, theirEphemeral);
+ MessageKeys messageKeys = getOrCreateMessageKeys(sessionState, theirEphemeral,
+ chainKey, counter);
+
+ ciphertextMessage.verifyMac(messageVersion,
+ sessionState.getRemoteIdentityKey(),
+ sessionState.getLocalIdentityKey(),
+ messageKeys.getMacKey());
+
+ byte[] plaintext = getPlaintext(messageVersion, messageKeys, ciphertextMessage.getBody());
+
+ sessionState.clearUnacknowledgedPreKeyMessage();
+
+ return plaintext;
+ }
+
+ public int getRemoteRegistrationId() {
+ synchronized (SESSION_LOCK) {
+ SessionRecord record = sessionStore.loadSession(recipientId, deviceId);
+ return record.getSessionState().getRemoteRegistrationId();
+ }
+ }
+
+ public int getSessionVersion() {
+ synchronized (SESSION_LOCK) {
+ if (!sessionStore.containsSession(recipientId, deviceId)) {
+ throw new IllegalStateException(String.format("No session for (%d, %d)!", recipientId, deviceId));
+ }
+
+ SessionRecord record = sessionStore.loadSession(recipientId, deviceId);
+ return record.getSessionState().getSessionVersion();
+ }
+ }
+
+ private ChainKey getOrCreateChainKey(SessionState sessionState, ECPublicKey theirEphemeral)
+ throws InvalidMessageException
+ {
+ try {
+ if (sessionState.hasReceiverChain(theirEphemeral)) {
+ return sessionState.getReceiverChainKey(theirEphemeral);
+ } else {
+ RootKey rootKey = sessionState.getRootKey();
+ ECKeyPair ourEphemeral = sessionState.getSenderRatchetKeyPair();
+ Pair<RootKey, ChainKey> receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral);
+ ECKeyPair ourNewEphemeral = Curve.generateKeyPair();
+ Pair<RootKey, ChainKey> senderChain = receiverChain.first().createChain(theirEphemeral, ourNewEphemeral);
+
+ sessionState.setRootKey(senderChain.first());
+ sessionState.addReceiverChain(theirEphemeral, receiverChain.second());
+ sessionState.setPreviousCounter(Math.max(sessionState.getSenderChainKey().getIndex()-1, 0));
+ sessionState.setSenderChain(ourNewEphemeral, senderChain.second());
+
+ return receiverChain.second();
+ }
+ } catch (InvalidKeyException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ private MessageKeys getOrCreateMessageKeys(SessionState sessionState,
+ ECPublicKey theirEphemeral,
+ ChainKey chainKey, int counter)
+ throws InvalidMessageException, DuplicateMessageException
+ {
+ if (chainKey.getIndex() > counter) {
+ if (sessionState.hasMessageKeys(theirEphemeral, counter)) {
+ return sessionState.removeMessageKeys(theirEphemeral, counter);
+ } else {
+ throw new DuplicateMessageException("Received message with old counter: " +
+ chainKey.getIndex() + " , " + counter);
+ }
+ }
+
+ if (counter - chainKey.getIndex() > 2000) {
+ throw new InvalidMessageException("Over 2000 messages into the future!");
+ }
+
+ while (chainKey.getIndex() < counter) {
+ MessageKeys messageKeys = chainKey.getMessageKeys();
+ sessionState.setMessageKeys(theirEphemeral, messageKeys);
+ chainKey = chainKey.getNextChainKey();
+ }
+
+ sessionState.setReceiverChainKey(theirEphemeral, chainKey.getNextChainKey());
+ return chainKey.getMessageKeys();
+ }
+
+ private byte[] getCiphertext(int version, MessageKeys messageKeys, byte[] plaintext) {
+ try {
+ Cipher cipher;
+
+ if (version >= 3) {
+ cipher = getCipher(Cipher.ENCRYPT_MODE, messageKeys.getCipherKey(), messageKeys.getIv());
+ } else {
+ cipher = getCipher(Cipher.ENCRYPT_MODE, messageKeys.getCipherKey(), messageKeys.getCounter());
+ }
+
+ return cipher.doFinal(plaintext);
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private byte[] getPlaintext(int version, MessageKeys messageKeys, byte[] cipherText)
+ throws InvalidMessageException
+ {
+ try {
+ Cipher cipher;
+
+ if (version >= 3) {
+ cipher = getCipher(Cipher.DECRYPT_MODE, messageKeys.getCipherKey(), messageKeys.getIv());
+ } else {
+ cipher = getCipher(Cipher.DECRYPT_MODE, messageKeys.getCipherKey(), messageKeys.getCounter());
+ }
+
+ return cipher.doFinal(cipherText);
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ private Cipher getCipher(int mode, SecretKeySpec key, int counter) {
+ try {
+ Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
+
+ byte[] ivBytes = new byte[16];
+ ByteUtil.intToByteArray(ivBytes, 0, counter);
+
+ IvParameterSpec iv = new IvParameterSpec(ivBytes);
+ cipher.init(mode, key, iv);
+
+ return cipher;
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | java.security.InvalidKeyException |
+ InvalidAlgorithmParameterException e)
+ {
+ throw new AssertionError(e);
+ }
+ }
+
+ private Cipher getCipher(int mode, SecretKeySpec key, IvParameterSpec iv) {
+ try {
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ cipher.init(mode, key, iv);
+ return cipher;
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | java.security.InvalidKeyException |
+ InvalidAlgorithmParameterException e)
+ {
+ throw new AssertionError(e);
+ }
+ }
+
+ public static interface DecryptionCallback {
+ public void handlePlaintext(byte[] plaintext);
+ }
+
+ private static class NullDecryptionCallback implements DecryptionCallback {
+ @Override
+ public void handlePlaintext(byte[] plaintext) {}
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java b/src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java
new file mode 100644
index 00000000..f94a3008
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java
@@ -0,0 +1,4 @@
+package org.whispersystems.libaxolotl;
+
+public class StaleKeyExchangeException extends Throwable {
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java b/src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java
new file mode 100644
index 00000000..f434b923
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java
@@ -0,0 +1,4 @@
+package org.whispersystems.libaxolotl;
+
+public class UntrustedIdentityException extends Exception {
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java
new file mode 100644
index 00000000..66b8cc3a
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.ecc;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+
+public class Curve {
+
+ public static final int DJB_TYPE = 0x05;
+
+ public static ECKeyPair generateKeyPair() {
+ return Curve25519.generateKeyPair();
+ }
+
+ public static ECPublicKey decodePoint(byte[] bytes, int offset)
+ throws InvalidKeyException
+ {
+ int type = bytes[offset];
+
+ if (type == DJB_TYPE) {
+ return Curve25519.decodePoint(bytes, offset);
+ } else {
+ throw new InvalidKeyException("Unknown key type: " + type);
+ }
+ }
+
+ public static ECPrivateKey decodePrivatePoint(byte[] bytes) {
+ return new DjbECPrivateKey(bytes);
+ }
+
+ public static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey)
+ throws InvalidKeyException
+ {
+ if (publicKey.getType() != privateKey.getType()) {
+ throw new InvalidKeyException("Public and private keys must be of the same type!");
+ }
+
+ if (publicKey.getType() == DJB_TYPE) {
+ return Curve25519.calculateAgreement(publicKey, privateKey);
+ } else {
+ throw new InvalidKeyException("Unknown type: " + publicKey.getType());
+ }
+ }
+
+ public static boolean verifySignature(ECPublicKey signingKey, byte[] message, byte[] signature)
+ throws InvalidKeyException
+ {
+ if (signingKey.getType() == DJB_TYPE) {
+ return Curve25519.verifySignature(signingKey, message, signature);
+ } else {
+ throw new InvalidKeyException("Unknown type: " + signingKey.getType());
+ }
+ }
+
+ public static byte[] calculateSignature(ECPrivateKey signingKey, byte[] message)
+ throws InvalidKeyException
+ {
+ if (signingKey.getType() == DJB_TYPE) {
+ return Curve25519.calculateSignature(signingKey, message);
+ } else {
+ throw new InvalidKeyException("Unknown type: " + signingKey.getType());
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java
new file mode 100644
index 00000000..685a4a11
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.ecc;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+public class Curve25519 {
+
+ static {
+ System.loadLibrary("curve25519");
+
+ try {
+ random = SecureRandom.getInstance("SHA1PRNG");
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private static final SecureRandom random;
+
+ private static native byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic);
+ private static native byte[] generatePublicKey(byte[] privateKey);
+ private static native byte[] generatePrivateKey(byte[] random);
+
+ private static native byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message);
+ private static native boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
+
+ public static ECKeyPair generateKeyPair() {
+ byte[] privateKey = generatePrivateKey();
+ byte[] publicKey = generatePublicKey(privateKey);
+
+ return new ECKeyPair(new DjbECPublicKey(publicKey), new DjbECPrivateKey(privateKey));
+ }
+
+ static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey) {
+ return calculateAgreement(((DjbECPrivateKey)privateKey).getPrivateKey(),
+ ((DjbECPublicKey)publicKey).getPublicKey());
+ }
+
+ static byte[] calculateSignature(ECPrivateKey privateKey, byte[] message) {
+ byte[] random = getRandom(64);
+ return calculateSignature(random, ((DjbECPrivateKey)privateKey).getPrivateKey(), message);
+ }
+
+ static boolean verifySignature(ECPublicKey publicKey, byte[] message, byte[] signature) {
+ return verifySignature(((DjbECPublicKey)publicKey).getPublicKey(), message, signature);
+ }
+
+ static ECPublicKey decodePoint(byte[] encoded, int offset)
+ throws InvalidKeyException
+ {
+ int type = encoded[offset] & 0xFF;
+ byte[] keyBytes = new byte[32];
+ System.arraycopy(encoded, offset+1, keyBytes, 0, keyBytes.length);
+
+ if (type != Curve.DJB_TYPE) {
+ throw new InvalidKeyException("Bad key type: " + type);
+ }
+
+ return new DjbECPublicKey(keyBytes);
+ }
+
+ private static byte[] generatePrivateKey() {
+ byte[] privateKey = new byte[32];
+ random.nextBytes(privateKey);
+
+ return generatePrivateKey(privateKey);
+ }
+
+ private static byte[] getRandom(int size) {
+ try {
+ byte[] random = new byte[size];
+ SecureRandom.getInstance("SHA1PRNG").nextBytes(random);
+
+ return random;
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java
new file mode 100644
index 00000000..ecb55b4e
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.ecc;
+
+public class DjbECPrivateKey implements ECPrivateKey {
+
+ private final byte[] privateKey;
+
+ DjbECPrivateKey(byte[] privateKey) {
+ this.privateKey = privateKey;
+ }
+
+ @Override
+ public byte[] serialize() {
+ return privateKey;
+ }
+
+ @Override
+ public int getType() {
+ return Curve.DJB_TYPE;
+ }
+
+ public byte[] getPrivateKey() {
+ return privateKey;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java
new file mode 100644
index 00000000..9f66d439
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.ecc;
+
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+
+public class DjbECPublicKey implements ECPublicKey {
+
+ private final byte[] publicKey;
+
+ DjbECPublicKey(byte[] publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ @Override
+ public byte[] serialize() {
+ byte[] type = {Curve.DJB_TYPE};
+ return ByteUtil.combine(type, publicKey);
+ }
+
+ @Override
+ public int getType() {
+ return Curve.DJB_TYPE;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) return false;
+ if (!(other instanceof DjbECPublicKey)) return false;
+
+ DjbECPublicKey that = (DjbECPublicKey)other;
+ return Arrays.equals(this.publicKey, that.publicKey);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(publicKey);
+ }
+
+ @Override
+ public int compareTo(ECPublicKey another) {
+ return new BigInteger(publicKey).compareTo(new BigInteger(((DjbECPublicKey)another).publicKey));
+ }
+
+ public byte[] getPublicKey() {
+ return publicKey;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java b/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java
new file mode 100644
index 00000000..bcaec927
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.ecc;
+
+public class ECKeyPair {
+
+ private final ECPublicKey publicKey;
+ private final ECPrivateKey privateKey;
+
+ public ECKeyPair(ECPublicKey publicKey, ECPrivateKey privateKey) {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ public ECPublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ public ECPrivateKey getPrivateKey() {
+ return privateKey;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java
new file mode 100644
index 00000000..922057de
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java
@@ -0,0 +1,23 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.ecc;
+
+public interface ECPrivateKey {
+ public byte[] serialize();
+ public int getType();
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java
new file mode 100644
index 00000000..12576807
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.ecc;
+
+public interface ECPublicKey extends Comparable<ECPublicKey> {
+
+ public static final int KEY_SIZE = 33;
+
+ public byte[] serialize();
+
+ public int getType();
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java b/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java
new file mode 100644
index 00000000..43dac752
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java
@@ -0,0 +1,146 @@
+package org.whispersystems.libaxolotl.groups;
+
+import org.whispersystems.libaxolotl.DuplicateMessageException;
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.NoSessionException;
+import org.whispersystems.libaxolotl.groups.ratchet.SenderChainKey;
+import org.whispersystems.libaxolotl.groups.ratchet.SenderMessageKey;
+import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord;
+import org.whispersystems.libaxolotl.groups.state.SenderKeyState;
+import org.whispersystems.libaxolotl.groups.state.SenderKeyStore;
+import org.whispersystems.libaxolotl.protocol.SenderKeyMessage;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class GroupCipher {
+
+ static final Object LOCK = new Object();
+
+ private final SenderKeyStore senderKeyStore;
+ private final String senderKeyId;
+
+ public GroupCipher(SenderKeyStore senderKeyStore, String senderKeyId) {
+ this.senderKeyStore = senderKeyStore;
+ this.senderKeyId = senderKeyId;
+ }
+
+ public byte[] encrypt(byte[] paddedPlaintext) throws NoSessionException {
+ synchronized (LOCK) {
+ try {
+ SenderKeyRecord record = senderKeyStore.loadSenderKey(senderKeyId);
+ SenderKeyState senderKeyState = record.getSenderKeyState();
+ SenderMessageKey senderKey = senderKeyState.getSenderChainKey().getSenderMessageKey();
+ byte[] ciphertext = getCipherText(senderKey.getIv(), senderKey.getCipherKey(), paddedPlaintext);
+
+ SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyState.getKeyId(),
+ senderKey.getIteration(),
+ ciphertext,
+ senderKeyState.getSigningKeyPrivate());
+
+ senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext());
+
+ senderKeyStore.storeSenderKey(senderKeyId, record);
+
+ return senderKeyMessage.serialize();
+ } catch (InvalidKeyIdException e) {
+ throw new NoSessionException(e);
+ }
+ }
+ }
+
+ public byte[] decrypt(byte[] senderKeyMessageBytes)
+ throws LegacyMessageException, InvalidMessageException, DuplicateMessageException
+ {
+ synchronized (LOCK) {
+ try {
+ SenderKeyRecord record = senderKeyStore.loadSenderKey(senderKeyId);
+ SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyMessageBytes);
+ SenderKeyState senderKeyState = record.getSenderKeyState(senderKeyMessage.getKeyId());
+
+ senderKeyMessage.verifySignature(senderKeyState.getSigningKeyPublic());
+
+ SenderMessageKey senderKey = getSenderKey(senderKeyState, senderKeyMessage.getIteration());
+
+ byte[] plaintext = getPlainText(senderKey.getIv(), senderKey.getCipherKey(), senderKeyMessage.getCipherText());
+
+ senderKeyStore.storeSenderKey(senderKeyId, record);
+
+ return plaintext;
+ } catch (org.whispersystems.libaxolotl.InvalidKeyException | InvalidKeyIdException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+ }
+
+ private SenderMessageKey getSenderKey(SenderKeyState senderKeyState, int iteration)
+ throws DuplicateMessageException, InvalidMessageException
+ {
+ SenderChainKey senderChainKey = senderKeyState.getSenderChainKey();
+
+ if (senderChainKey.getIteration() > iteration) {
+ if (senderKeyState.hasSenderMessageKey(iteration)) {
+ return senderKeyState.removeSenderMessageKey(iteration);
+ } else {
+ throw new DuplicateMessageException("Received message with old counter: " +
+ senderChainKey.getIteration() + " , " + iteration);
+ }
+ }
+
+ if (senderChainKey.getIteration() - iteration > 2000) {
+ throw new InvalidMessageException("Over 2000 messages into the future!");
+ }
+
+ while (senderChainKey.getIteration() < iteration) {
+ senderKeyState.addSenderMessageKey(senderChainKey.getSenderMessageKey());
+ senderChainKey = senderChainKey.getNext();
+ }
+
+ senderKeyState.setSenderChainKey(senderChainKey.getNext());
+ return senderChainKey.getSenderMessageKey();
+ }
+
+ private byte[] getPlainText(byte[] iv, byte[] key, byte[] ciphertext)
+ throws InvalidMessageException
+ {
+ try {
+ IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+
+ cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), ivParameterSpec);
+
+ return cipher.doFinal(ciphertext);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | java.security.InvalidKeyException |
+ InvalidAlgorithmParameterException e)
+ {
+ throw new AssertionError(e);
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ private byte[] getCipherText(byte[] iv, byte[] key, byte[] plaintext) {
+ try {
+ IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+
+ cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), ivParameterSpec);
+
+ return cipher.doFinal(plaintext);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException |
+ IllegalBlockSizeException | BadPaddingException | java.security.InvalidKeyException e)
+ {
+ throw new AssertionError(e);
+ }
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java b/src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java
new file mode 100644
index 00000000..8b73484b
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java
@@ -0,0 +1,38 @@
+package org.whispersystems.libaxolotl.groups;
+
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord;
+import org.whispersystems.libaxolotl.groups.state.SenderKeyStore;
+import org.whispersystems.libaxolotl.protocol.SenderKeyDistributionMessage;
+
+public class GroupSessionBuilder {
+
+ private final SenderKeyStore senderKeyStore;
+
+ public GroupSessionBuilder(SenderKeyStore senderKeyStore) {
+ this.senderKeyStore = senderKeyStore;
+ }
+
+ public void process(String sender, SenderKeyDistributionMessage senderKeyDistributionMessage) {
+ synchronized (GroupCipher.LOCK) {
+ SenderKeyRecord senderKeyRecord = senderKeyStore.loadSenderKey(sender);
+ senderKeyRecord.addSenderKeyState(senderKeyDistributionMessage.getId(),
+ senderKeyDistributionMessage.getIteration(),
+ senderKeyDistributionMessage.getChainKey(),
+ senderKeyDistributionMessage.getSignatureKey());
+ senderKeyStore.storeSenderKey(sender, senderKeyRecord);
+ }
+ }
+
+ public SenderKeyDistributionMessage process(String groupId, int keyId, int iteration,
+ byte[] chainKey, ECKeyPair signatureKey)
+ {
+ synchronized (GroupCipher.LOCK) {
+ SenderKeyRecord senderKeyRecord = senderKeyStore.loadSenderKey(groupId);
+ senderKeyRecord.setSenderKeyState(keyId, iteration, chainKey, signatureKey);
+ senderKeyStore.storeSenderKey(groupId, senderKeyRecord);
+
+ return new SenderKeyDistributionMessage(keyId, iteration, chainKey, signatureKey.getPublicKey());
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java b/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java
new file mode 100644
index 00000000..71375923
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java
@@ -0,0 +1,49 @@
+package org.whispersystems.libaxolotl.groups.ratchet;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public class SenderChainKey {
+
+ private static final byte[] MESSAGE_KEY_SEED = {0x01};
+ private static final byte[] CHAIN_KEY_SEED = {0x02};
+
+ private final int iteration;
+ private final byte[] chainKey;
+
+ public SenderChainKey(int iteration, byte[] chainKey) {
+ this.iteration = iteration;
+ this.chainKey = chainKey;
+ }
+
+ public int getIteration() {
+ return iteration;
+ }
+
+ public SenderMessageKey getSenderMessageKey() {
+ return new SenderMessageKey(iteration, getDerivative(MESSAGE_KEY_SEED, chainKey));
+ }
+
+ public SenderChainKey getNext() {
+ return new SenderChainKey(iteration + 1, getDerivative(CHAIN_KEY_SEED, chainKey));
+ }
+
+ public byte[] getSeed() {
+ return chainKey;
+ }
+
+ private byte[] getDerivative(byte[] seed, byte[] key) {
+ try {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(new SecretKeySpec(key, "HmacSHA256"));
+
+ return mac.doFinal(seed);
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java b/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java
new file mode 100644
index 00000000..8808a8e8
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java
@@ -0,0 +1,38 @@
+package org.whispersystems.libaxolotl.groups.ratchet;
+
+import org.whispersystems.libaxolotl.kdf.HKDFv3;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+public class SenderMessageKey {
+
+ private final int iteration;
+ private final byte[] iv;
+ private final byte[] cipherKey;
+ private final byte[] seed;
+
+ public SenderMessageKey(int iteration, byte[] seed) {
+ byte[] derivative = new HKDFv3().deriveSecrets(seed, "WhisperGroup".getBytes(), 48);
+ byte[][] parts = ByteUtil.split(derivative, 16, 32);
+
+ this.iteration = iteration;
+ this.seed = seed;
+ this.iv = parts[0];
+ this.cipherKey = parts[1];
+ }
+
+ public int getIteration() {
+ return iteration;
+ }
+
+ public byte[] getIv() {
+ return iv;
+ }
+
+ public byte[] getCipherKey() {
+ return cipherKey;
+ }
+
+ public byte[] getSeed() {
+ return seed;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java b/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java
new file mode 100644
index 00000000..bb1ba952
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java
@@ -0,0 +1,64 @@
+package org.whispersystems.libaxolotl.groups.state;
+
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.state.StorageProtos;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure;
+
+public class SenderKeyRecord {
+
+ private List<SenderKeyState> senderKeyStates = new LinkedList<>();
+
+ public SenderKeyRecord() {}
+
+ public SenderKeyRecord(byte[] serialized) throws IOException {
+ SenderKeyRecordStructure senderKeyRecordStructure = SenderKeyRecordStructure.parseFrom(serialized);
+
+ for (StorageProtos.SenderKeyStateStructure structure : senderKeyRecordStructure.getSenderKeyStatesList()) {
+ this.senderKeyStates.add(new SenderKeyState(structure));
+ }
+ }
+
+ public SenderKeyState getSenderKeyState() throws InvalidKeyIdException {
+ if (!senderKeyStates.isEmpty()) {
+ return senderKeyStates.get(0);
+ } else {
+ throw new InvalidKeyIdException("No key state in record!");
+ }
+ }
+
+ public SenderKeyState getSenderKeyState(int keyId) throws InvalidKeyIdException {
+ for (SenderKeyState state : senderKeyStates) {
+ if (state.getKeyId() == keyId) {
+ return state;
+ }
+ }
+
+ throw new InvalidKeyIdException("No keys for: " + keyId);
+ }
+
+ public void addSenderKeyState(int id, int iteration, byte[] chainKey, ECPublicKey signatureKey) {
+ senderKeyStates.add(new SenderKeyState(id, iteration, chainKey, signatureKey));
+ }
+
+ public void setSenderKeyState(int id, int iteration, byte[] chainKey, ECKeyPair signatureKey) {
+ senderKeyStates.clear();
+ senderKeyStates.add(new SenderKeyState(id, iteration, chainKey, signatureKey));
+ }
+
+ public byte[] serialize() {
+ SenderKeyRecordStructure.Builder recordStructure = SenderKeyRecordStructure.newBuilder();
+
+ for (SenderKeyState senderKeyState : senderKeyStates) {
+ recordStructure.addSenderKeyStates(senderKeyState.getStructure());
+ }
+
+ return recordStructure.build().toByteArray();
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java b/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java
new file mode 100644
index 00000000..80498ce0
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java
@@ -0,0 +1,144 @@
+package org.whispersystems.libaxolotl.groups.state;
+
+import com.google.protobuf.ByteString;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.groups.ratchet.SenderChainKey;
+import org.whispersystems.libaxolotl.groups.ratchet.SenderMessageKey;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure;
+
+public class SenderKeyState {
+
+ private SenderKeyStateStructure senderKeyStateStructure;
+
+ public SenderKeyState(int id, int iteration, byte[] chainKey, ECPublicKey signatureKey) {
+ this(id, iteration, chainKey, signatureKey, Optional.<ECPrivateKey>absent());
+ }
+
+ public SenderKeyState(int id, int iteration, byte[] chainKey, ECKeyPair signatureKey) {
+ this(id, iteration, chainKey, signatureKey.getPublicKey(), Optional.of(signatureKey.getPrivateKey()));
+ }
+
+ private SenderKeyState(int id, int iteration, byte[] chainKey,
+ ECPublicKey signatureKeyPublic,
+ Optional<ECPrivateKey> signatureKeyPrivate)
+ {
+ SenderKeyStateStructure.SenderChainKey senderChainKeyStructure =
+ SenderKeyStateStructure.SenderChainKey.newBuilder()
+ .setIteration(iteration)
+ .setSeed(ByteString.copyFrom(chainKey))
+ .build();
+
+ SenderKeyStateStructure.SenderSigningKey.Builder signingKeyStructure =
+ SenderKeyStateStructure.SenderSigningKey.newBuilder()
+ .setPublic(ByteString.copyFrom(signatureKeyPublic.serialize()));
+
+ if (signatureKeyPrivate.isPresent()) {
+ signingKeyStructure.setPrivate(ByteString.copyFrom(signatureKeyPrivate.get().serialize()));
+ }
+
+ this.senderKeyStateStructure = SenderKeyStateStructure.newBuilder()
+ .setSenderKeyId(id)
+ .setSenderChainKey(senderChainKeyStructure)
+ .setSenderSigningKey(signingKeyStructure)
+ .build();
+ }
+
+ public SenderKeyState(SenderKeyStateStructure senderKeyStateStructure) {
+ this.senderKeyStateStructure = senderKeyStateStructure;
+ }
+
+ public int getKeyId() {
+ return senderKeyStateStructure.getSenderKeyId();
+ }
+
+ public SenderChainKey getSenderChainKey() {
+ return new SenderChainKey(senderKeyStateStructure.getSenderChainKey().getIteration(),
+ senderKeyStateStructure.getSenderChainKey().getSeed().toByteArray());
+ }
+
+ public void setSenderChainKey(SenderChainKey chainKey) {
+ SenderKeyStateStructure.SenderChainKey senderChainKeyStructure =
+ SenderKeyStateStructure.SenderChainKey.newBuilder()
+ .setIteration(chainKey.getIteration())
+ .setSeed(ByteString.copyFrom(chainKey.getSeed()))
+ .build();
+
+ this.senderKeyStateStructure = senderKeyStateStructure.toBuilder()
+ .setSenderChainKey(senderChainKeyStructure)
+ .build();
+ }
+
+ public ECPublicKey getSigningKeyPublic() throws InvalidKeyException {
+ return Curve.decodePoint(senderKeyStateStructure.getSenderSigningKey()
+ .getPublic()
+ .toByteArray(), 0);
+ }
+
+ public ECPrivateKey getSigningKeyPrivate() {
+ return Curve.decodePrivatePoint(senderKeyStateStructure.getSenderSigningKey()
+ .getPrivate().toByteArray());
+ }
+
+ public boolean hasSenderMessageKey(int iteration) {
+ for (SenderKeyStateStructure.SenderMessageKey senderMessageKey : senderKeyStateStructure.getSenderMessageKeysList()) {
+ if (senderMessageKey.getIteration() == iteration) return true;
+ }
+
+ return false;
+ }
+
+ public void addSenderMessageKey(SenderMessageKey senderMessageKey) {
+ SenderKeyStateStructure.SenderMessageKey senderMessageKeyStructure =
+ SenderKeyStateStructure.SenderMessageKey.newBuilder()
+ .setIteration(senderMessageKey.getIteration())
+ .setSeed(ByteString.copyFrom(senderMessageKey.getSeed()))
+ .build();
+
+ this.senderKeyStateStructure = this.senderKeyStateStructure.toBuilder()
+ .addSenderMessageKeys(senderMessageKeyStructure)
+ .build();
+ }
+
+ public SenderMessageKey removeSenderMessageKey(int iteration) {
+ List<SenderKeyStateStructure.SenderMessageKey> keys = new LinkedList<>(senderKeyStateStructure.getSenderMessageKeysList());
+ Iterator<SenderKeyStateStructure.SenderMessageKey> iterator = keys.iterator();
+
+ SenderKeyStateStructure.SenderMessageKey result = null;
+
+ while (iterator.hasNext()) {
+ SenderKeyStateStructure.SenderMessageKey senderMessageKey = iterator.next();
+
+ if (senderMessageKey.getIteration() == iteration) {
+ result = senderMessageKey;
+ iterator.remove();
+ break;
+ }
+ }
+
+ this.senderKeyStateStructure = this.senderKeyStateStructure.toBuilder()
+ .clearSenderMessageKeys()
+ .addAllSenderMessageKeys(keys)
+ .build();
+
+ if (result != null) {
+ return new SenderMessageKey(result.getIteration(), result.getSeed().toByteArray());
+ } else {
+ return null;
+ }
+ }
+
+ public SenderKeyStateStructure getStructure() {
+ return senderKeyStateStructure;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java b/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java
new file mode 100644
index 00000000..da01b1f3
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java
@@ -0,0 +1,6 @@
+package org.whispersystems.libaxolotl.groups.state;
+
+public interface SenderKeyStore {
+ public void storeSenderKey(String senderKeyId, SenderKeyRecord record);
+ public SenderKeyRecord loadSenderKey(String senderKeyId);
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java b/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java
new file mode 100644
index 00000000..b3f54fb8
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.kdf;
+
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+import java.text.ParseException;
+
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class DerivedMessageSecrets {
+
+ public static final int SIZE = 80;
+ private static final int CIPHER_KEY_LENGTH = 32;
+ private static final int MAC_KEY_LENGTH = 32;
+ private static final int IV_LENGTH = 16;
+
+ private final SecretKeySpec cipherKey;
+ private final SecretKeySpec macKey;
+ private final IvParameterSpec iv;
+
+ public DerivedMessageSecrets(byte[] okm) {
+ try {
+ byte[][] keys = ByteUtil.split(okm, CIPHER_KEY_LENGTH, MAC_KEY_LENGTH, IV_LENGTH);
+
+ this.cipherKey = new SecretKeySpec(keys[0], "AES");
+ this.macKey = new SecretKeySpec(keys[1], "HmacSHA256");
+ this.iv = new IvParameterSpec(keys[2]);
+ } catch (ParseException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public SecretKeySpec getCipherKey() {
+ return cipherKey;
+ }
+
+ public SecretKeySpec getMacKey() {
+ return macKey;
+ }
+
+ public IvParameterSpec getIv() {
+ return iv;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java b/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java
new file mode 100644
index 00000000..82cc541d
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java
@@ -0,0 +1,26 @@
+package org.whispersystems.libaxolotl.kdf;
+
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+public class DerivedRootSecrets {
+
+ public static final int SIZE = 64;
+
+ private final byte[] rootKey;
+ private final byte[] chainKey;
+
+ public DerivedRootSecrets(byte[] okm) {
+ byte[][] keys = ByteUtil.split(okm, 32, 32);
+ this.rootKey = keys[0];
+ this.chainKey = keys[1];
+ }
+
+ public byte[] getRootKey() {
+ return rootKey;
+ }
+
+ public byte[] getChainKey() {
+ return chainKey;
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java b/src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java
new file mode 100644
index 00000000..d190822d
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2013 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.kdf;
+
+import java.io.ByteArrayOutputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public abstract class HKDF {
+
+ private static final int HASH_OUTPUT_SIZE = 32;
+
+ public static HKDF createFor(int messageVersion) {
+ switch (messageVersion) {
+ case 2: return new HKDFv2();
+ case 3: return new HKDFv3();
+ default: throw new AssertionError("Unknown version: " + messageVersion);
+ }
+ }
+
+ public byte[] deriveSecrets(byte[] inputKeyMaterial, byte[] info, int outputLength) {
+ byte[] salt = new byte[HASH_OUTPUT_SIZE];
+ return deriveSecrets(inputKeyMaterial, salt, info, outputLength);
+ }
+
+ public byte[] deriveSecrets(byte[] inputKeyMaterial, byte[] salt, byte[] info, int outputLength) {
+ byte[] prk = extract(salt, inputKeyMaterial);
+ return expand(prk, info, outputLength);
+ }
+
+ private byte[] extract(byte[] salt, byte[] inputKeyMaterial) {
+ try {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(new SecretKeySpec(salt, "HmacSHA256"));
+ return mac.doFinal(inputKeyMaterial);
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private byte[] expand(byte[] prk, byte[] info, int outputSize) {
+ try {
+ int iterations = (int) Math.ceil((double) outputSize / (double) HASH_OUTPUT_SIZE);
+ byte[] mixin = new byte[0];
+ ByteArrayOutputStream results = new ByteArrayOutputStream();
+ int remainingBytes = outputSize;
+
+ for (int i= getIterationStartOffset();i<iterations + getIterationStartOffset();i++) {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(new SecretKeySpec(prk, "HmacSHA256"));
+
+ mac.update(mixin);
+ if (info != null) {
+ mac.update(info);
+ }
+ mac.update((byte)i);
+
+ byte[] stepResult = mac.doFinal();
+ int stepSize = Math.min(remainingBytes, stepResult.length);
+
+ results.write(stepResult, 0, stepSize);
+
+ mixin = stepResult;
+ remainingBytes -= stepSize;
+ }
+
+ return results.toByteArray();
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ protected abstract int getIterationStartOffset();
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java b/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java
new file mode 100644
index 00000000..86e4bf5f
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java
@@ -0,0 +1,8 @@
+package org.whispersystems.libaxolotl.kdf;
+
+public class HKDFv2 extends HKDF {
+ @Override
+ protected int getIterationStartOffset() {
+ return 0;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java b/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java
new file mode 100644
index 00000000..a1934c90
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java
@@ -0,0 +1,8 @@
+package org.whispersystems.libaxolotl.kdf;
+
+public class HKDFv3 extends HKDF {
+ @Override
+ protected int getIterationStartOffset() {
+ return 1;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java b/src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java
new file mode 100644
index 00000000..cf4be756
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.protocol;
+
+public interface CiphertextMessage {
+
+ public static final int UNSUPPORTED_VERSION = 1;
+ public static final int CURRENT_VERSION = 3;
+
+ public static final int WHISPER_TYPE = 2;
+ public static final int PREKEY_TYPE = 3;
+ public static final int SENDERKEY_TYPE = 4;
+ public static final int SENDERKEY_DISTRIBUTION_TYPE = 5;
+
+ // This should be the worst case (worse than V2). So not always accurate, but good enough for padding.
+ public static final int ENCRYPTED_MESSAGE_OVERHEAD = 53;
+
+ public byte[] serialize();
+ public int getType();
+
+} \ No newline at end of file
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java b/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java
new file mode 100644
index 00000000..bec9208c
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java
@@ -0,0 +1,153 @@
+package org.whispersystems.libaxolotl.protocol;
+
+
+import com.google.protobuf.ByteString;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.InvalidVersionException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+import java.io.IOException;
+
+import static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.Builder;
+
+public class KeyExchangeMessage {
+
+ public static final int INITIATE_FLAG = 0x01;
+ public static final int RESPONSE_FLAG = 0X02;
+ public static final int SIMULTAENOUS_INITIATE_FLAG = 0x04;
+
+ private final int version;
+ private final int supportedVersion;
+ private final int sequence;
+ private final int flags;
+
+ private final ECPublicKey baseKey;
+ private final byte[] baseKeySignature;
+ private final ECPublicKey ratchetKey;
+ private final IdentityKey identityKey;
+ private final byte[] serialized;
+
+ public KeyExchangeMessage(int messageVersion, int sequence, int flags,
+ ECPublicKey baseKey, byte[] baseKeySignature,
+ ECPublicKey ratchetKey,
+ IdentityKey identityKey)
+ {
+ this.supportedVersion = CiphertextMessage.CURRENT_VERSION;
+ this.version = messageVersion;
+ this.sequence = sequence;
+ this.flags = flags;
+ this.baseKey = baseKey;
+ this.baseKeySignature = baseKeySignature;
+ this.ratchetKey = ratchetKey;
+ this.identityKey = identityKey;
+
+ byte[] version = {ByteUtil.intsToByteHighAndLow(this.version, this.supportedVersion)};
+ Builder builder = WhisperProtos.KeyExchangeMessage
+ .newBuilder()
+ .setId((sequence << 5) | flags)
+ .setBaseKey(ByteString.copyFrom(baseKey.serialize()))
+ .setRatchetKey(ByteString.copyFrom(ratchetKey.serialize()))
+ .setIdentityKey(ByteString.copyFrom(identityKey.serialize()));
+
+ if (messageVersion >= 3) {
+ builder.setBaseKeySignature(ByteString.copyFrom(baseKeySignature));
+ }
+
+ this.serialized = ByteUtil.combine(version, builder.build().toByteArray());
+ }
+
+ public KeyExchangeMessage(byte[] serialized)
+ throws InvalidMessageException, InvalidVersionException, LegacyMessageException
+ {
+ try {
+ byte[][] parts = ByteUtil.split(serialized, 1, serialized.length - 1);
+ this.version = ByteUtil.highBitsToInt(parts[0][0]);
+ this.supportedVersion = ByteUtil.lowBitsToInt(parts[0][0]);
+
+ if (this.version <= CiphertextMessage.UNSUPPORTED_VERSION) {
+ throw new LegacyMessageException("Unsupported legacy version: " + this.version);
+ }
+
+ if (this.version > CiphertextMessage.CURRENT_VERSION) {
+ throw new InvalidVersionException("Unknown version: " + this.version);
+ }
+
+ WhisperProtos.KeyExchangeMessage message = WhisperProtos.KeyExchangeMessage.parseFrom(parts[1]);
+
+ if (!message.hasId() || !message.hasBaseKey() ||
+ !message.hasRatchetKey() || !message.hasIdentityKey() ||
+ (this.version >=3 && !message.hasBaseKeySignature()))
+ {
+ throw new InvalidMessageException("Some required fields missing!");
+ }
+
+ this.sequence = message.getId() >> 5;
+ this.flags = message.getId() & 0x1f;
+ this.serialized = serialized;
+ this.baseKey = Curve.decodePoint(message.getBaseKey().toByteArray(), 0);
+ this.baseKeySignature = message.getBaseKeySignature().toByteArray();
+ this.ratchetKey = Curve.decodePoint(message.getRatchetKey().toByteArray(), 0);
+ this.identityKey = new IdentityKey(message.getIdentityKey().toByteArray(), 0);
+ } catch (InvalidKeyException | IOException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public ECPublicKey getBaseKey() {
+ return baseKey;
+ }
+
+ public byte[] getBaseKeySignature() {
+ return baseKeySignature;
+ }
+
+ public ECPublicKey getRatchetKey() {
+ return ratchetKey;
+ }
+
+ public IdentityKey getIdentityKey() {
+ return identityKey;
+ }
+
+ public boolean hasIdentityKey() {
+ return true;
+ }
+
+ public int getMaxVersion() {
+ return supportedVersion;
+ }
+
+ public boolean isResponse() {
+ return ((flags & RESPONSE_FLAG) != 0);
+ }
+
+ public boolean isInitiate() {
+ return (flags & INITIATE_FLAG) != 0;
+ }
+
+ public boolean isResponseForSimultaneousInitiate() {
+ return (flags & SIMULTAENOUS_INITIATE_FLAG) != 0;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public int getSequence() {
+ return sequence;
+ }
+
+ public byte[] serialize() {
+ return serialized;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java b/src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java
new file mode 100644
index 00000000..fff6d02a
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.protocol;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.InvalidVersionException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+
+public class PreKeyWhisperMessage implements CiphertextMessage {
+
+ private final int version;
+ private final int registrationId;
+ private final Optional<Integer> preKeyId;
+ private final int signedPreKeyId;
+ private final ECPublicKey baseKey;
+ private final IdentityKey identityKey;
+ private final WhisperMessage message;
+ private final byte[] serialized;
+
+ public PreKeyWhisperMessage(byte[] serialized)
+ throws InvalidMessageException, InvalidVersionException
+ {
+ try {
+ this.version = ByteUtil.highBitsToInt(serialized[0]);
+
+ if (this.version > CiphertextMessage.CURRENT_VERSION) {
+ throw new InvalidVersionException("Unknown version: " + this.version);
+ }
+
+ WhisperProtos.PreKeyWhisperMessage preKeyWhisperMessage
+ = WhisperProtos.PreKeyWhisperMessage.parseFrom(ByteString.copyFrom(serialized, 1,
+ serialized.length-1));
+
+ if ((version == 2 && !preKeyWhisperMessage.hasPreKeyId()) ||
+ (version == 3 && !preKeyWhisperMessage.hasSignedPreKeyId()) ||
+ !preKeyWhisperMessage.hasBaseKey() ||
+ !preKeyWhisperMessage.hasIdentityKey() ||
+ !preKeyWhisperMessage.hasMessage())
+ {
+ throw new InvalidMessageException("Incomplete message.");
+ }
+
+ this.serialized = serialized;
+ this.registrationId = preKeyWhisperMessage.getRegistrationId();
+ this.preKeyId = preKeyWhisperMessage.hasPreKeyId() ? Optional.of(preKeyWhisperMessage.getPreKeyId()) : Optional.<Integer>absent();
+ this.signedPreKeyId = preKeyWhisperMessage.hasSignedPreKeyId() ? preKeyWhisperMessage.getSignedPreKeyId() : -1;
+ this.baseKey = Curve.decodePoint(preKeyWhisperMessage.getBaseKey().toByteArray(), 0);
+ this.identityKey = new IdentityKey(Curve.decodePoint(preKeyWhisperMessage.getIdentityKey().toByteArray(), 0));
+ this.message = new WhisperMessage(preKeyWhisperMessage.getMessage().toByteArray());
+ } catch (InvalidProtocolBufferException | InvalidKeyException | LegacyMessageException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ public PreKeyWhisperMessage(int messageVersion, int registrationId, Optional<Integer> preKeyId,
+ int signedPreKeyId, ECPublicKey baseKey, IdentityKey identityKey,
+ WhisperMessage message)
+ {
+ this.version = messageVersion;
+ this.registrationId = registrationId;
+ this.preKeyId = preKeyId;
+ this.signedPreKeyId = signedPreKeyId;
+ this.baseKey = baseKey;
+ this.identityKey = identityKey;
+ this.message = message;
+
+ WhisperProtos.PreKeyWhisperMessage.Builder builder =
+ WhisperProtos.PreKeyWhisperMessage.newBuilder()
+ .setSignedPreKeyId(signedPreKeyId)
+ .setBaseKey(ByteString.copyFrom(baseKey.serialize()))
+ .setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
+ .setMessage(ByteString.copyFrom(message.serialize()))
+ .setRegistrationId(registrationId);
+
+ if (preKeyId.isPresent()) {
+ builder.setPreKeyId(preKeyId.get());
+ }
+
+ byte[] versionBytes = {ByteUtil.intsToByteHighAndLow(this.version, CURRENT_VERSION)};
+ byte[] messageBytes = builder.build().toByteArray();
+
+ this.serialized = ByteUtil.combine(versionBytes, messageBytes);
+ }
+
+ public int getMessageVersion() {
+ return version;
+ }
+
+ public IdentityKey getIdentityKey() {
+ return identityKey;
+ }
+
+ public int getRegistrationId() {
+ return registrationId;
+ }
+
+ public Optional<Integer> getPreKeyId() {
+ return preKeyId;
+ }
+
+ public int getSignedPreKeyId() {
+ return signedPreKeyId;
+ }
+
+ public ECPublicKey getBaseKey() {
+ return baseKey;
+ }
+
+ public WhisperMessage getWhisperMessage() {
+ return message;
+ }
+
+ @Override
+ public byte[] serialize() {
+ return serialized;
+ }
+
+ @Override
+ public int getType() {
+ return CiphertextMessage.PREKEY_TYPE;
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java b/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java
new file mode 100644
index 00000000..424dd87c
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java
@@ -0,0 +1,56 @@
+package org.whispersystems.libaxolotl.protocol;
+
+import com.google.protobuf.ByteString;
+
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+public class SenderKeyDistributionMessage implements CiphertextMessage {
+
+ private final int id;
+ private final int iteration;
+ private final byte[] chainKey;
+ private final ECPublicKey signatureKey;
+ private final byte[] serialized;
+
+ public SenderKeyDistributionMessage(int id, int iteration, byte[] chainKey, ECPublicKey signatureKey) {
+ byte[] version = {ByteUtil.intsToByteHighAndLow(CURRENT_VERSION, CURRENT_VERSION)};
+
+ this.id = id;
+ this.iteration = iteration;
+ this.chainKey = chainKey;
+ this.signatureKey = signatureKey;
+ this.serialized = WhisperProtos.SenderKeyDistributionMessage.newBuilder()
+ .setId(id)
+ .setIteration(iteration)
+ .setChainKey(ByteString.copyFrom(chainKey))
+ .setSigningKey(ByteString.copyFrom(signatureKey.serialize()))
+ .build().toByteArray();
+ }
+
+ @Override
+ public byte[] serialize() {
+ return serialized;
+ }
+
+ @Override
+ public int getType() {
+ return SENDERKEY_DISTRIBUTION_TYPE;
+ }
+
+ public int getIteration() {
+ return iteration;
+ }
+
+ public byte[] getChainKey() {
+ return chainKey;
+ }
+
+ public ECPublicKey getSignatureKey() {
+ return signatureKey;
+ }
+
+ public int getId() {
+ return id;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java b/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java
new file mode 100644
index 00000000..b3a17456
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java
@@ -0,0 +1,121 @@
+package org.whispersystems.libaxolotl.protocol;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+import java.text.ParseException;
+
+public class SenderKeyMessage implements CiphertextMessage {
+
+ private static final int SIGNATURE_LENGTH = 64;
+
+ private final int messageVersion;
+ private final int keyId;
+ private final int iteration;
+ private final byte[] ciphertext;
+ private final byte[] serialized;
+
+ public SenderKeyMessage(byte[] serialized) throws InvalidMessageException, LegacyMessageException {
+ try {
+ byte[][] messageParts = ByteUtil.split(serialized, 1, serialized.length - 1 - SIGNATURE_LENGTH, SIGNATURE_LENGTH);
+ byte version = messageParts[0][0];
+ byte[] message = messageParts[1];
+ byte[] signature = messageParts[2];
+
+ if (ByteUtil.highBitsToInt(version) < 3) {
+ throw new LegacyMessageException("Legacy message: " + ByteUtil.highBitsToInt(version));
+ }
+
+ if (ByteUtil.highBitsToInt(version) > CURRENT_VERSION) {
+ throw new InvalidMessageException("Unknown version: " + ByteUtil.highBitsToInt(version));
+ }
+
+ WhisperProtos.SenderKeyMessage senderKeyMessage = WhisperProtos.SenderKeyMessage.parseFrom(message);
+
+ if (!senderKeyMessage.hasId() ||
+ !senderKeyMessage.hasIteration() ||
+ !senderKeyMessage.hasCiphertext())
+ {
+ throw new InvalidMessageException("Incomplete message.");
+ }
+
+ this.serialized = serialized;
+ this.messageVersion = ByteUtil.highBitsToInt(version);
+ this.keyId = senderKeyMessage.getId();
+ this.iteration = senderKeyMessage.getIteration();
+ this.ciphertext = senderKeyMessage.getCiphertext().toByteArray();
+ } catch (InvalidProtocolBufferException | ParseException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ public SenderKeyMessage(int keyId, int iteration, byte[] ciphertext, ECPrivateKey signatureKey) {
+ byte[] version = {ByteUtil.intsToByteHighAndLow(CURRENT_VERSION, CURRENT_VERSION)};
+ byte[] message = WhisperProtos.SenderKeyMessage.newBuilder()
+ .setId(keyId)
+ .setIteration(iteration)
+ .setCiphertext(ByteString.copyFrom(ciphertext))
+ .build().toByteArray();
+
+ byte[] signature = getSignature(signatureKey, ByteUtil.combine(version, message));
+
+ this.serialized = ByteUtil.combine(version, message, signature);
+ this.messageVersion = CURRENT_VERSION;
+ this.keyId = keyId;
+ this.iteration = iteration;
+ this.ciphertext = ciphertext;
+ }
+
+ public int getKeyId() {
+ return keyId;
+ }
+
+ public int getIteration() {
+ return iteration;
+ }
+
+ public byte[] getCipherText() {
+ return ciphertext;
+ }
+
+ public void verifySignature(ECPublicKey signatureKey)
+ throws InvalidMessageException
+ {
+ try {
+ byte[][] parts = ByteUtil.split(serialized, serialized.length - SIGNATURE_LENGTH, SIGNATURE_LENGTH);
+
+ if (!Curve.verifySignature(signatureKey, parts[0], parts[1])) {
+ throw new InvalidMessageException("Invalid signature!");
+ }
+
+ } catch (InvalidKeyException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ private byte[] getSignature(ECPrivateKey signatureKey, byte[] serialized) {
+ try {
+ return Curve.calculateSignature(signatureKey, serialized);
+ } catch (InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public byte[] serialize() {
+ return serialized;
+ }
+
+ @Override
+ public int getType() {
+ return CiphertextMessage.SENDERKEY_TYPE;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java b/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java
new file mode 100644
index 00000000..980bec1f
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.protocol;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.ParseException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public class WhisperMessage implements CiphertextMessage {
+
+ private static final int MAC_LENGTH = 8;
+
+ private final int messageVersion;
+ private final ECPublicKey senderRatchetKey;
+ private final int counter;
+ private final int previousCounter;
+ private final byte[] ciphertext;
+ private final byte[] serialized;
+
+ public WhisperMessage(byte[] serialized) throws InvalidMessageException, LegacyMessageException {
+ try {
+ byte[][] messageParts = ByteUtil.split(serialized, 1, serialized.length - 1 - MAC_LENGTH, MAC_LENGTH);
+ byte version = messageParts[0][0];
+ byte[] message = messageParts[1];
+ byte[] mac = messageParts[2];
+
+ if (ByteUtil.highBitsToInt(version) <= CiphertextMessage.UNSUPPORTED_VERSION) {
+ throw new LegacyMessageException("Legacy message: " + ByteUtil.highBitsToInt(version));
+ }
+
+ if (ByteUtil.highBitsToInt(version) > CURRENT_VERSION) {
+ throw new InvalidMessageException("Unknown version: " + ByteUtil.highBitsToInt(version));
+ }
+
+ WhisperProtos.WhisperMessage whisperMessage = WhisperProtos.WhisperMessage.parseFrom(message);
+
+ if (!whisperMessage.hasCiphertext() ||
+ !whisperMessage.hasCounter() ||
+ !whisperMessage.hasRatchetKey())
+ {
+ throw new InvalidMessageException("Incomplete message.");
+ }
+
+ this.serialized = serialized;
+ this.senderRatchetKey = Curve.decodePoint(whisperMessage.getRatchetKey().toByteArray(), 0);
+ this.messageVersion = ByteUtil.highBitsToInt(version);
+ this.counter = whisperMessage.getCounter();
+ this.previousCounter = whisperMessage.getPreviousCounter();
+ this.ciphertext = whisperMessage.getCiphertext().toByteArray();
+ } catch (InvalidProtocolBufferException | InvalidKeyException | ParseException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ public WhisperMessage(int messageVersion, SecretKeySpec macKey, ECPublicKey senderRatchetKey,
+ int counter, int previousCounter, byte[] ciphertext,
+ IdentityKey senderIdentityKey,
+ IdentityKey receiverIdentityKey)
+ {
+ byte[] version = {ByteUtil.intsToByteHighAndLow(messageVersion, CURRENT_VERSION)};
+ byte[] message = WhisperProtos.WhisperMessage.newBuilder()
+ .setRatchetKey(ByteString.copyFrom(senderRatchetKey.serialize()))
+ .setCounter(counter)
+ .setPreviousCounter(previousCounter)
+ .setCiphertext(ByteString.copyFrom(ciphertext))
+ .build().toByteArray();
+
+ byte[] mac = getMac(messageVersion, senderIdentityKey, receiverIdentityKey, macKey,
+ ByteUtil.combine(version, message));
+
+ this.serialized = ByteUtil.combine(version, message, mac);
+ this.senderRatchetKey = senderRatchetKey;
+ this.counter = counter;
+ this.previousCounter = previousCounter;
+ this.ciphertext = ciphertext;
+ this.messageVersion = messageVersion;
+ }
+
+ public ECPublicKey getSenderRatchetKey() {
+ return senderRatchetKey;
+ }
+
+ public int getMessageVersion() {
+ return messageVersion;
+ }
+
+ public int getCounter() {
+ return counter;
+ }
+
+ public byte[] getBody() {
+ return ciphertext;
+ }
+
+ public void verifyMac(int messageVersion, IdentityKey senderIdentityKey,
+ IdentityKey receiverIdentityKey, SecretKeySpec macKey)
+ throws InvalidMessageException
+ {
+ byte[][] parts = ByteUtil.split(serialized, serialized.length - MAC_LENGTH, MAC_LENGTH);
+ byte[] ourMac = getMac(messageVersion, senderIdentityKey, receiverIdentityKey, macKey, parts[0]);
+ byte[] theirMac = parts[1];
+
+ if (!MessageDigest.isEqual(ourMac, theirMac)) {
+ throw new InvalidMessageException("Bad Mac!");
+ }
+ }
+
+ private byte[] getMac(int messageVersion,
+ IdentityKey senderIdentityKey,
+ IdentityKey receiverIdentityKey,
+ SecretKeySpec macKey, byte[] serialized)
+ {
+ try {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(macKey);
+
+ if (messageVersion >= 3) {
+ mac.update(senderIdentityKey.getPublicKey().serialize());
+ mac.update(receiverIdentityKey.getPublicKey().serialize());
+ }
+
+ byte[] fullMac = mac.doFinal(serialized);
+ return ByteUtil.trim(fullMac, MAC_LENGTH);
+ } catch (NoSuchAlgorithmException | java.security.InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public byte[] serialize() {
+ return serialized;
+ }
+
+ @Override
+ public int getType() {
+ return CiphertextMessage.WHISPER_TYPE;
+ }
+
+ public static boolean isLegacy(byte[] message) {
+ return message != null && message.length >= 1 &&
+ ByteUtil.highBitsToInt(message[0]) <= CiphertextMessage.UNSUPPORTED_VERSION;
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java b/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java
new file mode 100644
index 00000000..12ab0272
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java
@@ -0,0 +1,3532 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: WhisperTextProtocol.proto
+
+package org.whispersystems.libaxolotl.protocol;
+
+public final class WhisperProtos {
+ private WhisperProtos() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ }
+ public interface WhisperMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional bytes ratchetKey = 1;
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ boolean hasRatchetKey();
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ com.google.protobuf.ByteString getRatchetKey();
+
+ // optional uint32 counter = 2;
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ boolean hasCounter();
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ int getCounter();
+
+ // optional uint32 previousCounter = 3;
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ boolean hasPreviousCounter();
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ int getPreviousCounter();
+
+ // optional bytes ciphertext = 4;
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ boolean hasCiphertext();
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ com.google.protobuf.ByteString getCiphertext();
+ }
+ /**
+ * Protobuf type {@code textsecure.WhisperMessage}
+ */
+ public static final class WhisperMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements WhisperMessageOrBuilder {
+ // Use WhisperMessage.newBuilder() to construct.
+ private WhisperMessage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private WhisperMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final WhisperMessage defaultInstance;
+ public static WhisperMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public WhisperMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private WhisperMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ ratchetKey_ = input.readBytes();
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ counter_ = input.readUInt32();
+ break;
+ }
+ case 24: {
+ bitField0_ |= 0x00000004;
+ previousCounter_ = input.readUInt32();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ ciphertext_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_WhisperMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_WhisperMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<WhisperMessage> PARSER =
+ new com.google.protobuf.AbstractParser<WhisperMessage>() {
+ public WhisperMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new WhisperMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<WhisperMessage> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional bytes ratchetKey = 1;
+ public static final int RATCHETKEY_FIELD_NUMBER = 1;
+ private com.google.protobuf.ByteString ratchetKey_;
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ public boolean hasRatchetKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ public com.google.protobuf.ByteString getRatchetKey() {
+ return ratchetKey_;
+ }
+
+ // optional uint32 counter = 2;
+ public static final int COUNTER_FIELD_NUMBER = 2;
+ private int counter_;
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ public boolean hasCounter() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ public int getCounter() {
+ return counter_;
+ }
+
+ // optional uint32 previousCounter = 3;
+ public static final int PREVIOUSCOUNTER_FIELD_NUMBER = 3;
+ private int previousCounter_;
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ public boolean hasPreviousCounter() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ public int getPreviousCounter() {
+ return previousCounter_;
+ }
+
+ // optional bytes ciphertext = 4;
+ public static final int CIPHERTEXT_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString ciphertext_;
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ public boolean hasCiphertext() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ public com.google.protobuf.ByteString getCiphertext() {
+ return ciphertext_;
+ }
+
+ private void initFields() {
+ ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ counter_ = 0;
+ previousCounter_ = 0;
+ ciphertext_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, ratchetKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeUInt32(2, counter_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeUInt32(3, previousCounter_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, ciphertext_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, ratchetKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(2, counter_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(3, previousCounter_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, ciphertext_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.WhisperMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_WhisperMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_WhisperMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ counter_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ previousCounter_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ ciphertext_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_WhisperMessage_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage build() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage buildPartial() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage result = new org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.ratchetKey_ = ratchetKey_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.counter_ = counter_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.previousCounter_ = previousCounter_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.ciphertext_ = ciphertext_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage) {
+ return mergeFrom((org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage other) {
+ if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage.getDefaultInstance()) return this;
+ if (other.hasRatchetKey()) {
+ setRatchetKey(other.getRatchetKey());
+ }
+ if (other.hasCounter()) {
+ setCounter(other.getCounter());
+ }
+ if (other.hasPreviousCounter()) {
+ setPreviousCounter(other.getPreviousCounter());
+ }
+ if (other.hasCiphertext()) {
+ setCiphertext(other.getCiphertext());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.protocol.WhisperProtos.WhisperMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional bytes ratchetKey = 1;
+ private com.google.protobuf.ByteString ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ public boolean hasRatchetKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ public com.google.protobuf.ByteString getRatchetKey() {
+ return ratchetKey_;
+ }
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ public Builder setRatchetKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ ratchetKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes ratchetKey = 1;</code>
+ */
+ public Builder clearRatchetKey() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ ratchetKey_ = getDefaultInstance().getRatchetKey();
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 counter = 2;
+ private int counter_ ;
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ public boolean hasCounter() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ public int getCounter() {
+ return counter_;
+ }
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ public Builder setCounter(int value) {
+ bitField0_ |= 0x00000002;
+ counter_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 counter = 2;</code>
+ */
+ public Builder clearCounter() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ counter_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 previousCounter = 3;
+ private int previousCounter_ ;
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ public boolean hasPreviousCounter() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ public int getPreviousCounter() {
+ return previousCounter_;
+ }
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ public Builder setPreviousCounter(int value) {
+ bitField0_ |= 0x00000004;
+ previousCounter_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 previousCounter = 3;</code>
+ */
+ public Builder clearPreviousCounter() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ previousCounter_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes ciphertext = 4;
+ private com.google.protobuf.ByteString ciphertext_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ public boolean hasCiphertext() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ public com.google.protobuf.ByteString getCiphertext() {
+ return ciphertext_;
+ }
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ public Builder setCiphertext(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ ciphertext_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes ciphertext = 4;</code>
+ */
+ public Builder clearCiphertext() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ ciphertext_ = getDefaultInstance().getCiphertext();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.WhisperMessage)
+ }
+
+ static {
+ defaultInstance = new WhisperMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.WhisperMessage)
+ }
+
+ public interface PreKeyWhisperMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 registrationId = 5;
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ boolean hasRegistrationId();
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ int getRegistrationId();
+
+ // optional uint32 preKeyId = 1;
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ boolean hasPreKeyId();
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ int getPreKeyId();
+
+ // optional uint32 signedPreKeyId = 6;
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ boolean hasSignedPreKeyId();
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ int getSignedPreKeyId();
+
+ // optional bytes baseKey = 2;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ boolean hasBaseKey();
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getBaseKey();
+
+ // optional bytes identityKey = 3;
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ boolean hasIdentityKey();
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ com.google.protobuf.ByteString getIdentityKey();
+
+ // optional bytes message = 4;
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ boolean hasMessage();
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ com.google.protobuf.ByteString getMessage();
+ }
+ /**
+ * Protobuf type {@code textsecure.PreKeyWhisperMessage}
+ */
+ public static final class PreKeyWhisperMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements PreKeyWhisperMessageOrBuilder {
+ // Use PreKeyWhisperMessage.newBuilder() to construct.
+ private PreKeyWhisperMessage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private PreKeyWhisperMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final PreKeyWhisperMessage defaultInstance;
+ public static PreKeyWhisperMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PreKeyWhisperMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private PreKeyWhisperMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000002;
+ preKeyId_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000008;
+ baseKey_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000010;
+ identityKey_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000020;
+ message_ = input.readBytes();
+ break;
+ }
+ case 40: {
+ bitField0_ |= 0x00000001;
+ registrationId_ = input.readUInt32();
+ break;
+ }
+ case 48: {
+ bitField0_ |= 0x00000004;
+ signedPreKeyId_ = input.readUInt32();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_PreKeyWhisperMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_PreKeyWhisperMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<PreKeyWhisperMessage> PARSER =
+ new com.google.protobuf.AbstractParser<PreKeyWhisperMessage>() {
+ public PreKeyWhisperMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new PreKeyWhisperMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<PreKeyWhisperMessage> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 registrationId = 5;
+ public static final int REGISTRATIONID_FIELD_NUMBER = 5;
+ private int registrationId_;
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ public boolean hasRegistrationId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ public int getRegistrationId() {
+ return registrationId_;
+ }
+
+ // optional uint32 preKeyId = 1;
+ public static final int PREKEYID_FIELD_NUMBER = 1;
+ private int preKeyId_;
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public boolean hasPreKeyId() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public int getPreKeyId() {
+ return preKeyId_;
+ }
+
+ // optional uint32 signedPreKeyId = 6;
+ public static final int SIGNEDPREKEYID_FIELD_NUMBER = 6;
+ private int signedPreKeyId_;
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ public boolean hasSignedPreKeyId() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ public int getSignedPreKeyId() {
+ return signedPreKeyId_;
+ }
+
+ // optional bytes baseKey = 2;
+ public static final int BASEKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString baseKey_;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public boolean hasBaseKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKey() {
+ return baseKey_;
+ }
+
+ // optional bytes identityKey = 3;
+ public static final int IDENTITYKEY_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString identityKey_;
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ public boolean hasIdentityKey() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getIdentityKey() {
+ return identityKey_;
+ }
+
+ // optional bytes message = 4;
+ public static final int MESSAGE_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString message_;
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ public boolean hasMessage() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ public com.google.protobuf.ByteString getMessage() {
+ return message_;
+ }
+
+ private void initFields() {
+ registrationId_ = 0;
+ preKeyId_ = 0;
+ signedPreKeyId_ = 0;
+ baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ identityKey_ = com.google.protobuf.ByteString.EMPTY;
+ message_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeUInt32(1, preKeyId_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(2, baseKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeBytes(3, identityKey_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ output.writeBytes(4, message_);
+ }
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(5, registrationId_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeUInt32(6, signedPreKeyId_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, preKeyId_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, baseKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, identityKey_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, message_);
+ }
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(5, registrationId_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(6, signedPreKeyId_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.PreKeyWhisperMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_PreKeyWhisperMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_PreKeyWhisperMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ registrationId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ preKeyId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ signedPreKeyId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ identityKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ message_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000020);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_PreKeyWhisperMessage_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage build() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage buildPartial() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage result = new org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.registrationId_ = registrationId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.preKeyId_ = preKeyId_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.signedPreKeyId_ = signedPreKeyId_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.baseKey_ = baseKey_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.identityKey_ = identityKey_;
+ if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+ to_bitField0_ |= 0x00000020;
+ }
+ result.message_ = message_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage) {
+ return mergeFrom((org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage other) {
+ if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage.getDefaultInstance()) return this;
+ if (other.hasRegistrationId()) {
+ setRegistrationId(other.getRegistrationId());
+ }
+ if (other.hasPreKeyId()) {
+ setPreKeyId(other.getPreKeyId());
+ }
+ if (other.hasSignedPreKeyId()) {
+ setSignedPreKeyId(other.getSignedPreKeyId());
+ }
+ if (other.hasBaseKey()) {
+ setBaseKey(other.getBaseKey());
+ }
+ if (other.hasIdentityKey()) {
+ setIdentityKey(other.getIdentityKey());
+ }
+ if (other.hasMessage()) {
+ setMessage(other.getMessage());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.protocol.WhisperProtos.PreKeyWhisperMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 registrationId = 5;
+ private int registrationId_ ;
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ public boolean hasRegistrationId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ public int getRegistrationId() {
+ return registrationId_;
+ }
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ public Builder setRegistrationId(int value) {
+ bitField0_ |= 0x00000001;
+ registrationId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 registrationId = 5;</code>
+ */
+ public Builder clearRegistrationId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ registrationId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 preKeyId = 1;
+ private int preKeyId_ ;
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public boolean hasPreKeyId() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public int getPreKeyId() {
+ return preKeyId_;
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public Builder setPreKeyId(int value) {
+ bitField0_ |= 0x00000002;
+ preKeyId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public Builder clearPreKeyId() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ preKeyId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 signedPreKeyId = 6;
+ private int signedPreKeyId_ ;
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ public boolean hasSignedPreKeyId() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ public int getSignedPreKeyId() {
+ return signedPreKeyId_;
+ }
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ public Builder setSignedPreKeyId(int value) {
+ bitField0_ |= 0x00000004;
+ signedPreKeyId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 signedPreKeyId = 6;</code>
+ */
+ public Builder clearSignedPreKeyId() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ signedPreKeyId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes baseKey = 2;
+ private com.google.protobuf.ByteString baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public boolean hasBaseKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKey() {
+ return baseKey_;
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public Builder setBaseKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ baseKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public Builder clearBaseKey() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ baseKey_ = getDefaultInstance().getBaseKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes identityKey = 3;
+ private com.google.protobuf.ByteString identityKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ public boolean hasIdentityKey() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getIdentityKey() {
+ return identityKey_;
+ }
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ public Builder setIdentityKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000010;
+ identityKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes identityKey = 3;</code>
+ */
+ public Builder clearIdentityKey() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ identityKey_ = getDefaultInstance().getIdentityKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes message = 4;
+ private com.google.protobuf.ByteString message_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ public boolean hasMessage() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ public com.google.protobuf.ByteString getMessage() {
+ return message_;
+ }
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ public Builder setMessage(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000020;
+ message_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes message = 4;</code>
+ *
+ * <pre>
+ * WhisperMessage
+ * </pre>
+ */
+ public Builder clearMessage() {
+ bitField0_ = (bitField0_ & ~0x00000020);
+ message_ = getDefaultInstance().getMessage();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.PreKeyWhisperMessage)
+ }
+
+ static {
+ defaultInstance = new PreKeyWhisperMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.PreKeyWhisperMessage)
+ }
+
+ public interface KeyExchangeMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 id = 1;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ boolean hasId();
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ int getId();
+
+ // optional bytes baseKey = 2;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ boolean hasBaseKey();
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getBaseKey();
+
+ // optional bytes ratchetKey = 3;
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ boolean hasRatchetKey();
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ com.google.protobuf.ByteString getRatchetKey();
+
+ // optional bytes identityKey = 4;
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ boolean hasIdentityKey();
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ com.google.protobuf.ByteString getIdentityKey();
+
+ // optional bytes baseKeySignature = 5;
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ boolean hasBaseKeySignature();
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ com.google.protobuf.ByteString getBaseKeySignature();
+ }
+ /**
+ * Protobuf type {@code textsecure.KeyExchangeMessage}
+ */
+ public static final class KeyExchangeMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements KeyExchangeMessageOrBuilder {
+ // Use KeyExchangeMessage.newBuilder() to construct.
+ private KeyExchangeMessage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private KeyExchangeMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final KeyExchangeMessage defaultInstance;
+ public static KeyExchangeMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public KeyExchangeMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private KeyExchangeMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ id_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ baseKey_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ ratchetKey_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ identityKey_ = input.readBytes();
+ break;
+ }
+ case 42: {
+ bitField0_ |= 0x00000010;
+ baseKeySignature_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_KeyExchangeMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_KeyExchangeMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<KeyExchangeMessage> PARSER =
+ new com.google.protobuf.AbstractParser<KeyExchangeMessage>() {
+ public KeyExchangeMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new KeyExchangeMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<KeyExchangeMessage> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 id = 1;
+ public static final int ID_FIELD_NUMBER = 1;
+ private int id_;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+
+ // optional bytes baseKey = 2;
+ public static final int BASEKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString baseKey_;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public boolean hasBaseKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKey() {
+ return baseKey_;
+ }
+
+ // optional bytes ratchetKey = 3;
+ public static final int RATCHETKEY_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString ratchetKey_;
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ public boolean hasRatchetKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getRatchetKey() {
+ return ratchetKey_;
+ }
+
+ // optional bytes identityKey = 4;
+ public static final int IDENTITYKEY_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString identityKey_;
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ public boolean hasIdentityKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getIdentityKey() {
+ return identityKey_;
+ }
+
+ // optional bytes baseKeySignature = 5;
+ public static final int BASEKEYSIGNATURE_FIELD_NUMBER = 5;
+ private com.google.protobuf.ByteString baseKeySignature_;
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ public boolean hasBaseKeySignature() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKeySignature() {
+ return baseKeySignature_;
+ }
+
+ private void initFields() {
+ id_ = 0;
+ baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ identityKey_ = com.google.protobuf.ByteString.EMPTY;
+ baseKeySignature_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, baseKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, ratchetKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, identityKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeBytes(5, baseKeySignature_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, baseKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, ratchetKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, identityKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(5, baseKeySignature_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.KeyExchangeMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_KeyExchangeMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_KeyExchangeMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ id_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ identityKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ baseKeySignature_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_KeyExchangeMessage_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage build() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage buildPartial() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage result = new org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.id_ = id_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.baseKey_ = baseKey_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.ratchetKey_ = ratchetKey_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.identityKey_ = identityKey_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.baseKeySignature_ = baseKeySignature_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage) {
+ return mergeFrom((org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage other) {
+ if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasBaseKey()) {
+ setBaseKey(other.getBaseKey());
+ }
+ if (other.hasRatchetKey()) {
+ setRatchetKey(other.getRatchetKey());
+ }
+ if (other.hasIdentityKey()) {
+ setIdentityKey(other.getIdentityKey());
+ }
+ if (other.hasBaseKeySignature()) {
+ setBaseKeySignature(other.getBaseKeySignature());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.protocol.WhisperProtos.KeyExchangeMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 id = 1;
+ private int id_ ;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder setId(int value) {
+ bitField0_ |= 0x00000001;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes baseKey = 2;
+ private com.google.protobuf.ByteString baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public boolean hasBaseKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKey() {
+ return baseKey_;
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public Builder setBaseKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ baseKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public Builder clearBaseKey() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ baseKey_ = getDefaultInstance().getBaseKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes ratchetKey = 3;
+ private com.google.protobuf.ByteString ratchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ public boolean hasRatchetKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getRatchetKey() {
+ return ratchetKey_;
+ }
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ public Builder setRatchetKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ ratchetKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes ratchetKey = 3;</code>
+ */
+ public Builder clearRatchetKey() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ ratchetKey_ = getDefaultInstance().getRatchetKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes identityKey = 4;
+ private com.google.protobuf.ByteString identityKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ public boolean hasIdentityKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getIdentityKey() {
+ return identityKey_;
+ }
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ public Builder setIdentityKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ identityKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes identityKey = 4;</code>
+ */
+ public Builder clearIdentityKey() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ identityKey_ = getDefaultInstance().getIdentityKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes baseKeySignature = 5;
+ private com.google.protobuf.ByteString baseKeySignature_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ public boolean hasBaseKeySignature() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKeySignature() {
+ return baseKeySignature_;
+ }
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ public Builder setBaseKeySignature(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000010;
+ baseKeySignature_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes baseKeySignature = 5;</code>
+ */
+ public Builder clearBaseKeySignature() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ baseKeySignature_ = getDefaultInstance().getBaseKeySignature();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.KeyExchangeMessage)
+ }
+
+ static {
+ defaultInstance = new KeyExchangeMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.KeyExchangeMessage)
+ }
+
+ public interface SenderKeyMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 id = 1;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ boolean hasId();
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ int getId();
+
+ // optional uint32 iteration = 2;
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ boolean hasIteration();
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ int getIteration();
+
+ // optional bytes ciphertext = 3;
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ boolean hasCiphertext();
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ com.google.protobuf.ByteString getCiphertext();
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyMessage}
+ */
+ public static final class SenderKeyMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements SenderKeyMessageOrBuilder {
+ // Use SenderKeyMessage.newBuilder() to construct.
+ private SenderKeyMessage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SenderKeyMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SenderKeyMessage defaultInstance;
+ public static SenderKeyMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SenderKeyMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SenderKeyMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ id_ = input.readUInt32();
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ iteration_ = input.readUInt32();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ ciphertext_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SenderKeyMessage> PARSER =
+ new com.google.protobuf.AbstractParser<SenderKeyMessage>() {
+ public SenderKeyMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SenderKeyMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SenderKeyMessage> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 id = 1;
+ public static final int ID_FIELD_NUMBER = 1;
+ private int id_;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+
+ // optional uint32 iteration = 2;
+ public static final int ITERATION_FIELD_NUMBER = 2;
+ private int iteration_;
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+
+ // optional bytes ciphertext = 3;
+ public static final int CIPHERTEXT_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString ciphertext_;
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ public boolean hasCiphertext() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ public com.google.protobuf.ByteString getCiphertext() {
+ return ciphertext_;
+ }
+
+ private void initFields() {
+ id_ = 0;
+ iteration_ = 0;
+ ciphertext_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeUInt32(2, iteration_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, ciphertext_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(2, iteration_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, ciphertext_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ id_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ iteration_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ ciphertext_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyMessage_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage build() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage buildPartial() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage result = new org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.id_ = id_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.iteration_ = iteration_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.ciphertext_ = ciphertext_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage) {
+ return mergeFrom((org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage other) {
+ if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasIteration()) {
+ setIteration(other.getIteration());
+ }
+ if (other.hasCiphertext()) {
+ setCiphertext(other.getCiphertext());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 id = 1;
+ private int id_ ;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder setId(int value) {
+ bitField0_ |= 0x00000001;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 iteration = 2;
+ private int iteration_ ;
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public Builder setIteration(int value) {
+ bitField0_ |= 0x00000002;
+ iteration_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public Builder clearIteration() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ iteration_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes ciphertext = 3;
+ private com.google.protobuf.ByteString ciphertext_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ public boolean hasCiphertext() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ public com.google.protobuf.ByteString getCiphertext() {
+ return ciphertext_;
+ }
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ public Builder setCiphertext(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ ciphertext_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes ciphertext = 3;</code>
+ */
+ public Builder clearCiphertext() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ ciphertext_ = getDefaultInstance().getCiphertext();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SenderKeyMessage)
+ }
+
+ static {
+ defaultInstance = new SenderKeyMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SenderKeyMessage)
+ }
+
+ public interface SenderKeyDistributionMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 id = 1;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ boolean hasId();
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ int getId();
+
+ // optional uint32 iteration = 2;
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ boolean hasIteration();
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ int getIteration();
+
+ // optional bytes chainKey = 3;
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ boolean hasChainKey();
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ com.google.protobuf.ByteString getChainKey();
+
+ // optional bytes signingKey = 4;
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ boolean hasSigningKey();
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ com.google.protobuf.ByteString getSigningKey();
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyDistributionMessage}
+ */
+ public static final class SenderKeyDistributionMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements SenderKeyDistributionMessageOrBuilder {
+ // Use SenderKeyDistributionMessage.newBuilder() to construct.
+ private SenderKeyDistributionMessage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SenderKeyDistributionMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SenderKeyDistributionMessage defaultInstance;
+ public static SenderKeyDistributionMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SenderKeyDistributionMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SenderKeyDistributionMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ id_ = input.readUInt32();
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ iteration_ = input.readUInt32();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ chainKey_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ signingKey_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyDistributionMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyDistributionMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SenderKeyDistributionMessage> PARSER =
+ new com.google.protobuf.AbstractParser<SenderKeyDistributionMessage>() {
+ public SenderKeyDistributionMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SenderKeyDistributionMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SenderKeyDistributionMessage> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 id = 1;
+ public static final int ID_FIELD_NUMBER = 1;
+ private int id_;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+
+ // optional uint32 iteration = 2;
+ public static final int ITERATION_FIELD_NUMBER = 2;
+ private int iteration_;
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+
+ // optional bytes chainKey = 3;
+ public static final int CHAINKEY_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString chainKey_;
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ public boolean hasChainKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getChainKey() {
+ return chainKey_;
+ }
+
+ // optional bytes signingKey = 4;
+ public static final int SIGNINGKEY_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString signingKey_;
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ public boolean hasSigningKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getSigningKey() {
+ return signingKey_;
+ }
+
+ private void initFields() {
+ id_ = 0;
+ iteration_ = 0;
+ chainKey_ = com.google.protobuf.ByteString.EMPTY;
+ signingKey_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeUInt32(2, iteration_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, chainKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, signingKey_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(2, iteration_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, chainKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, signingKey_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyDistributionMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyDistributionMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyDistributionMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage.class, org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ id_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ iteration_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ chainKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ signingKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.internal_static_textsecure_SenderKeyDistributionMessage_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage build() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage buildPartial() {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage result = new org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.id_ = id_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.iteration_ = iteration_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.chainKey_ = chainKey_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.signingKey_ = signingKey_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage) {
+ return mergeFrom((org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage other) {
+ if (other == org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasIteration()) {
+ setIteration(other.getIteration());
+ }
+ if (other.hasChainKey()) {
+ setChainKey(other.getChainKey());
+ }
+ if (other.hasSigningKey()) {
+ setSigningKey(other.getSigningKey());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.protocol.WhisperProtos.SenderKeyDistributionMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 id = 1;
+ private int id_ ;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder setId(int value) {
+ bitField0_ |= 0x00000001;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 iteration = 2;
+ private int iteration_ ;
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public Builder setIteration(int value) {
+ bitField0_ |= 0x00000002;
+ iteration_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 iteration = 2;</code>
+ */
+ public Builder clearIteration() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ iteration_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes chainKey = 3;
+ private com.google.protobuf.ByteString chainKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ public boolean hasChainKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getChainKey() {
+ return chainKey_;
+ }
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ public Builder setChainKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ chainKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes chainKey = 3;</code>
+ */
+ public Builder clearChainKey() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ chainKey_ = getDefaultInstance().getChainKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes signingKey = 4;
+ private com.google.protobuf.ByteString signingKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ public boolean hasSigningKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getSigningKey() {
+ return signingKey_;
+ }
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ public Builder setSigningKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ signingKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes signingKey = 4;</code>
+ */
+ public Builder clearSigningKey() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ signingKey_ = getDefaultInstance().getSigningKey();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SenderKeyDistributionMessage)
+ }
+
+ static {
+ defaultInstance = new SenderKeyDistributionMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SenderKeyDistributionMessage)
+ }
+
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_WhisperMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_WhisperMessage_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_PreKeyWhisperMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_PreKeyWhisperMessage_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_KeyExchangeMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_KeyExchangeMessage_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SenderKeyMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SenderKeyMessage_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SenderKeyDistributionMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SenderKeyDistributionMessage_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\031WhisperTextProtocol.proto\022\ntextsecure\"" +
+ "b\n\016WhisperMessage\022\022\n\nratchetKey\030\001 \001(\014\022\017\n" +
+ "\007counter\030\002 \001(\r\022\027\n\017previousCounter\030\003 \001(\r\022" +
+ "\022\n\nciphertext\030\004 \001(\014\"\217\001\n\024PreKeyWhisperMes" +
+ "sage\022\026\n\016registrationId\030\005 \001(\r\022\020\n\010preKeyId" +
+ "\030\001 \001(\r\022\026\n\016signedPreKeyId\030\006 \001(\r\022\017\n\007baseKe" +
+ "y\030\002 \001(\014\022\023\n\013identityKey\030\003 \001(\014\022\017\n\007message\030" +
+ "\004 \001(\014\"t\n\022KeyExchangeMessage\022\n\n\002id\030\001 \001(\r\022" +
+ "\017\n\007baseKey\030\002 \001(\014\022\022\n\nratchetKey\030\003 \001(\014\022\023\n\013" +
+ "identityKey\030\004 \001(\014\022\030\n\020baseKeySignature\030\005 ",
+ "\001(\014\"E\n\020SenderKeyMessage\022\n\n\002id\030\001 \001(\r\022\021\n\ti" +
+ "teration\030\002 \001(\r\022\022\n\nciphertext\030\003 \001(\014\"c\n\034Se" +
+ "nderKeyDistributionMessage\022\n\n\002id\030\001 \001(\r\022\021" +
+ "\n\titeration\030\002 \001(\r\022\020\n\010chainKey\030\003 \001(\014\022\022\n\ns" +
+ "igningKey\030\004 \001(\014B7\n&org.whispersystems.li" +
+ "baxolotl.protocolB\rWhisperProtos"
+ };
+ com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+ new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+ public com.google.protobuf.ExtensionRegistry assignDescriptors(
+ com.google.protobuf.Descriptors.FileDescriptor root) {
+ descriptor = root;
+ internal_static_textsecure_WhisperMessage_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_textsecure_WhisperMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_WhisperMessage_descriptor,
+ new java.lang.String[] { "RatchetKey", "Counter", "PreviousCounter", "Ciphertext", });
+ internal_static_textsecure_PreKeyWhisperMessage_descriptor =
+ getDescriptor().getMessageTypes().get(1);
+ internal_static_textsecure_PreKeyWhisperMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_PreKeyWhisperMessage_descriptor,
+ new java.lang.String[] { "RegistrationId", "PreKeyId", "SignedPreKeyId", "BaseKey", "IdentityKey", "Message", });
+ internal_static_textsecure_KeyExchangeMessage_descriptor =
+ getDescriptor().getMessageTypes().get(2);
+ internal_static_textsecure_KeyExchangeMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_KeyExchangeMessage_descriptor,
+ new java.lang.String[] { "Id", "BaseKey", "RatchetKey", "IdentityKey", "BaseKeySignature", });
+ internal_static_textsecure_SenderKeyMessage_descriptor =
+ getDescriptor().getMessageTypes().get(3);
+ internal_static_textsecure_SenderKeyMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SenderKeyMessage_descriptor,
+ new java.lang.String[] { "Id", "Iteration", "Ciphertext", });
+ internal_static_textsecure_SenderKeyDistributionMessage_descriptor =
+ getDescriptor().getMessageTypes().get(4);
+ internal_static_textsecure_SenderKeyDistributionMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SenderKeyDistributionMessage_descriptor,
+ new java.lang.String[] { "Id", "Iteration", "ChainKey", "SigningKey", });
+ return null;
+ }
+ };
+ com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ }, assigner);
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java
new file mode 100644
index 00000000..13c995e9
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java
@@ -0,0 +1,109 @@
+package org.whispersystems.libaxolotl.ratchet;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+public class AliceAxolotlParameters {
+
+ private final IdentityKeyPair ourIdentityKey;
+ private final ECKeyPair ourBaseKey;
+
+ private final IdentityKey theirIdentityKey;
+ private final ECPublicKey theirSignedPreKey;
+ private final Optional<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);
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java
new file mode 100644
index 00000000..27116a8b
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java
@@ -0,0 +1,109 @@
+package org.whispersystems.libaxolotl.ratchet;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+public class BobAxolotlParameters {
+
+ private final IdentityKeyPair ourIdentityKey;
+ private final ECKeyPair ourSignedPreKey;
+ private final Optional<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);
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java
new file mode 100644
index 00000000..9dd1dbee
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.ratchet;
+
+
+import org.whispersystems.libaxolotl.kdf.DerivedMessageSecrets;
+import org.whispersystems.libaxolotl.kdf.HKDF;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public class ChainKey {
+
+ private static final byte[] MESSAGE_KEY_SEED = {0x01};
+ private static final byte[] CHAIN_KEY_SEED = {0x02};
+
+ private final HKDF kdf;
+ private final byte[] key;
+ private final int index;
+
+ public ChainKey(HKDF kdf, byte[] key, int index) {
+ this.kdf = kdf;
+ this.key = key;
+ this.index = index;
+ }
+
+ public byte[] getKey() {
+ return key;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public ChainKey getNextChainKey() {
+ byte[] nextKey = getBaseMaterial(CHAIN_KEY_SEED);
+ return new ChainKey(kdf, nextKey, index + 1);
+ }
+
+ public MessageKeys getMessageKeys() {
+ byte[] inputKeyMaterial = getBaseMaterial(MESSAGE_KEY_SEED);
+ byte[] keyMaterialBytes = kdf.deriveSecrets(inputKeyMaterial, "WhisperMessageKeys".getBytes(), DerivedMessageSecrets.SIZE);
+ DerivedMessageSecrets keyMaterial = new DerivedMessageSecrets(keyMaterialBytes);
+
+ return new MessageKeys(keyMaterial.getCipherKey(), keyMaterial.getMacKey(), keyMaterial.getIv(), index);
+ }
+
+ private byte[] getBaseMaterial(byte[] seed) {
+ try {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(new SecretKeySpec(key, "HmacSHA256"));
+
+ return mac.doFinal(seed);
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java
new file mode 100644
index 00000000..95a8c7dc
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.ratchet;
+
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class MessageKeys {
+
+ private final SecretKeySpec cipherKey;
+ private final SecretKeySpec macKey;
+ private final IvParameterSpec iv;
+ private final int counter;
+
+ public MessageKeys(SecretKeySpec cipherKey, SecretKeySpec macKey, IvParameterSpec iv, int counter) {
+ this.cipherKey = cipherKey;
+ this.macKey = macKey;
+ this.iv = iv;
+ this.counter = counter;
+ }
+
+ public SecretKeySpec getCipherKey() {
+ return cipherKey;
+ }
+
+ public SecretKeySpec getMacKey() {
+ return macKey;
+ }
+
+ public IvParameterSpec getIv() {
+ return iv;
+ }
+
+ public int getCounter() {
+ return counter;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java
new file mode 100644
index 00000000..8c094ec0
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java
@@ -0,0 +1,179 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.ratchet;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.kdf.HKDF;
+import org.whispersystems.libaxolotl.state.SessionState;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+import org.whispersystems.libaxolotl.util.Pair;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+public class RatchetingSession {
+
+ public static void initializeSession(SessionState sessionState,
+ int sessionVersion,
+ SymmetricAxolotlParameters parameters)
+ throws InvalidKeyException
+ {
+ if (isAlice(parameters.getOurBaseKey().getPublicKey(), parameters.getTheirBaseKey())) {
+ AliceAxolotlParameters.Builder aliceParameters = AliceAxolotlParameters.newBuilder();
+
+ aliceParameters.setOurBaseKey(parameters.getOurBaseKey())
+ .setOurIdentityKey(parameters.getOurIdentityKey())
+ .setTheirRatchetKey(parameters.getTheirRatchetKey())
+ .setTheirIdentityKey(parameters.getTheirIdentityKey())
+ .setTheirSignedPreKey(parameters.getTheirBaseKey())
+ .setTheirOneTimePreKey(Optional.<ECPublicKey>absent());
+
+ RatchetingSession.initializeSession(sessionState, sessionVersion, aliceParameters.create());
+ } else {
+ BobAxolotlParameters.Builder bobParameters = BobAxolotlParameters.newBuilder();
+
+ bobParameters.setOurIdentityKey(parameters.getOurIdentityKey())
+ .setOurRatchetKey(parameters.getOurRatchetKey())
+ .setOurSignedPreKey(parameters.getOurBaseKey())
+ .setOurOneTimePreKey(Optional.<ECKeyPair>absent())
+ .setTheirBaseKey(parameters.getTheirBaseKey())
+ .setTheirIdentityKey(parameters.getTheirIdentityKey());
+
+ RatchetingSession.initializeSession(sessionState, sessionVersion, bobParameters.create());
+ }
+ }
+
+ public static void initializeSession(SessionState sessionState,
+ int sessionVersion,
+ AliceAxolotlParameters parameters)
+ throws InvalidKeyException
+ {
+ try {
+ sessionState.setSessionVersion(sessionVersion);
+ sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey());
+ sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey());
+
+ ECKeyPair sendingRatchetKey = Curve.generateKeyPair();
+ ByteArrayOutputStream secrets = new ByteArrayOutputStream();
+
+ if (sessionVersion >= 3) {
+ secrets.write(getDiscontinuityBytes());
+ }
+
+ secrets.write(Curve.calculateAgreement(parameters.getTheirSignedPreKey(),
+ parameters.getOurIdentityKey().getPrivateKey()));
+ secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(),
+ parameters.getOurBaseKey().getPrivateKey()));
+ secrets.write(Curve.calculateAgreement(parameters.getTheirSignedPreKey(),
+ parameters.getOurBaseKey().getPrivateKey()));
+
+ if (sessionVersion >= 3 & parameters.getTheirOneTimePreKey().isPresent()) {
+ secrets.write(Curve.calculateAgreement(parameters.getTheirOneTimePreKey().get(),
+ parameters.getOurBaseKey().getPrivateKey()));
+ }
+
+ DerivedKeys derivedKeys = calculateDerivedKeys(sessionVersion, secrets.toByteArray());
+ Pair<RootKey, ChainKey> sendingChain = derivedKeys.getRootKey().createChain(parameters.getTheirRatchetKey(), sendingRatchetKey);
+
+ sessionState.addReceiverChain(parameters.getTheirRatchetKey(), derivedKeys.getChainKey());
+ sessionState.setSenderChain(sendingRatchetKey, sendingChain.second());
+ sessionState.setRootKey(sendingChain.first());
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public static void initializeSession(SessionState sessionState,
+ int sessionVersion,
+ BobAxolotlParameters parameters)
+ throws InvalidKeyException
+ {
+
+ try {
+ sessionState.setSessionVersion(sessionVersion);
+ sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey());
+ sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey());
+
+ ByteArrayOutputStream secrets = new ByteArrayOutputStream();
+
+ if (sessionVersion >= 3) {
+ secrets.write(getDiscontinuityBytes());
+ }
+
+ secrets.write(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(),
+ parameters.getOurSignedPreKey().getPrivateKey()));
+ secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(),
+ parameters.getOurIdentityKey().getPrivateKey()));
+ secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(),
+ parameters.getOurSignedPreKey().getPrivateKey()));
+
+ if (sessionVersion >= 3 && parameters.getOurOneTimePreKey().isPresent()) {
+ secrets.write(Curve.calculateAgreement(parameters.getTheirBaseKey(),
+ parameters.getOurOneTimePreKey().get().getPrivateKey()));
+ }
+
+ DerivedKeys derivedKeys = calculateDerivedKeys(sessionVersion, secrets.toByteArray());
+
+ sessionState.setSenderChain(parameters.getOurRatchetKey(), derivedKeys.getChainKey());
+ sessionState.setRootKey(derivedKeys.getRootKey());
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private static byte[] getDiscontinuityBytes() {
+ byte[] discontinuity = new byte[32];
+ Arrays.fill(discontinuity, (byte) 0xFF);
+ return discontinuity;
+ }
+
+ private static DerivedKeys calculateDerivedKeys(int sessionVersion, byte[] masterSecret) {
+ HKDF kdf = HKDF.createFor(sessionVersion);
+ byte[] derivedSecretBytes = kdf.deriveSecrets(masterSecret, "WhisperText".getBytes(), 64);
+ byte[][] derivedSecrets = ByteUtil.split(derivedSecretBytes, 32, 32);
+
+ return new DerivedKeys(new RootKey(kdf, derivedSecrets[0]),
+ new ChainKey(kdf, derivedSecrets[1], 0));
+ }
+
+ private static boolean isAlice(ECPublicKey ourKey, ECPublicKey theirKey) {
+ return ourKey.compareTo(theirKey) < 0;
+ }
+
+ private static class DerivedKeys {
+ private final RootKey rootKey;
+ private final ChainKey chainKey;
+
+ private DerivedKeys(RootKey rootKey, ChainKey chainKey) {
+ this.rootKey = rootKey;
+ this.chainKey = chainKey;
+ }
+
+ public RootKey getRootKey() {
+ return rootKey;
+ }
+
+ public ChainKey getChainKey() {
+ return chainKey;
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java
new file mode 100644
index 00000000..39f3a831
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.ratchet;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.kdf.DerivedRootSecrets;
+import org.whispersystems.libaxolotl.kdf.HKDF;
+import org.whispersystems.libaxolotl.util.ByteUtil;
+import org.whispersystems.libaxolotl.util.Pair;
+
+public class RootKey {
+
+ private final HKDF kdf;
+ private final byte[] key;
+
+ public RootKey(HKDF kdf, byte[] key) {
+ this.kdf = kdf;
+ this.key = key;
+ }
+
+ public byte[] getKeyBytes() {
+ return key;
+ }
+
+ public Pair<RootKey, ChainKey> createChain(ECPublicKey theirRatchetKey, ECKeyPair ourRatchetKey)
+ throws InvalidKeyException
+ {
+ byte[] sharedSecret = Curve.calculateAgreement(theirRatchetKey, ourRatchetKey.getPrivateKey());
+ byte[] derivedSecretBytes = kdf.deriveSecrets(sharedSecret, key, "WhisperRatchet".getBytes(), DerivedRootSecrets.SIZE);
+ DerivedRootSecrets derivedSecrets = new DerivedRootSecrets(derivedSecretBytes);
+
+ RootKey newRootKey = new RootKey(kdf, derivedSecrets.getRootKey());
+ ChainKey newChainKey = new ChainKey(kdf, derivedSecrets.getChainKey(), 0);
+
+ return new Pair<>(newRootKey, newChainKey);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java b/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java
new file mode 100644
index 00000000..7a63c45f
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java
@@ -0,0 +1,108 @@
+package org.whispersystems.libaxolotl.ratchet;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+
+public class SymmetricAxolotlParameters {
+
+ private final ECKeyPair ourBaseKey;
+ private final ECKeyPair ourRatchetKey;
+ private final IdentityKeyPair ourIdentityKey;
+
+ private final ECPublicKey theirBaseKey;
+ private final ECPublicKey theirRatchetKey;
+ private final IdentityKey theirIdentityKey;
+
+ SymmetricAxolotlParameters(ECKeyPair ourBaseKey, ECKeyPair ourRatchetKey,
+ IdentityKeyPair ourIdentityKey, ECPublicKey theirBaseKey,
+ ECPublicKey theirRatchetKey, IdentityKey theirIdentityKey)
+ {
+ this.ourBaseKey = ourBaseKey;
+ this.ourRatchetKey = ourRatchetKey;
+ this.ourIdentityKey = ourIdentityKey;
+ this.theirBaseKey = theirBaseKey;
+ this.theirRatchetKey = theirRatchetKey;
+ this.theirIdentityKey = theirIdentityKey;
+
+ if (ourBaseKey == null || ourRatchetKey == null || ourIdentityKey == null ||
+ theirBaseKey == null || theirRatchetKey == null || theirIdentityKey == null)
+ {
+ throw new IllegalArgumentException("Null values!");
+ }
+ }
+
+ public ECKeyPair getOurBaseKey() {
+ return ourBaseKey;
+ }
+
+ public ECKeyPair getOurRatchetKey() {
+ return ourRatchetKey;
+ }
+
+ public IdentityKeyPair getOurIdentityKey() {
+ return ourIdentityKey;
+ }
+
+ public ECPublicKey getTheirBaseKey() {
+ return theirBaseKey;
+ }
+
+ public ECPublicKey getTheirRatchetKey() {
+ return theirRatchetKey;
+ }
+
+ public IdentityKey getTheirIdentityKey() {
+ return theirIdentityKey;
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private ECKeyPair ourBaseKey;
+ private ECKeyPair ourRatchetKey;
+ private IdentityKeyPair ourIdentityKey;
+
+ private ECPublicKey theirBaseKey;
+ private ECPublicKey theirRatchetKey;
+ private IdentityKey theirIdentityKey;
+
+ public Builder setOurBaseKey(ECKeyPair ourBaseKey) {
+ this.ourBaseKey = ourBaseKey;
+ return this;
+ }
+
+ public Builder setOurRatchetKey(ECKeyPair ourRatchetKey) {
+ this.ourRatchetKey = ourRatchetKey;
+ return this;
+ }
+
+ public Builder setOurIdentityKey(IdentityKeyPair ourIdentityKey) {
+ this.ourIdentityKey = ourIdentityKey;
+ return this;
+ }
+
+ public Builder setTheirBaseKey(ECPublicKey theirBaseKey) {
+ this.theirBaseKey = theirBaseKey;
+ return this;
+ }
+
+ public Builder setTheirRatchetKey(ECPublicKey theirRatchetKey) {
+ this.theirRatchetKey = theirRatchetKey;
+ return this;
+ }
+
+ public Builder setTheirIdentityKey(IdentityKey theirIdentityKey) {
+ this.theirIdentityKey = theirIdentityKey;
+ return this;
+ }
+
+ public SymmetricAxolotlParameters create() {
+ return new SymmetricAxolotlParameters(ourBaseKey, ourRatchetKey, ourIdentityKey,
+ theirBaseKey, theirRatchetKey, theirIdentityKey);
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java b/src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java
new file mode 100644
index 00000000..2fda9a21
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java
@@ -0,0 +1,6 @@
+package org.whispersystems.libaxolotl.state;
+
+public interface AxolotlStore
+ extends IdentityKeyStore, PreKeyStore, SessionStore, SignedPreKeyStore
+{
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java b/src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java
new file mode 100644
index 00000000..d2024f78
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java
@@ -0,0 +1,57 @@
+package org.whispersystems.libaxolotl.state;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+
+/**
+ * Provides an interface to identity information.
+ *
+ * @author Moxie Marlinspike
+ */
+public interface IdentityKeyStore {
+
+ /**
+ * Get the local client's identity key pair.
+ *
+ * @return The local client's persistent identity key pair.
+ */
+ public IdentityKeyPair getIdentityKeyPair();
+
+ /**
+ * Return the local client's registration ID.
+ * <p>
+ * Clients should maintain a registration ID, a random number
+ * between 1 and 16380 that's generated once at install time.
+ *
+ * @return the local client's registration ID.
+ */
+ public int getLocalRegistrationId();
+
+ /**
+ * Save a remote client's identity key
+ * <p>
+ * Store a remote client's identity key as trusted.
+ *
+ * @param recipientId The recipient ID of the remote client.
+ * @param identityKey The remote client's identity key.
+ */
+ public void saveIdentity(long recipientId, IdentityKey identityKey);
+
+
+ /**
+ * Verify a remote client's identity key.
+ * <p>
+ * Determine whether a remote client's identity is trusted. Convention is
+ * that the TextSecure protocol is 'trust on first use.' This means that
+ * an identity key is considered 'trusted' if there is no entry for the recipient
+ * in the local store, or if it matches the saved key for a recipient in the local
+ * store. Only if it mismatches an entry in the local store is it considered
+ * 'untrusted.'
+ *
+ * @param recipientId The recipient ID of the remote client.
+ * @param identityKey The identity key to verify.
+ * @return true if trusted, false if untrusted.
+ */
+ public boolean isTrustedIdentity(long recipientId, IdentityKey identityKey);
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java b/src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java
new file mode 100644
index 00000000..772bcc14
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java
@@ -0,0 +1,96 @@
+package org.whispersystems.libaxolotl.state;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+
+/**
+ * A class that contains a remote PreKey and collection
+ * of associated items.
+ *
+ * @author Moxie Marlinspike
+ */
+public class PreKeyBundle {
+
+ private int registrationId;
+
+ private int deviceId;
+
+ private int preKeyId;
+ private ECPublicKey preKeyPublic;
+
+ private int signedPreKeyId;
+ private ECPublicKey signedPreKeyPublic;
+ private byte[] signedPreKeySignature;
+
+ private IdentityKey identityKey;
+
+ public PreKeyBundle(int registrationId, int deviceId, int preKeyId, ECPublicKey preKeyPublic,
+ int signedPreKeyId, ECPublicKey signedPreKeyPublic, byte[] signedPreKeySignature,
+ IdentityKey identityKey)
+ {
+ this.registrationId = registrationId;
+ this.deviceId = deviceId;
+ this.preKeyId = preKeyId;
+ this.preKeyPublic = preKeyPublic;
+ this.signedPreKeyId = signedPreKeyId;
+ this.signedPreKeyPublic = signedPreKeyPublic;
+ this.signedPreKeySignature = signedPreKeySignature;
+ this.identityKey = identityKey;
+ }
+
+ /**
+ * @return the device ID this PreKey belongs to.
+ */
+ public int getDeviceId() {
+ return deviceId;
+ }
+
+ /**
+ * @return the unique key ID for this PreKey.
+ */
+ public int getPreKeyId() {
+ return preKeyId;
+ }
+
+ /**
+ * @return the public key for this PreKey.
+ */
+ public ECPublicKey getPreKey() {
+ return preKeyPublic;
+ }
+
+ /**
+ * @return the unique key ID for this signed prekey.
+ */
+ public int getSignedPreKeyId() {
+ return signedPreKeyId;
+ }
+
+ /**
+ * @return the signed prekey for this PreKeyBundle.
+ */
+ public ECPublicKey getSignedPreKey() {
+ return signedPreKeyPublic;
+ }
+
+ /**
+ * @return the signature over the signed prekey.
+ */
+ public byte[] getSignedPreKeySignature() {
+ return signedPreKeySignature;
+ }
+
+ /**
+ * @return the {@link org.whispersystems.libaxolotl.IdentityKey} of this PreKeys owner.
+ */
+ public IdentityKey getIdentityKey() {
+ return identityKey;
+ }
+
+ /**
+ * @return the registration ID associated with this PreKey.
+ */
+ public int getRegistrationId() {
+ return registrationId;
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java b/src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java
new file mode 100644
index 00000000..0ea905f4
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java
@@ -0,0 +1,51 @@
+package org.whispersystems.libaxolotl.state;
+
+import com.google.protobuf.ByteString;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+
+import java.io.IOException;
+
+import static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure;
+
+public class PreKeyRecord {
+
+ private PreKeyRecordStructure structure;
+
+ public PreKeyRecord(int id, ECKeyPair keyPair) {
+ this.structure = PreKeyRecordStructure.newBuilder()
+ .setId(id)
+ .setPublicKey(ByteString.copyFrom(keyPair.getPublicKey()
+ .serialize()))
+ .setPrivateKey(ByteString.copyFrom(keyPair.getPrivateKey()
+ .serialize()))
+ .build();
+ }
+
+ public PreKeyRecord(byte[] serialized) throws IOException {
+ this.structure = PreKeyRecordStructure.parseFrom(serialized);
+ }
+
+ public int getId() {
+ return this.structure.getId();
+ }
+
+ public ECKeyPair getKeyPair() {
+ try {
+ ECPublicKey publicKey = Curve.decodePoint(this.structure.getPublicKey().toByteArray(), 0);
+ ECPrivateKey privateKey = Curve.decodePrivatePoint(this.structure.getPrivateKey().toByteArray());
+
+ return new ECKeyPair(publicKey, privateKey);
+ } catch (InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public byte[] serialize() {
+ return this.structure.toByteArray();
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java b/src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java
new file mode 100644
index 00000000..7dc5e626
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java
@@ -0,0 +1,42 @@
+package org.whispersystems.libaxolotl.state;
+
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+
+/**
+ * An interface describing the local storage of {@link PreKeyRecord}s.
+ *
+ * @author Moxie Marlinspike
+ */
+public interface PreKeyStore {
+
+ /**
+ * Load a local PreKeyRecord.
+ *
+ * @param preKeyId the ID of the local PreKeyRecord.
+ * @return the corresponding PreKeyRecord.
+ * @throws InvalidKeyIdException when there is no corresponding PreKeyRecord.
+ */
+ public PreKeyRecord loadPreKey(int preKeyId) throws InvalidKeyIdException;
+
+ /**
+ * Store a local PreKeyRecord.
+ *
+ * @param preKeyId the ID of the PreKeyRecord to store.
+ * @param record the PreKeyRecord.
+ */
+ public void storePreKey(int preKeyId, PreKeyRecord record);
+
+ /**
+ * @param preKeyId A PreKeyRecord ID.
+ * @return true if the store has a record for the preKeyId, otherwise false.
+ */
+ public boolean containsPreKey(int preKeyId);
+
+ /**
+ * Delete a PreKeyRecord from local storage.
+ *
+ * @param preKeyId The ID of the PreKeyRecord to remove.
+ */
+ public void removePreKey(int preKeyId);
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java b/src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java
new file mode 100644
index 00000000..76c64922
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java
@@ -0,0 +1,117 @@
+package org.whispersystems.libaxolotl.state;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure;
+import static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure;
+
+/**
+ * A SessionRecord encapsulates the state of an ongoing session.
+ *
+ * @author Moxie Marlinspike
+ */
+public class SessionRecord {
+
+ private static final int ARCHIVED_STATES_MAX_LENGTH = 40;
+
+ private SessionState sessionState = new SessionState();
+ private LinkedList<SessionState> previousStates = new LinkedList<>();
+ private boolean fresh = false;
+
+ public SessionRecord() {
+ this.fresh = true;
+ }
+
+ public SessionRecord(SessionState sessionState) {
+ this.sessionState = sessionState;
+ this.fresh = false;
+ }
+
+ public SessionRecord(byte[] serialized) throws IOException {
+ RecordStructure record = RecordStructure.parseFrom(serialized);
+ this.sessionState = new SessionState(record.getCurrentSession());
+ this.fresh = false;
+
+ for (SessionStructure previousStructure : record.getPreviousSessionsList()) {
+ previousStates.add(new SessionState(previousStructure));
+ }
+ }
+
+ public boolean hasSessionState(int version, byte[] aliceBaseKey) {
+ if (sessionState.getSessionVersion() == version &&
+ Arrays.equals(aliceBaseKey, sessionState.getAliceBaseKey()))
+ {
+ return true;
+ }
+
+ for (SessionState state : previousStates) {
+ if (state.getSessionVersion() == version &&
+ Arrays.equals(aliceBaseKey, state.getAliceBaseKey()))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public SessionState getSessionState() {
+ return sessionState;
+ }
+
+ /**
+ * @return the list of all currently maintained "previous" session states.
+ */
+ public List<SessionState> getPreviousSessionStates() {
+ return previousStates;
+ }
+
+
+ public boolean isFresh() {
+ return fresh;
+ }
+
+ /**
+ * Move the current {@link SessionState} into the list of "previous" session states,
+ * and replace the current {@link org.whispersystems.libaxolotl.state.SessionState}
+ * with a fresh reset instance.
+ */
+ public void archiveCurrentState() {
+ promoteState(new SessionState());
+ }
+
+ public void promoteState(SessionState promotedState) {
+ this.previousStates.addFirst(sessionState);
+ this.sessionState = promotedState;
+
+ if (previousStates.size() > ARCHIVED_STATES_MAX_LENGTH) {
+ previousStates.removeLast();
+ }
+ }
+
+ public void setState(SessionState sessionState) {
+ this.sessionState = sessionState;
+ }
+
+ /**
+ * @return a serialized version of the current SessionRecord.
+ */
+ public byte[] serialize() {
+ List<SessionStructure> previousStructures = new LinkedList<>();
+
+ for (SessionState previousState : previousStates) {
+ previousStructures.add(previousState.getStructure());
+ }
+
+ RecordStructure record = RecordStructure.newBuilder()
+ .setCurrentSession(sessionState.getStructure())
+ .addAllPreviousSessions(previousStructures)
+ .build();
+
+ return record.toByteArray();
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java b/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java
new file mode 100644
index 00000000..9b2b1e2a
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java
@@ -0,0 +1,509 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.whispersystems.libaxolotl.state;
+
+import android.util.Log;
+
+import com.google.protobuf.ByteString;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.kdf.HKDF;
+import org.whispersystems.libaxolotl.ratchet.ChainKey;
+import org.whispersystems.libaxolotl.ratchet.MessageKeys;
+import org.whispersystems.libaxolotl.ratchet.RootKey;
+import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain;
+import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange;
+import org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey;
+import org.whispersystems.libaxolotl.util.Pair;
+import org.whispersystems.libaxolotl.util.guava.Optional;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure;
+
+public class SessionState {
+
+ private SessionStructure sessionStructure;
+
+ public SessionState() {
+ this.sessionStructure = SessionStructure.newBuilder().build();
+ }
+
+ public SessionState(SessionStructure sessionStructure) {
+ this.sessionStructure = sessionStructure;
+ }
+
+ public SessionState(SessionState copy) {
+ this.sessionStructure = copy.sessionStructure.toBuilder().build();
+ }
+
+ public SessionStructure getStructure() {
+ return sessionStructure;
+ }
+
+ public byte[] getAliceBaseKey() {
+ return this.sessionStructure.getAliceBaseKey().toByteArray();
+ }
+
+ public void setAliceBaseKey(byte[] aliceBaseKey) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setAliceBaseKey(ByteString.copyFrom(aliceBaseKey))
+ .build();
+ }
+
+ public void setSessionVersion(int version) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setSessionVersion(version)
+ .build();
+ }
+
+ public int getSessionVersion() {
+ int sessionVersion = this.sessionStructure.getSessionVersion();
+
+ if (sessionVersion == 0) return 2;
+ else return sessionVersion;
+ }
+
+ public void setRemoteIdentityKey(IdentityKey identityKey) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setRemoteIdentityPublic(ByteString.copyFrom(identityKey.serialize()))
+ .build();
+ }
+
+ public void setLocalIdentityKey(IdentityKey identityKey) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setLocalIdentityPublic(ByteString.copyFrom(identityKey.serialize()))
+ .build();
+ }
+
+ public IdentityKey getRemoteIdentityKey() {
+ try {
+ if (!this.sessionStructure.hasRemoteIdentityPublic()) {
+ return null;
+ }
+
+ return new IdentityKey(this.sessionStructure.getRemoteIdentityPublic().toByteArray(), 0);
+ } catch (InvalidKeyException e) {
+ Log.w("SessionRecordV2", e);
+ return null;
+ }
+ }
+
+ public IdentityKey getLocalIdentityKey() {
+ try {
+ return new IdentityKey(this.sessionStructure.getLocalIdentityPublic().toByteArray(), 0);
+ } catch (InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public int getPreviousCounter() {
+ return sessionStructure.getPreviousCounter();
+ }
+
+ public void setPreviousCounter(int previousCounter) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setPreviousCounter(previousCounter)
+ .build();
+ }
+
+ public RootKey getRootKey() {
+ return new RootKey(HKDF.createFor(getSessionVersion()),
+ this.sessionStructure.getRootKey().toByteArray());
+ }
+
+ public void setRootKey(RootKey rootKey) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setRootKey(ByteString.copyFrom(rootKey.getKeyBytes()))
+ .build();
+ }
+
+ public ECPublicKey getSenderRatchetKey() {
+ try {
+ return Curve.decodePoint(sessionStructure.getSenderChain().getSenderRatchetKey().toByteArray(), 0);
+ } catch (InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public ECKeyPair getSenderRatchetKeyPair() {
+ ECPublicKey publicKey = getSenderRatchetKey();
+ ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getSenderChain()
+ .getSenderRatchetKeyPrivate()
+ .toByteArray());
+
+ return new ECKeyPair(publicKey, privateKey);
+ }
+
+ public boolean hasReceiverChain(ECPublicKey senderEphemeral) {
+ return getReceiverChain(senderEphemeral) != null;
+ }
+
+ public boolean hasSenderChain() {
+ return sessionStructure.hasSenderChain();
+ }
+
+ private Pair<Chain,Integer> getReceiverChain(ECPublicKey senderEphemeral) {
+ List<Chain> receiverChains = sessionStructure.getReceiverChainsList();
+ int index = 0;
+
+ for (Chain receiverChain : receiverChains) {
+ try {
+ ECPublicKey chainSenderRatchetKey = Curve.decodePoint(receiverChain.getSenderRatchetKey().toByteArray(), 0);
+
+ if (chainSenderRatchetKey.equals(senderEphemeral)) {
+ return new Pair<>(receiverChain,index);
+ }
+ } catch (InvalidKeyException e) {
+ Log.w("SessionRecordV2", e);
+ }
+
+ index++;
+ }
+
+ return null;
+ }
+
+ public ChainKey getReceiverChainKey(ECPublicKey senderEphemeral) {
+ Pair<Chain,Integer> receiverChainAndIndex = getReceiverChain(senderEphemeral);
+ Chain receiverChain = receiverChainAndIndex.first();
+
+ if (receiverChain == null) {
+ return null;
+ } else {
+ return new ChainKey(HKDF.createFor(getSessionVersion()),
+ receiverChain.getChainKey().getKey().toByteArray(),
+ receiverChain.getChainKey().getIndex());
+ }
+ }
+
+ public void addReceiverChain(ECPublicKey senderRatchetKey, ChainKey chainKey) {
+ Chain.ChainKey chainKeyStructure = Chain.ChainKey.newBuilder()
+ .setKey(ByteString.copyFrom(chainKey.getKey()))
+ .setIndex(chainKey.getIndex())
+ .build();
+
+ Chain chain = Chain.newBuilder()
+ .setChainKey(chainKeyStructure)
+ .setSenderRatchetKey(ByteString.copyFrom(senderRatchetKey.serialize()))
+ .build();
+
+ this.sessionStructure = this.sessionStructure.toBuilder().addReceiverChains(chain).build();
+
+ if (this.sessionStructure.getReceiverChainsList().size() > 5) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .removeReceiverChains(0)
+ .build();
+ }
+ }
+
+ public void setSenderChain(ECKeyPair senderRatchetKeyPair, ChainKey chainKey) {
+ Chain.ChainKey chainKeyStructure = Chain.ChainKey.newBuilder()
+ .setKey(ByteString.copyFrom(chainKey.getKey()))
+ .setIndex(chainKey.getIndex())
+ .build();
+
+ Chain senderChain = Chain.newBuilder()
+ .setSenderRatchetKey(ByteString.copyFrom(senderRatchetKeyPair.getPublicKey().serialize()))
+ .setSenderRatchetKeyPrivate(ByteString.copyFrom(senderRatchetKeyPair.getPrivateKey().serialize()))
+ .setChainKey(chainKeyStructure)
+ .build();
+
+ this.sessionStructure = this.sessionStructure.toBuilder().setSenderChain(senderChain).build();
+ }
+
+ public ChainKey getSenderChainKey() {
+ Chain.ChainKey chainKeyStructure = sessionStructure.getSenderChain().getChainKey();
+ return new ChainKey(HKDF.createFor(getSessionVersion()),
+ chainKeyStructure.getKey().toByteArray(), chainKeyStructure.getIndex());
+ }
+
+
+ public void setSenderChainKey(ChainKey nextChainKey) {
+ Chain.ChainKey chainKey = Chain.ChainKey.newBuilder()
+ .setKey(ByteString.copyFrom(nextChainKey.getKey()))
+ .setIndex(nextChainKey.getIndex())
+ .build();
+
+ Chain chain = sessionStructure.getSenderChain().toBuilder()
+ .setChainKey(chainKey).build();
+
+ this.sessionStructure = this.sessionStructure.toBuilder().setSenderChain(chain).build();
+ }
+
+ public boolean hasMessageKeys(ECPublicKey senderEphemeral, int counter) {
+ Pair<Chain,Integer> chainAndIndex = getReceiverChain(senderEphemeral);
+ Chain chain = chainAndIndex.first();
+
+ if (chain == null) {
+ return false;
+ }
+
+ List<Chain.MessageKey> messageKeyList = chain.getMessageKeysList();
+
+ for (Chain.MessageKey messageKey : messageKeyList) {
+ if (messageKey.getIndex() == counter) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public MessageKeys removeMessageKeys(ECPublicKey senderEphemeral, int counter) {
+ Pair<Chain,Integer> chainAndIndex = getReceiverChain(senderEphemeral);
+ Chain chain = chainAndIndex.first();
+
+ if (chain == null) {
+ return null;
+ }
+
+ List<Chain.MessageKey> messageKeyList = new LinkedList<>(chain.getMessageKeysList());
+ Iterator<Chain.MessageKey> messageKeyIterator = messageKeyList.iterator();
+ MessageKeys result = null;
+
+ while (messageKeyIterator.hasNext()) {
+ Chain.MessageKey messageKey = messageKeyIterator.next();
+
+ if (messageKey.getIndex() == counter) {
+ result = new MessageKeys(new SecretKeySpec(messageKey.getCipherKey().toByteArray(), "AES"),
+ new SecretKeySpec(messageKey.getMacKey().toByteArray(), "HmacSHA256"),
+ new IvParameterSpec(messageKey.getIv().toByteArray()),
+ messageKey.getIndex());
+
+ messageKeyIterator.remove();
+ break;
+ }
+ }
+
+ Chain updatedChain = chain.toBuilder().clearMessageKeys()
+ .addAllMessageKeys(messageKeyList)
+ .build();
+
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setReceiverChains(chainAndIndex.second(), updatedChain)
+ .build();
+
+ return result;
+ }
+
+ public void setMessageKeys(ECPublicKey senderEphemeral, MessageKeys messageKeys) {
+ Pair<Chain,Integer> chainAndIndex = getReceiverChain(senderEphemeral);
+ Chain chain = chainAndIndex.first();
+ Chain.MessageKey messageKeyStructure = Chain.MessageKey.newBuilder()
+ .setCipherKey(ByteString.copyFrom(messageKeys.getCipherKey().getEncoded()))
+ .setMacKey(ByteString.copyFrom(messageKeys.getMacKey().getEncoded()))
+ .setIndex(messageKeys.getCounter())
+ .setIv(ByteString.copyFrom(messageKeys.getIv().getIV()))
+ .build();
+
+ Chain updatedChain = chain.toBuilder()
+ .addMessageKeys(messageKeyStructure)
+ .build();
+
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setReceiverChains(chainAndIndex.second(), updatedChain)
+ .build();
+ }
+
+ public void setReceiverChainKey(ECPublicKey senderEphemeral, ChainKey chainKey) {
+ Pair<Chain,Integer> chainAndIndex = getReceiverChain(senderEphemeral);
+ Chain chain = chainAndIndex.first();
+
+ Chain.ChainKey chainKeyStructure = Chain.ChainKey.newBuilder()
+ .setKey(ByteString.copyFrom(chainKey.getKey()))
+ .setIndex(chainKey.getIndex())
+ .build();
+
+ Chain updatedChain = chain.toBuilder().setChainKey(chainKeyStructure).build();
+
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setReceiverChains(chainAndIndex.second(), updatedChain)
+ .build();
+ }
+
+ public void setPendingKeyExchange(int sequence,
+ ECKeyPair ourBaseKey,
+ ECKeyPair ourRatchetKey,
+ IdentityKeyPair ourIdentityKey)
+ {
+ PendingKeyExchange structure =
+ PendingKeyExchange.newBuilder()
+ .setSequence(sequence)
+ .setLocalBaseKey(ByteString.copyFrom(ourBaseKey.getPublicKey().serialize()))
+ .setLocalBaseKeyPrivate(ByteString.copyFrom(ourBaseKey.getPrivateKey().serialize()))
+ .setLocalRatchetKey(ByteString.copyFrom(ourRatchetKey.getPublicKey().serialize()))
+ .setLocalRatchetKeyPrivate(ByteString.copyFrom(ourRatchetKey.getPrivateKey().serialize()))
+ .setLocalIdentityKey(ByteString.copyFrom(ourIdentityKey.getPublicKey().serialize()))
+ .setLocalIdentityKeyPrivate(ByteString.copyFrom(ourIdentityKey.getPrivateKey().serialize()))
+ .build();
+
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setPendingKeyExchange(structure)
+ .build();
+ }
+
+ public int getPendingKeyExchangeSequence() {
+ return sessionStructure.getPendingKeyExchange().getSequence();
+ }
+
+ public ECKeyPair getPendingKeyExchangeBaseKey() throws InvalidKeyException {
+ ECPublicKey publicKey = Curve.decodePoint(sessionStructure.getPendingKeyExchange()
+ .getLocalBaseKey().toByteArray(), 0);
+
+ ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getPendingKeyExchange()
+ .getLocalBaseKeyPrivate()
+ .toByteArray());
+
+ return new ECKeyPair(publicKey, privateKey);
+ }
+
+ public ECKeyPair getPendingKeyExchangeRatchetKey() throws InvalidKeyException {
+ ECPublicKey publicKey = Curve.decodePoint(sessionStructure.getPendingKeyExchange()
+ .getLocalRatchetKey().toByteArray(), 0);
+
+ ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getPendingKeyExchange()
+ .getLocalRatchetKeyPrivate()
+ .toByteArray());
+
+ return new ECKeyPair(publicKey, privateKey);
+ }
+
+ public IdentityKeyPair getPendingKeyExchangeIdentityKey() throws InvalidKeyException {
+ IdentityKey publicKey = new IdentityKey(sessionStructure.getPendingKeyExchange()
+ .getLocalIdentityKey().toByteArray(), 0);
+
+ ECPrivateKey privateKey = Curve.decodePrivatePoint(sessionStructure.getPendingKeyExchange()
+ .getLocalIdentityKeyPrivate()
+ .toByteArray());
+
+ return new IdentityKeyPair(publicKey, privateKey);
+ }
+
+ public boolean hasPendingKeyExchange() {
+ return sessionStructure.hasPendingKeyExchange();
+ }
+
+ public void setUnacknowledgedPreKeyMessage(Optional<Integer> preKeyId, int signedPreKeyId, ECPublicKey baseKey) {
+ PendingPreKey.Builder pending = PendingPreKey.newBuilder()
+ .setSignedPreKeyId(signedPreKeyId)
+ .setBaseKey(ByteString.copyFrom(baseKey.serialize()));
+
+ if (preKeyId.isPresent()) {
+ pending.setPreKeyId(preKeyId.get());
+ }
+
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setPendingPreKey(pending.build())
+ .build();
+ }
+
+ public boolean hasUnacknowledgedPreKeyMessage() {
+ return this.sessionStructure.hasPendingPreKey();
+ }
+
+ public UnacknowledgedPreKeyMessageItems getUnacknowledgedPreKeyMessageItems() {
+ try {
+ Optional<Integer> preKeyId;
+
+ if (sessionStructure.getPendingPreKey().hasPreKeyId()) {
+ preKeyId = Optional.of(sessionStructure.getPendingPreKey().getPreKeyId());
+ } else {
+ preKeyId = Optional.absent();
+ }
+
+ return
+ new UnacknowledgedPreKeyMessageItems(preKeyId,
+ sessionStructure.getPendingPreKey().getSignedPreKeyId(),
+ Curve.decodePoint(sessionStructure.getPendingPreKey()
+ .getBaseKey()
+ .toByteArray(), 0));
+ } catch (InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public void clearUnacknowledgedPreKeyMessage() {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .clearPendingPreKey()
+ .build();
+ }
+
+ public void setRemoteRegistrationId(int registrationId) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setRemoteRegistrationId(registrationId)
+ .build();
+ }
+
+ public int getRemoteRegistrationId() {
+ return this.sessionStructure.getRemoteRegistrationId();
+ }
+
+ public void setLocalRegistrationId(int registrationId) {
+ this.sessionStructure = this.sessionStructure.toBuilder()
+ .setLocalRegistrationId(registrationId)
+ .build();
+ }
+
+ public int getLocalRegistrationId() {
+ return this.sessionStructure.getLocalRegistrationId();
+ }
+
+ public byte[] serialize() {
+ return sessionStructure.toByteArray();
+ }
+
+ public static class UnacknowledgedPreKeyMessageItems {
+ private final Optional<Integer> preKeyId;
+ private final int signedPreKeyId;
+ private final ECPublicKey baseKey;
+
+ public UnacknowledgedPreKeyMessageItems(Optional<Integer> preKeyId,
+ int signedPreKeyId,
+ ECPublicKey baseKey)
+ {
+ this.preKeyId = preKeyId;
+ this.signedPreKeyId = signedPreKeyId;
+ this.baseKey = baseKey;
+ }
+
+
+ public Optional<Integer> getPreKeyId() {
+ return preKeyId;
+ }
+
+ public int getSignedPreKeyId() {
+ return signedPreKeyId;
+ }
+
+ public ECPublicKey getBaseKey() {
+ return baseKey;
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java b/src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java
new file mode 100644
index 00000000..c5ad00b0
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java
@@ -0,0 +1,68 @@
+package org.whispersystems.libaxolotl.state;
+
+import java.util.List;
+
+/**
+ * The interface to the durable store of session state information
+ * for remote clients.
+ *
+ * @author Moxie Marlinspike
+ */
+public interface SessionStore {
+
+ /**
+ * Returns a copy of the {@link SessionRecord} corresponding to the recipientId + deviceId tuple,
+ * or a new SessionRecord if one does not currently exist.
+ * <p>
+ * It is important that implementations return a copy of the current durable information. The
+ * returned SessionRecord may be modified, but those changes should not have an effect on the
+ * durable session state (what is returned by subsequent calls to this method) without the
+ * store method being called here first.
+ *
+ * @param recipientId The recipientID of the remote client.
+ * @param deviceId The deviceID of the remote client.
+ * @return a copy of the SessionRecord corresponding to the recipientId + deviceId tuple, or
+ * a new SessionRecord if one does not currently exist.
+ */
+ public SessionRecord loadSession(long recipientId, int deviceId);
+
+ /**
+ * Returns all known devices with active sessions for a recipient
+ *
+ * @param recipientId the recipient ID.
+ * @return all known sub-devices with active sessions.
+ */
+ public List<Integer> getSubDeviceSessions(long recipientId);
+
+ /**
+ * Commit to storage the {@link SessionRecord} for a given recipientId + deviceId tuple.
+ * @param recipientId the recipient ID of the remote client.
+ * @param deviceId the device ID of the remote client.
+ * @param record the current SessionRecord for the remote client.
+ */
+ public void storeSession(long recipientId, int deviceId, SessionRecord record);
+
+ /**
+ * Determine whether there is a committed {@link SessionRecord} for a recipientId + deviceId tuple.
+ * @param recipientId the recipient ID of the remote client.
+ * @param deviceId the device ID of the remote client.
+ * @return true if a {@link SessionRecord} exists, false otherwise.
+ */
+ public boolean containsSession(long recipientId, int deviceId);
+
+ /**
+ * Remove a {@link SessionRecord} for a recipientId + deviceId tuple.
+ *
+ * @param recipientId the recipient ID of the remote client.
+ * @param deviceId the device ID of the remote client.
+ */
+ public void deleteSession(long recipientId, int deviceId);
+
+ /**
+ * Remove the {@link SessionRecord}s corresponding to all devices of a recipientId.
+ *
+ * @param recipientId the recipient ID of the remote client.
+ */
+ public void deleteAllSessions(long recipientId);
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java b/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java
new file mode 100644
index 00000000..f11f5cf1
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java
@@ -0,0 +1,61 @@
+package org.whispersystems.libaxolotl.state;
+
+import com.google.protobuf.ByteString;
+
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+
+import java.io.IOException;
+
+import static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure;
+
+public class SignedPreKeyRecord {
+
+ private SignedPreKeyRecordStructure structure;
+
+ public SignedPreKeyRecord(int id, long timestamp, ECKeyPair keyPair, byte[] signature) {
+ this.structure = SignedPreKeyRecordStructure.newBuilder()
+ .setId(id)
+ .setPublicKey(ByteString.copyFrom(keyPair.getPublicKey()
+ .serialize()))
+ .setPrivateKey(ByteString.copyFrom(keyPair.getPrivateKey()
+ .serialize()))
+ .setSignature(ByteString.copyFrom(signature))
+ .setTimestamp(timestamp)
+ .build();
+ }
+
+ public SignedPreKeyRecord(byte[] serialized) throws IOException {
+ this.structure = SignedPreKeyRecordStructure.parseFrom(serialized);
+ }
+
+ public int getId() {
+ return this.structure.getId();
+ }
+
+ public long getTimestamp() {
+ return this.structure.getTimestamp();
+ }
+
+ public ECKeyPair getKeyPair() {
+ try {
+ ECPublicKey publicKey = Curve.decodePoint(this.structure.getPublicKey().toByteArray(), 0);
+ ECPrivateKey privateKey = Curve.decodePrivatePoint(this.structure.getPrivateKey().toByteArray());
+
+ return new ECKeyPair(publicKey, privateKey);
+ } catch (InvalidKeyException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public byte[] getSignature() {
+ return this.structure.getSignature().toByteArray();
+ }
+
+ public byte[] serialize() {
+ return this.structure.toByteArray();
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java b/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java
new file mode 100644
index 00000000..c828bf23
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java
@@ -0,0 +1,47 @@
+package org.whispersystems.libaxolotl.state;
+
+import org.whispersystems.libaxolotl.InvalidKeyIdException;
+
+import java.util.List;
+
+public interface SignedPreKeyStore {
+
+
+ /**
+ * Load a local SignedPreKeyRecord.
+ *
+ * @param signedPreKeyId the ID of the local SignedPreKeyRecord.
+ * @return the corresponding SignedPreKeyRecord.
+ * @throws InvalidKeyIdException when there is no corresponding SignedPreKeyRecord.
+ */
+ public SignedPreKeyRecord loadSignedPreKey(int signedPreKeyId) throws InvalidKeyIdException;
+
+ /**
+ * Load all local SignedPreKeyRecords.
+ *
+ * @return All stored SignedPreKeyRecords.
+ */
+ public List<SignedPreKeyRecord> loadSignedPreKeys();
+
+ /**
+ * Store a local SignedPreKeyRecord.
+ *
+ * @param signedPreKeyId the ID of the SignedPreKeyRecord to store.
+ * @param record the SignedPreKeyRecord.
+ */
+ public void storeSignedPreKey(int signedPreKeyId, SignedPreKeyRecord record);
+
+ /**
+ * @param signedPreKeyId A SignedPreKeyRecord ID.
+ * @return true if the store has a record for the signedPreKeyId, otherwise false.
+ */
+ public boolean containsSignedPreKey(int signedPreKeyId);
+
+ /**
+ * Delete a SignedPreKeyRecord from local storage.
+ *
+ * @param signedPreKeyId The ID of the SignedPreKeyRecord to remove.
+ */
+ public void removeSignedPreKey(int signedPreKeyId);
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java b/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java
new file mode 100644
index 00000000..b3e3e0e6
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java
@@ -0,0 +1,11779 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: LocalStorageProtocol.proto
+
+package org.whispersystems.libaxolotl.state;
+
+public final class StorageProtos {
+ private StorageProtos() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ }
+ public interface SessionStructureOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 sessionVersion = 1;
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ boolean hasSessionVersion();
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ int getSessionVersion();
+
+ // optional bytes localIdentityPublic = 2;
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ boolean hasLocalIdentityPublic();
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ com.google.protobuf.ByteString getLocalIdentityPublic();
+
+ // optional bytes remoteIdentityPublic = 3;
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ boolean hasRemoteIdentityPublic();
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ com.google.protobuf.ByteString getRemoteIdentityPublic();
+
+ // optional bytes rootKey = 4;
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ boolean hasRootKey();
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ com.google.protobuf.ByteString getRootKey();
+
+ // optional uint32 previousCounter = 5;
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ boolean hasPreviousCounter();
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ int getPreviousCounter();
+
+ // optional .textsecure.SessionStructure.Chain senderChain = 6;
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ boolean hasSenderChain();
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain getSenderChain();
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder getSenderChainOrBuilder();
+
+ // repeated .textsecure.SessionStructure.Chain receiverChains = 7;
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain>
+ getReceiverChainsList();
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain getReceiverChains(int index);
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ int getReceiverChainsCount();
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder>
+ getReceiverChainsOrBuilderList();
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder getReceiverChainsOrBuilder(
+ int index);
+
+ // optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ boolean hasPendingKeyExchange();
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange getPendingKeyExchange();
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchangeOrBuilder getPendingKeyExchangeOrBuilder();
+
+ // optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ boolean hasPendingPreKey();
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey getPendingPreKey();
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKeyOrBuilder getPendingPreKeyOrBuilder();
+
+ // optional uint32 remoteRegistrationId = 10;
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ boolean hasRemoteRegistrationId();
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ int getRemoteRegistrationId();
+
+ // optional uint32 localRegistrationId = 11;
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ boolean hasLocalRegistrationId();
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ int getLocalRegistrationId();
+
+ // optional bool needsRefresh = 12;
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ boolean hasNeedsRefresh();
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ boolean getNeedsRefresh();
+
+ // optional bytes aliceBaseKey = 13;
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ boolean hasAliceBaseKey();
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ com.google.protobuf.ByteString getAliceBaseKey();
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure}
+ */
+ public static final class SessionStructure extends
+ com.google.protobuf.GeneratedMessage
+ implements SessionStructureOrBuilder {
+ // Use SessionStructure.newBuilder() to construct.
+ private SessionStructure(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SessionStructure(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SessionStructure defaultInstance;
+ public static SessionStructure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SessionStructure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SessionStructure(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ sessionVersion_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ localIdentityPublic_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ remoteIdentityPublic_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ rootKey_ = input.readBytes();
+ break;
+ }
+ case 40: {
+ bitField0_ |= 0x00000010;
+ previousCounter_ = input.readUInt32();
+ break;
+ }
+ case 50: {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ subBuilder = senderChain_.toBuilder();
+ }
+ senderChain_ = input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(senderChain_);
+ senderChain_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000020;
+ break;
+ }
+ case 58: {
+ if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
+ receiverChains_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain>();
+ mutable_bitField0_ |= 0x00000040;
+ }
+ receiverChains_.add(input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.PARSER, extensionRegistry));
+ break;
+ }
+ case 66: {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ subBuilder = pendingKeyExchange_.toBuilder();
+ }
+ pendingKeyExchange_ = input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(pendingKeyExchange_);
+ pendingKeyExchange_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000040;
+ break;
+ }
+ case 74: {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ subBuilder = pendingPreKey_.toBuilder();
+ }
+ pendingPreKey_ = input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(pendingPreKey_);
+ pendingPreKey_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000080;
+ break;
+ }
+ case 80: {
+ bitField0_ |= 0x00000100;
+ remoteRegistrationId_ = input.readUInt32();
+ break;
+ }
+ case 88: {
+ bitField0_ |= 0x00000200;
+ localRegistrationId_ = input.readUInt32();
+ break;
+ }
+ case 96: {
+ bitField0_ |= 0x00000400;
+ needsRefresh_ = input.readBool();
+ break;
+ }
+ case 106: {
+ bitField0_ |= 0x00000800;
+ aliceBaseKey_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
+ receiverChains_ = java.util.Collections.unmodifiableList(receiverChains_);
+ }
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SessionStructure> PARSER =
+ new com.google.protobuf.AbstractParser<SessionStructure>() {
+ public SessionStructure parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SessionStructure(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SessionStructure> getParserForType() {
+ return PARSER;
+ }
+
+ public interface ChainOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional bytes senderRatchetKey = 1;
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ boolean hasSenderRatchetKey();
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ com.google.protobuf.ByteString getSenderRatchetKey();
+
+ // optional bytes senderRatchetKeyPrivate = 2;
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ boolean hasSenderRatchetKeyPrivate();
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ com.google.protobuf.ByteString getSenderRatchetKeyPrivate();
+
+ // optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ boolean hasChainKey();
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey getChainKey();
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKeyOrBuilder getChainKeyOrBuilder();
+
+ // repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey>
+ getMessageKeysList();
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey getMessageKeys(int index);
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ int getMessageKeysCount();
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder>
+ getMessageKeysOrBuilderList();
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder getMessageKeysOrBuilder(
+ int index);
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.Chain}
+ */
+ public static final class Chain extends
+ com.google.protobuf.GeneratedMessage
+ implements ChainOrBuilder {
+ // Use Chain.newBuilder() to construct.
+ private Chain(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private Chain(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final Chain defaultInstance;
+ public static Chain getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public Chain getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private Chain(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ senderRatchetKey_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ senderRatchetKeyPrivate_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ subBuilder = chainKey_.toBuilder();
+ }
+ chainKey_ = input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(chainKey_);
+ chainKey_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000004;
+ break;
+ }
+ case 34: {
+ if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+ messageKeys_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey>();
+ mutable_bitField0_ |= 0x00000008;
+ }
+ messageKeys_.add(input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.PARSER, extensionRegistry));
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+ messageKeys_ = java.util.Collections.unmodifiableList(messageKeys_);
+ }
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<Chain> PARSER =
+ new com.google.protobuf.AbstractParser<Chain>() {
+ public Chain parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new Chain(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<Chain> getParserForType() {
+ return PARSER;
+ }
+
+ public interface ChainKeyOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 index = 1;
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ boolean hasIndex();
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ int getIndex();
+
+ // optional bytes key = 2;
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ boolean hasKey();
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ com.google.protobuf.ByteString getKey();
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.Chain.ChainKey}
+ */
+ public static final class ChainKey extends
+ com.google.protobuf.GeneratedMessage
+ implements ChainKeyOrBuilder {
+ // Use ChainKey.newBuilder() to construct.
+ private ChainKey(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private ChainKey(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final ChainKey defaultInstance;
+ public static ChainKey getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public ChainKey getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private ChainKey(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ index_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ key_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_ChainKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_ChainKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<ChainKey> PARSER =
+ new com.google.protobuf.AbstractParser<ChainKey>() {
+ public ChainKey parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new ChainKey(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<ChainKey> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 index = 1;
+ public static final int INDEX_FIELD_NUMBER = 1;
+ private int index_;
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public boolean hasIndex() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public int getIndex() {
+ return index_;
+ }
+
+ // optional bytes key = 2;
+ public static final int KEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString key_;
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ public boolean hasKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ public com.google.protobuf.ByteString getKey() {
+ return key_;
+ }
+
+ private void initFields() {
+ index_ = 0;
+ key_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, index_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, key_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, index_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, key_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.Chain.ChainKey}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKeyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_ChainKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_ChainKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ index_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ key_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_ChainKey_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey result = new org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.index_ = index_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.key_ = key_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance()) return this;
+ if (other.hasIndex()) {
+ setIndex(other.getIndex());
+ }
+ if (other.hasKey()) {
+ setKey(other.getKey());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 index = 1;
+ private int index_ ;
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public boolean hasIndex() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public int getIndex() {
+ return index_;
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public Builder setIndex(int value) {
+ bitField0_ |= 0x00000001;
+ index_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public Builder clearIndex() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ index_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes key = 2;
+ private com.google.protobuf.ByteString key_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ public boolean hasKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ public com.google.protobuf.ByteString getKey() {
+ return key_;
+ }
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ public Builder setKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ key_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes key = 2;</code>
+ */
+ public Builder clearKey() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ key_ = getDefaultInstance().getKey();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SessionStructure.Chain.ChainKey)
+ }
+
+ static {
+ defaultInstance = new ChainKey(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SessionStructure.Chain.ChainKey)
+ }
+
+ public interface MessageKeyOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 index = 1;
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ boolean hasIndex();
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ int getIndex();
+
+ // optional bytes cipherKey = 2;
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ boolean hasCipherKey();
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getCipherKey();
+
+ // optional bytes macKey = 3;
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ boolean hasMacKey();
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ com.google.protobuf.ByteString getMacKey();
+
+ // optional bytes iv = 4;
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ boolean hasIv();
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ com.google.protobuf.ByteString getIv();
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.Chain.MessageKey}
+ */
+ public static final class MessageKey extends
+ com.google.protobuf.GeneratedMessage
+ implements MessageKeyOrBuilder {
+ // Use MessageKey.newBuilder() to construct.
+ private MessageKey(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private MessageKey(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final MessageKey defaultInstance;
+ public static MessageKey getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public MessageKey getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private MessageKey(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ index_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ cipherKey_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ macKey_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ iv_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_MessageKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_MessageKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<MessageKey> PARSER =
+ new com.google.protobuf.AbstractParser<MessageKey>() {
+ public MessageKey parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new MessageKey(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<MessageKey> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 index = 1;
+ public static final int INDEX_FIELD_NUMBER = 1;
+ private int index_;
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public boolean hasIndex() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public int getIndex() {
+ return index_;
+ }
+
+ // optional bytes cipherKey = 2;
+ public static final int CIPHERKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString cipherKey_;
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ public boolean hasCipherKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getCipherKey() {
+ return cipherKey_;
+ }
+
+ // optional bytes macKey = 3;
+ public static final int MACKEY_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString macKey_;
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ public boolean hasMacKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getMacKey() {
+ return macKey_;
+ }
+
+ // optional bytes iv = 4;
+ public static final int IV_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString iv_;
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ public boolean hasIv() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ public com.google.protobuf.ByteString getIv() {
+ return iv_;
+ }
+
+ private void initFields() {
+ index_ = 0;
+ cipherKey_ = com.google.protobuf.ByteString.EMPTY;
+ macKey_ = com.google.protobuf.ByteString.EMPTY;
+ iv_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, index_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, cipherKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, macKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, iv_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, index_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, cipherKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, macKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, iv_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.Chain.MessageKey}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_MessageKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_MessageKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ index_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ cipherKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ macKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ iv_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_MessageKey_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey result = new org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.index_ = index_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.cipherKey_ = cipherKey_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.macKey_ = macKey_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.iv_ = iv_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.getDefaultInstance()) return this;
+ if (other.hasIndex()) {
+ setIndex(other.getIndex());
+ }
+ if (other.hasCipherKey()) {
+ setCipherKey(other.getCipherKey());
+ }
+ if (other.hasMacKey()) {
+ setMacKey(other.getMacKey());
+ }
+ if (other.hasIv()) {
+ setIv(other.getIv());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 index = 1;
+ private int index_ ;
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public boolean hasIndex() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public int getIndex() {
+ return index_;
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public Builder setIndex(int value) {
+ bitField0_ |= 0x00000001;
+ index_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 index = 1;</code>
+ */
+ public Builder clearIndex() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ index_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes cipherKey = 2;
+ private com.google.protobuf.ByteString cipherKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ public boolean hasCipherKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getCipherKey() {
+ return cipherKey_;
+ }
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ public Builder setCipherKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ cipherKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes cipherKey = 2;</code>
+ */
+ public Builder clearCipherKey() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ cipherKey_ = getDefaultInstance().getCipherKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes macKey = 3;
+ private com.google.protobuf.ByteString macKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ public boolean hasMacKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getMacKey() {
+ return macKey_;
+ }
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ public Builder setMacKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ macKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes macKey = 3;</code>
+ */
+ public Builder clearMacKey() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ macKey_ = getDefaultInstance().getMacKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes iv = 4;
+ private com.google.protobuf.ByteString iv_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ public boolean hasIv() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ public com.google.protobuf.ByteString getIv() {
+ return iv_;
+ }
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ public Builder setIv(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ iv_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes iv = 4;</code>
+ */
+ public Builder clearIv() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ iv_ = getDefaultInstance().getIv();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SessionStructure.Chain.MessageKey)
+ }
+
+ static {
+ defaultInstance = new MessageKey(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SessionStructure.Chain.MessageKey)
+ }
+
+ private int bitField0_;
+ // optional bytes senderRatchetKey = 1;
+ public static final int SENDERRATCHETKEY_FIELD_NUMBER = 1;
+ private com.google.protobuf.ByteString senderRatchetKey_;
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ public boolean hasSenderRatchetKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ public com.google.protobuf.ByteString getSenderRatchetKey() {
+ return senderRatchetKey_;
+ }
+
+ // optional bytes senderRatchetKeyPrivate = 2;
+ public static final int SENDERRATCHETKEYPRIVATE_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString senderRatchetKeyPrivate_;
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ public boolean hasSenderRatchetKeyPrivate() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ public com.google.protobuf.ByteString getSenderRatchetKeyPrivate() {
+ return senderRatchetKeyPrivate_;
+ }
+
+ // optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;
+ public static final int CHAINKEY_FIELD_NUMBER = 3;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey chainKey_;
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public boolean hasChainKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey getChainKey() {
+ return chainKey_;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKeyOrBuilder getChainKeyOrBuilder() {
+ return chainKey_;
+ }
+
+ // repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;
+ public static final int MESSAGEKEYS_FIELD_NUMBER = 4;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey> messageKeys_;
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey> getMessageKeysList() {
+ return messageKeys_;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder>
+ getMessageKeysOrBuilderList() {
+ return messageKeys_;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public int getMessageKeysCount() {
+ return messageKeys_.size();
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey getMessageKeys(int index) {
+ return messageKeys_.get(index);
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder getMessageKeysOrBuilder(
+ int index) {
+ return messageKeys_.get(index);
+ }
+
+ private void initFields() {
+ senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance();
+ messageKeys_ = java.util.Collections.emptyList();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, senderRatchetKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, senderRatchetKeyPrivate_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, chainKey_);
+ }
+ for (int i = 0; i < messageKeys_.size(); i++) {
+ output.writeMessage(4, messageKeys_.get(i));
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, senderRatchetKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, senderRatchetKeyPrivate_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, chainKey_);
+ }
+ for (int i = 0; i < messageKeys_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, messageKeys_.get(i));
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.Chain}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ getChainKeyFieldBuilder();
+ getMessageKeysFieldBuilder();
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ if (chainKeyBuilder_ == null) {
+ chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance();
+ } else {
+ chainKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000004);
+ if (messageKeysBuilder_ == null) {
+ messageKeys_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ messageKeysBuilder_.clear();
+ }
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_Chain_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain result = new org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.senderRatchetKey_ = senderRatchetKey_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.senderRatchetKeyPrivate_ = senderRatchetKeyPrivate_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ if (chainKeyBuilder_ == null) {
+ result.chainKey_ = chainKey_;
+ } else {
+ result.chainKey_ = chainKeyBuilder_.build();
+ }
+ if (messageKeysBuilder_ == null) {
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ messageKeys_ = java.util.Collections.unmodifiableList(messageKeys_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.messageKeys_ = messageKeys_;
+ } else {
+ result.messageKeys_ = messageKeysBuilder_.build();
+ }
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ 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.hasSenderRatchetKey()) {
+ setSenderRatchetKey(other.getSenderRatchetKey());
+ }
+ if (other.hasSenderRatchetKeyPrivate()) {
+ setSenderRatchetKeyPrivate(other.getSenderRatchetKeyPrivate());
+ }
+ if (other.hasChainKey()) {
+ mergeChainKey(other.getChainKey());
+ }
+ if (messageKeysBuilder_ == null) {
+ if (!other.messageKeys_.isEmpty()) {
+ if (messageKeys_.isEmpty()) {
+ messageKeys_ = other.messageKeys_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensureMessageKeysIsMutable();
+ messageKeys_.addAll(other.messageKeys_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.messageKeys_.isEmpty()) {
+ if (messageKeysBuilder_.isEmpty()) {
+ messageKeysBuilder_.dispose();
+ messageKeysBuilder_ = null;
+ messageKeys_ = other.messageKeys_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ messageKeysBuilder_ =
+ com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+ getMessageKeysFieldBuilder() : null;
+ } else {
+ messageKeysBuilder_.addAllMessages(other.messageKeys_);
+ }
+ }
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional bytes senderRatchetKey = 1;
+ private com.google.protobuf.ByteString senderRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ public boolean hasSenderRatchetKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ public com.google.protobuf.ByteString getSenderRatchetKey() {
+ return senderRatchetKey_;
+ }
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ public Builder setSenderRatchetKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ senderRatchetKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes senderRatchetKey = 1;</code>
+ */
+ public Builder clearSenderRatchetKey() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ senderRatchetKey_ = getDefaultInstance().getSenderRatchetKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes senderRatchetKeyPrivate = 2;
+ private com.google.protobuf.ByteString senderRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ public boolean hasSenderRatchetKeyPrivate() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ public com.google.protobuf.ByteString getSenderRatchetKeyPrivate() {
+ return senderRatchetKeyPrivate_;
+ }
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ public Builder setSenderRatchetKeyPrivate(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ senderRatchetKeyPrivate_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes senderRatchetKeyPrivate = 2;</code>
+ */
+ public Builder clearSenderRatchetKeyPrivate() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ senderRatchetKeyPrivate_ = getDefaultInstance().getSenderRatchetKeyPrivate();
+ onChanged();
+ return this;
+ }
+
+ // optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKeyOrBuilder> chainKeyBuilder_;
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public boolean hasChainKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey getChainKey() {
+ if (chainKeyBuilder_ == null) {
+ return chainKey_;
+ } else {
+ return chainKeyBuilder_.getMessage();
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public Builder setChainKey(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey value) {
+ if (chainKeyBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ chainKey_ = value;
+ onChanged();
+ } else {
+ chainKeyBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public Builder setChainKey(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder builderForValue) {
+ if (chainKeyBuilder_ == null) {
+ chainKey_ = builderForValue.build();
+ onChanged();
+ } else {
+ chainKeyBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public Builder mergeChainKey(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey value) {
+ if (chainKeyBuilder_ == null) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ chainKey_ != org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance()) {
+ chainKey_ =
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.newBuilder(chainKey_).mergeFrom(value).buildPartial();
+ } else {
+ chainKey_ = value;
+ }
+ onChanged();
+ } else {
+ chainKeyBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public Builder clearChainKey() {
+ if (chainKeyBuilder_ == null) {
+ chainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.getDefaultInstance();
+ onChanged();
+ } else {
+ chainKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder getChainKeyBuilder() {
+ bitField0_ |= 0x00000004;
+ onChanged();
+ return getChainKeyFieldBuilder().getBuilder();
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKeyOrBuilder getChainKeyOrBuilder() {
+ if (chainKeyBuilder_ != null) {
+ return chainKeyBuilder_.getMessageOrBuilder();
+ } else {
+ return chainKey_;
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain.ChainKey chainKey = 3;</code>
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKeyOrBuilder>
+ getChainKeyFieldBuilder() {
+ if (chainKeyBuilder_ == null) {
+ chainKeyBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.ChainKeyOrBuilder>(
+ chainKey_,
+ getParentForChildren(),
+ isClean());
+ chainKey_ = null;
+ }
+ return chainKeyBuilder_;
+ }
+
+ // repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey> messageKeys_ =
+ java.util.Collections.emptyList();
+ private void ensureMessageKeysIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ messageKeys_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey>(messageKeys_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder> messageKeysBuilder_;
+
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey> getMessageKeysList() {
+ if (messageKeysBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(messageKeys_);
+ } else {
+ return messageKeysBuilder_.getMessageList();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public int getMessageKeysCount() {
+ if (messageKeysBuilder_ == null) {
+ return messageKeys_.size();
+ } else {
+ return messageKeysBuilder_.getCount();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey getMessageKeys(int index) {
+ if (messageKeysBuilder_ == null) {
+ return messageKeys_.get(index);
+ } else {
+ return messageKeysBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder setMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey value) {
+ if (messageKeysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureMessageKeysIsMutable();
+ messageKeys_.set(index, value);
+ onChanged();
+ } else {
+ messageKeysBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder setMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder builderForValue) {
+ if (messageKeysBuilder_ == null) {
+ ensureMessageKeysIsMutable();
+ messageKeys_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ messageKeysBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder addMessageKeys(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey value) {
+ if (messageKeysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureMessageKeysIsMutable();
+ messageKeys_.add(value);
+ onChanged();
+ } else {
+ messageKeysBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder addMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey value) {
+ if (messageKeysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureMessageKeysIsMutable();
+ messageKeys_.add(index, value);
+ onChanged();
+ } else {
+ messageKeysBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder addMessageKeys(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder builderForValue) {
+ if (messageKeysBuilder_ == null) {
+ ensureMessageKeysIsMutable();
+ messageKeys_.add(builderForValue.build());
+ onChanged();
+ } else {
+ messageKeysBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder addMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder builderForValue) {
+ if (messageKeysBuilder_ == null) {
+ ensureMessageKeysIsMutable();
+ messageKeys_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ messageKeysBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder addAllMessageKeys(
+ java.lang.Iterable<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey> values) {
+ if (messageKeysBuilder_ == null) {
+ ensureMessageKeysIsMutable();
+ super.addAll(values, messageKeys_);
+ onChanged();
+ } else {
+ messageKeysBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder clearMessageKeys() {
+ if (messageKeysBuilder_ == null) {
+ messageKeys_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ onChanged();
+ } else {
+ messageKeysBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public Builder removeMessageKeys(int index) {
+ if (messageKeysBuilder_ == null) {
+ ensureMessageKeysIsMutable();
+ messageKeys_.remove(index);
+ onChanged();
+ } else {
+ messageKeysBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder getMessageKeysBuilder(
+ int index) {
+ return getMessageKeysFieldBuilder().getBuilder(index);
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder getMessageKeysOrBuilder(
+ int index) {
+ if (messageKeysBuilder_ == null) {
+ return messageKeys_.get(index); } else {
+ return messageKeysBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder>
+ getMessageKeysOrBuilderList() {
+ if (messageKeysBuilder_ != null) {
+ return messageKeysBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(messageKeys_);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder addMessageKeysBuilder() {
+ return getMessageKeysFieldBuilder().addBuilder(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder addMessageKeysBuilder(
+ int index) {
+ return getMessageKeysFieldBuilder().addBuilder(
+ index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain.MessageKey messageKeys = 4;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder>
+ getMessageKeysBuilderList() {
+ return getMessageKeysFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder>
+ getMessageKeysFieldBuilder() {
+ if (messageKeysBuilder_ == null) {
+ messageKeysBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.MessageKeyOrBuilder>(
+ messageKeys_,
+ ((bitField0_ & 0x00000008) == 0x00000008),
+ getParentForChildren(),
+ isClean());
+ messageKeys_ = null;
+ }
+ return messageKeysBuilder_;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SessionStructure.Chain)
+ }
+
+ static {
+ defaultInstance = new Chain(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SessionStructure.Chain)
+ }
+
+ public interface PendingKeyExchangeOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 sequence = 1;
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ boolean hasSequence();
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ int getSequence();
+
+ // optional bytes localBaseKey = 2;
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ boolean hasLocalBaseKey();
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getLocalBaseKey();
+
+ // optional bytes localBaseKeyPrivate = 3;
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ boolean hasLocalBaseKeyPrivate();
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ com.google.protobuf.ByteString getLocalBaseKeyPrivate();
+
+ // optional bytes localRatchetKey = 4;
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ boolean hasLocalRatchetKey();
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ com.google.protobuf.ByteString getLocalRatchetKey();
+
+ // optional bytes localRatchetKeyPrivate = 5;
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ boolean hasLocalRatchetKeyPrivate();
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ com.google.protobuf.ByteString getLocalRatchetKeyPrivate();
+
+ // optional bytes localIdentityKey = 7;
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ boolean hasLocalIdentityKey();
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ com.google.protobuf.ByteString getLocalIdentityKey();
+
+ // optional bytes localIdentityKeyPrivate = 8;
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ boolean hasLocalIdentityKeyPrivate();
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ com.google.protobuf.ByteString getLocalIdentityKeyPrivate();
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.PendingKeyExchange}
+ */
+ public static final class PendingKeyExchange extends
+ com.google.protobuf.GeneratedMessage
+ implements PendingKeyExchangeOrBuilder {
+ // Use PendingKeyExchange.newBuilder() to construct.
+ private PendingKeyExchange(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private PendingKeyExchange(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final PendingKeyExchange defaultInstance;
+ public static PendingKeyExchange getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PendingKeyExchange getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private PendingKeyExchange(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ sequence_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ localBaseKey_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ localBaseKeyPrivate_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ localRatchetKey_ = input.readBytes();
+ break;
+ }
+ case 42: {
+ bitField0_ |= 0x00000010;
+ localRatchetKeyPrivate_ = input.readBytes();
+ break;
+ }
+ case 58: {
+ bitField0_ |= 0x00000020;
+ localIdentityKey_ = input.readBytes();
+ break;
+ }
+ case 66: {
+ bitField0_ |= 0x00000040;
+ localIdentityKeyPrivate_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingKeyExchange_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<PendingKeyExchange> PARSER =
+ new com.google.protobuf.AbstractParser<PendingKeyExchange>() {
+ public PendingKeyExchange parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new PendingKeyExchange(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<PendingKeyExchange> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 sequence = 1;
+ public static final int SEQUENCE_FIELD_NUMBER = 1;
+ private int sequence_;
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ public boolean hasSequence() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ public int getSequence() {
+ return sequence_;
+ }
+
+ // optional bytes localBaseKey = 2;
+ public static final int LOCALBASEKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString localBaseKey_;
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ public boolean hasLocalBaseKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getLocalBaseKey() {
+ return localBaseKey_;
+ }
+
+ // optional bytes localBaseKeyPrivate = 3;
+ public static final int LOCALBASEKEYPRIVATE_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString localBaseKeyPrivate_;
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ public boolean hasLocalBaseKeyPrivate() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ public com.google.protobuf.ByteString getLocalBaseKeyPrivate() {
+ return localBaseKeyPrivate_;
+ }
+
+ // optional bytes localRatchetKey = 4;
+ public static final int LOCALRATCHETKEY_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString localRatchetKey_;
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ public boolean hasLocalRatchetKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getLocalRatchetKey() {
+ return localRatchetKey_;
+ }
+
+ // optional bytes localRatchetKeyPrivate = 5;
+ public static final int LOCALRATCHETKEYPRIVATE_FIELD_NUMBER = 5;
+ private com.google.protobuf.ByteString localRatchetKeyPrivate_;
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ public boolean hasLocalRatchetKeyPrivate() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ public com.google.protobuf.ByteString getLocalRatchetKeyPrivate() {
+ return localRatchetKeyPrivate_;
+ }
+
+ // optional bytes localIdentityKey = 7;
+ public static final int LOCALIDENTITYKEY_FIELD_NUMBER = 7;
+ private com.google.protobuf.ByteString localIdentityKey_;
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ public boolean hasLocalIdentityKey() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ public com.google.protobuf.ByteString getLocalIdentityKey() {
+ return localIdentityKey_;
+ }
+
+ // optional bytes localIdentityKeyPrivate = 8;
+ public static final int LOCALIDENTITYKEYPRIVATE_FIELD_NUMBER = 8;
+ private com.google.protobuf.ByteString localIdentityKeyPrivate_;
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ public boolean hasLocalIdentityKeyPrivate() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ public com.google.protobuf.ByteString getLocalIdentityKeyPrivate() {
+ return localIdentityKeyPrivate_;
+ }
+
+ private void initFields() {
+ sequence_ = 0;
+ localBaseKey_ = com.google.protobuf.ByteString.EMPTY;
+ localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ localRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ localIdentityKey_ = com.google.protobuf.ByteString.EMPTY;
+ localIdentityKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, sequence_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, localBaseKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, localBaseKeyPrivate_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, localRatchetKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeBytes(5, localRatchetKeyPrivate_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ output.writeBytes(7, localIdentityKey_);
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ output.writeBytes(8, localIdentityKeyPrivate_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, sequence_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, localBaseKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, localBaseKeyPrivate_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, localRatchetKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(5, localRatchetKeyPrivate_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(7, localIdentityKey_);
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(8, localIdentityKeyPrivate_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.PendingKeyExchange}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchangeOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingKeyExchange_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ sequence_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ localBaseKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ localRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ localIdentityKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000020);
+ localIdentityKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000040);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange result = new org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.sequence_ = sequence_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.localBaseKey_ = localBaseKey_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.localBaseKeyPrivate_ = localBaseKeyPrivate_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.localRatchetKey_ = localRatchetKey_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.localRatchetKeyPrivate_ = localRatchetKeyPrivate_;
+ if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+ to_bitField0_ |= 0x00000020;
+ }
+ result.localIdentityKey_ = localIdentityKey_;
+ if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+ to_bitField0_ |= 0x00000040;
+ }
+ result.localIdentityKeyPrivate_ = localIdentityKeyPrivate_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.getDefaultInstance()) return this;
+ if (other.hasSequence()) {
+ setSequence(other.getSequence());
+ }
+ if (other.hasLocalBaseKey()) {
+ setLocalBaseKey(other.getLocalBaseKey());
+ }
+ if (other.hasLocalBaseKeyPrivate()) {
+ setLocalBaseKeyPrivate(other.getLocalBaseKeyPrivate());
+ }
+ if (other.hasLocalRatchetKey()) {
+ setLocalRatchetKey(other.getLocalRatchetKey());
+ }
+ if (other.hasLocalRatchetKeyPrivate()) {
+ setLocalRatchetKeyPrivate(other.getLocalRatchetKeyPrivate());
+ }
+ if (other.hasLocalIdentityKey()) {
+ setLocalIdentityKey(other.getLocalIdentityKey());
+ }
+ if (other.hasLocalIdentityKeyPrivate()) {
+ setLocalIdentityKeyPrivate(other.getLocalIdentityKeyPrivate());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 sequence = 1;
+ private int sequence_ ;
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ public boolean hasSequence() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ public int getSequence() {
+ return sequence_;
+ }
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ public Builder setSequence(int value) {
+ bitField0_ |= 0x00000001;
+ sequence_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 sequence = 1;</code>
+ */
+ public Builder clearSequence() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ sequence_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes localBaseKey = 2;
+ private com.google.protobuf.ByteString localBaseKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ public boolean hasLocalBaseKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getLocalBaseKey() {
+ return localBaseKey_;
+ }
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ public Builder setLocalBaseKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ localBaseKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes localBaseKey = 2;</code>
+ */
+ public Builder clearLocalBaseKey() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ localBaseKey_ = getDefaultInstance().getLocalBaseKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes localBaseKeyPrivate = 3;
+ private com.google.protobuf.ByteString localBaseKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ public boolean hasLocalBaseKeyPrivate() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ public com.google.protobuf.ByteString getLocalBaseKeyPrivate() {
+ return localBaseKeyPrivate_;
+ }
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ public Builder setLocalBaseKeyPrivate(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ localBaseKeyPrivate_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes localBaseKeyPrivate = 3;</code>
+ */
+ public Builder clearLocalBaseKeyPrivate() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ localBaseKeyPrivate_ = getDefaultInstance().getLocalBaseKeyPrivate();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes localRatchetKey = 4;
+ private com.google.protobuf.ByteString localRatchetKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ public boolean hasLocalRatchetKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getLocalRatchetKey() {
+ return localRatchetKey_;
+ }
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ public Builder setLocalRatchetKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ localRatchetKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes localRatchetKey = 4;</code>
+ */
+ public Builder clearLocalRatchetKey() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ localRatchetKey_ = getDefaultInstance().getLocalRatchetKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes localRatchetKeyPrivate = 5;
+ private com.google.protobuf.ByteString localRatchetKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ public boolean hasLocalRatchetKeyPrivate() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ public com.google.protobuf.ByteString getLocalRatchetKeyPrivate() {
+ return localRatchetKeyPrivate_;
+ }
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ public Builder setLocalRatchetKeyPrivate(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000010;
+ localRatchetKeyPrivate_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes localRatchetKeyPrivate = 5;</code>
+ */
+ public Builder clearLocalRatchetKeyPrivate() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ localRatchetKeyPrivate_ = getDefaultInstance().getLocalRatchetKeyPrivate();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes localIdentityKey = 7;
+ private com.google.protobuf.ByteString localIdentityKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ public boolean hasLocalIdentityKey() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ public com.google.protobuf.ByteString getLocalIdentityKey() {
+ return localIdentityKey_;
+ }
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ public Builder setLocalIdentityKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000020;
+ localIdentityKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes localIdentityKey = 7;</code>
+ */
+ public Builder clearLocalIdentityKey() {
+ bitField0_ = (bitField0_ & ~0x00000020);
+ localIdentityKey_ = getDefaultInstance().getLocalIdentityKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes localIdentityKeyPrivate = 8;
+ private com.google.protobuf.ByteString localIdentityKeyPrivate_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ public boolean hasLocalIdentityKeyPrivate() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ public com.google.protobuf.ByteString getLocalIdentityKeyPrivate() {
+ return localIdentityKeyPrivate_;
+ }
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ public Builder setLocalIdentityKeyPrivate(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000040;
+ localIdentityKeyPrivate_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes localIdentityKeyPrivate = 8;</code>
+ */
+ public Builder clearLocalIdentityKeyPrivate() {
+ bitField0_ = (bitField0_ & ~0x00000040);
+ localIdentityKeyPrivate_ = getDefaultInstance().getLocalIdentityKeyPrivate();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SessionStructure.PendingKeyExchange)
+ }
+
+ static {
+ defaultInstance = new PendingKeyExchange(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SessionStructure.PendingKeyExchange)
+ }
+
+ public interface PendingPreKeyOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 preKeyId = 1;
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ boolean hasPreKeyId();
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ int getPreKeyId();
+
+ // optional int32 signedPreKeyId = 3;
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ boolean hasSignedPreKeyId();
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ int getSignedPreKeyId();
+
+ // optional bytes baseKey = 2;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ boolean hasBaseKey();
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getBaseKey();
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.PendingPreKey}
+ */
+ public static final class PendingPreKey extends
+ com.google.protobuf.GeneratedMessage
+ implements PendingPreKeyOrBuilder {
+ // Use PendingPreKey.newBuilder() to construct.
+ private PendingPreKey(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private PendingPreKey(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final PendingPreKey defaultInstance;
+ public static PendingPreKey getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PendingPreKey getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private PendingPreKey(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ preKeyId_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000004;
+ baseKey_ = input.readBytes();
+ break;
+ }
+ case 24: {
+ bitField0_ |= 0x00000002;
+ signedPreKeyId_ = input.readInt32();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingPreKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<PendingPreKey> PARSER =
+ new com.google.protobuf.AbstractParser<PendingPreKey>() {
+ public PendingPreKey parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new PendingPreKey(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<PendingPreKey> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 preKeyId = 1;
+ public static final int PREKEYID_FIELD_NUMBER = 1;
+ private int preKeyId_;
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public boolean hasPreKeyId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public int getPreKeyId() {
+ return preKeyId_;
+ }
+
+ // optional int32 signedPreKeyId = 3;
+ public static final int SIGNEDPREKEYID_FIELD_NUMBER = 3;
+ private int signedPreKeyId_;
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ public boolean hasSignedPreKeyId() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ public int getSignedPreKeyId() {
+ return signedPreKeyId_;
+ }
+
+ // optional bytes baseKey = 2;
+ public static final int BASEKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString baseKey_;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public boolean hasBaseKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKey() {
+ return baseKey_;
+ }
+
+ private void initFields() {
+ preKeyId_ = 0;
+ signedPreKeyId_ = 0;
+ baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, preKeyId_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(2, baseKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeInt32(3, signedPreKeyId_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, preKeyId_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, baseKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(3, signedPreKeyId_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure.PendingPreKey}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKeyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingPreKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ preKeyId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ signedPreKeyId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_PendingPreKey_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey result = new org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.preKeyId_ = preKeyId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.signedPreKeyId_ = signedPreKeyId_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.baseKey_ = baseKey_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.getDefaultInstance()) return this;
+ if (other.hasPreKeyId()) {
+ setPreKeyId(other.getPreKeyId());
+ }
+ if (other.hasSignedPreKeyId()) {
+ setSignedPreKeyId(other.getSignedPreKeyId());
+ }
+ if (other.hasBaseKey()) {
+ setBaseKey(other.getBaseKey());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 preKeyId = 1;
+ private int preKeyId_ ;
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public boolean hasPreKeyId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public int getPreKeyId() {
+ return preKeyId_;
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public Builder setPreKeyId(int value) {
+ bitField0_ |= 0x00000001;
+ preKeyId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 preKeyId = 1;</code>
+ */
+ public Builder clearPreKeyId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ preKeyId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional int32 signedPreKeyId = 3;
+ private int signedPreKeyId_ ;
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ public boolean hasSignedPreKeyId() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ public int getSignedPreKeyId() {
+ return signedPreKeyId_;
+ }
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ public Builder setSignedPreKeyId(int value) {
+ bitField0_ |= 0x00000002;
+ signedPreKeyId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 signedPreKeyId = 3;</code>
+ */
+ public Builder clearSignedPreKeyId() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ signedPreKeyId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes baseKey = 2;
+ private com.google.protobuf.ByteString baseKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public boolean hasBaseKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getBaseKey() {
+ return baseKey_;
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public Builder setBaseKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ baseKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes baseKey = 2;</code>
+ */
+ public Builder clearBaseKey() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ baseKey_ = getDefaultInstance().getBaseKey();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SessionStructure.PendingPreKey)
+ }
+
+ static {
+ defaultInstance = new PendingPreKey(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SessionStructure.PendingPreKey)
+ }
+
+ private int bitField0_;
+ // optional uint32 sessionVersion = 1;
+ public static final int SESSIONVERSION_FIELD_NUMBER = 1;
+ private int sessionVersion_;
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ public boolean hasSessionVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ public int getSessionVersion() {
+ return sessionVersion_;
+ }
+
+ // optional bytes localIdentityPublic = 2;
+ public static final int LOCALIDENTITYPUBLIC_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString localIdentityPublic_;
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ public boolean hasLocalIdentityPublic() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ public com.google.protobuf.ByteString getLocalIdentityPublic() {
+ return localIdentityPublic_;
+ }
+
+ // optional bytes remoteIdentityPublic = 3;
+ public static final int REMOTEIDENTITYPUBLIC_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString remoteIdentityPublic_;
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ public boolean hasRemoteIdentityPublic() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ public com.google.protobuf.ByteString getRemoteIdentityPublic() {
+ return remoteIdentityPublic_;
+ }
+
+ // optional bytes rootKey = 4;
+ public static final int ROOTKEY_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString rootKey_;
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ public boolean hasRootKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getRootKey() {
+ return rootKey_;
+ }
+
+ // optional uint32 previousCounter = 5;
+ public static final int PREVIOUSCOUNTER_FIELD_NUMBER = 5;
+ private int previousCounter_;
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ public boolean hasPreviousCounter() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ public int getPreviousCounter() {
+ return previousCounter_;
+ }
+
+ // optional .textsecure.SessionStructure.Chain senderChain = 6;
+ public static final int SENDERCHAIN_FIELD_NUMBER = 6;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain senderChain_;
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public boolean hasSenderChain() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain getSenderChain() {
+ return senderChain_;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder getSenderChainOrBuilder() {
+ return senderChain_;
+ }
+
+ // repeated .textsecure.SessionStructure.Chain receiverChains = 7;
+ public static final int RECEIVERCHAINS_FIELD_NUMBER = 7;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain> receiverChains_;
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain> getReceiverChainsList() {
+ return receiverChains_;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder>
+ getReceiverChainsOrBuilderList() {
+ return receiverChains_;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public int getReceiverChainsCount() {
+ return receiverChains_.size();
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain getReceiverChains(int index) {
+ return receiverChains_.get(index);
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder getReceiverChainsOrBuilder(
+ int index) {
+ return receiverChains_.get(index);
+ }
+
+ // optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;
+ public static final int PENDINGKEYEXCHANGE_FIELD_NUMBER = 8;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange pendingKeyExchange_;
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public boolean hasPendingKeyExchange() {
+ return ((bitField0_ & 0x00000040) == 0x00000040);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange getPendingKeyExchange() {
+ return pendingKeyExchange_;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchangeOrBuilder getPendingKeyExchangeOrBuilder() {
+ return pendingKeyExchange_;
+ }
+
+ // optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;
+ public static final int PENDINGPREKEY_FIELD_NUMBER = 9;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey pendingPreKey_;
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public boolean hasPendingPreKey() {
+ return ((bitField0_ & 0x00000080) == 0x00000080);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey getPendingPreKey() {
+ return pendingPreKey_;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKeyOrBuilder getPendingPreKeyOrBuilder() {
+ return pendingPreKey_;
+ }
+
+ // optional uint32 remoteRegistrationId = 10;
+ public static final int REMOTEREGISTRATIONID_FIELD_NUMBER = 10;
+ private int remoteRegistrationId_;
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ public boolean hasRemoteRegistrationId() {
+ return ((bitField0_ & 0x00000100) == 0x00000100);
+ }
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ public int getRemoteRegistrationId() {
+ return remoteRegistrationId_;
+ }
+
+ // optional uint32 localRegistrationId = 11;
+ public static final int LOCALREGISTRATIONID_FIELD_NUMBER = 11;
+ private int localRegistrationId_;
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ public boolean hasLocalRegistrationId() {
+ return ((bitField0_ & 0x00000200) == 0x00000200);
+ }
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ public int getLocalRegistrationId() {
+ return localRegistrationId_;
+ }
+
+ // optional bool needsRefresh = 12;
+ public static final int NEEDSREFRESH_FIELD_NUMBER = 12;
+ private boolean needsRefresh_;
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ public boolean hasNeedsRefresh() {
+ return ((bitField0_ & 0x00000400) == 0x00000400);
+ }
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ public boolean getNeedsRefresh() {
+ return needsRefresh_;
+ }
+
+ // optional bytes aliceBaseKey = 13;
+ public static final int ALICEBASEKEY_FIELD_NUMBER = 13;
+ private com.google.protobuf.ByteString aliceBaseKey_;
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ public boolean hasAliceBaseKey() {
+ return ((bitField0_ & 0x00000800) == 0x00000800);
+ }
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ public com.google.protobuf.ByteString getAliceBaseKey() {
+ return aliceBaseKey_;
+ }
+
+ private void initFields() {
+ sessionVersion_ = 0;
+ localIdentityPublic_ = com.google.protobuf.ByteString.EMPTY;
+ remoteIdentityPublic_ = com.google.protobuf.ByteString.EMPTY;
+ rootKey_ = com.google.protobuf.ByteString.EMPTY;
+ previousCounter_ = 0;
+ senderChain_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance();
+ receiverChains_ = java.util.Collections.emptyList();
+ pendingKeyExchange_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.getDefaultInstance();
+ pendingPreKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.getDefaultInstance();
+ remoteRegistrationId_ = 0;
+ localRegistrationId_ = 0;
+ needsRefresh_ = false;
+ aliceBaseKey_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, sessionVersion_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, localIdentityPublic_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, remoteIdentityPublic_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, rootKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeUInt32(5, previousCounter_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ output.writeMessage(6, senderChain_);
+ }
+ for (int i = 0; i < receiverChains_.size(); i++) {
+ output.writeMessage(7, receiverChains_.get(i));
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ output.writeMessage(8, pendingKeyExchange_);
+ }
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ output.writeMessage(9, pendingPreKey_);
+ }
+ if (((bitField0_ & 0x00000100) == 0x00000100)) {
+ output.writeUInt32(10, remoteRegistrationId_);
+ }
+ if (((bitField0_ & 0x00000200) == 0x00000200)) {
+ output.writeUInt32(11, localRegistrationId_);
+ }
+ if (((bitField0_ & 0x00000400) == 0x00000400)) {
+ output.writeBool(12, needsRefresh_);
+ }
+ if (((bitField0_ & 0x00000800) == 0x00000800)) {
+ output.writeBytes(13, aliceBaseKey_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, sessionVersion_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, localIdentityPublic_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, remoteIdentityPublic_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, rootKey_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(5, previousCounter_);
+ }
+ if (((bitField0_ & 0x00000020) == 0x00000020)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(6, senderChain_);
+ }
+ for (int i = 0; i < receiverChains_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(7, receiverChains_.get(i));
+ }
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(8, pendingKeyExchange_);
+ }
+ if (((bitField0_ & 0x00000080) == 0x00000080)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(9, pendingPreKey_);
+ }
+ if (((bitField0_ & 0x00000100) == 0x00000100)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(10, remoteRegistrationId_);
+ }
+ if (((bitField0_ & 0x00000200) == 0x00000200)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(11, localRegistrationId_);
+ }
+ if (((bitField0_ & 0x00000400) == 0x00000400)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(12, needsRefresh_);
+ }
+ if (((bitField0_ & 0x00000800) == 0x00000800)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(13, aliceBaseKey_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SessionStructure}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ getSenderChainFieldBuilder();
+ getReceiverChainsFieldBuilder();
+ getPendingKeyExchangeFieldBuilder();
+ getPendingPreKeyFieldBuilder();
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ sessionVersion_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ localIdentityPublic_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ remoteIdentityPublic_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ rootKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ previousCounter_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ if (senderChainBuilder_ == null) {
+ senderChain_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance();
+ } else {
+ senderChainBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000020);
+ if (receiverChainsBuilder_ == null) {
+ receiverChains_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000040);
+ } else {
+ receiverChainsBuilder_.clear();
+ }
+ if (pendingKeyExchangeBuilder_ == null) {
+ pendingKeyExchange_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.getDefaultInstance();
+ } else {
+ pendingKeyExchangeBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000080);
+ if (pendingPreKeyBuilder_ == null) {
+ pendingPreKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.getDefaultInstance();
+ } else {
+ pendingPreKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000100);
+ remoteRegistrationId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000200);
+ localRegistrationId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000400);
+ needsRefresh_ = false;
+ bitField0_ = (bitField0_ & ~0x00000800);
+ aliceBaseKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00001000);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SessionStructure_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure result = new org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.sessionVersion_ = sessionVersion_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.localIdentityPublic_ = localIdentityPublic_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.remoteIdentityPublic_ = remoteIdentityPublic_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.rootKey_ = rootKey_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.previousCounter_ = previousCounter_;
+ if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+ to_bitField0_ |= 0x00000020;
+ }
+ if (senderChainBuilder_ == null) {
+ result.senderChain_ = senderChain_;
+ } else {
+ result.senderChain_ = senderChainBuilder_.build();
+ }
+ if (receiverChainsBuilder_ == null) {
+ if (((bitField0_ & 0x00000040) == 0x00000040)) {
+ receiverChains_ = java.util.Collections.unmodifiableList(receiverChains_);
+ bitField0_ = (bitField0_ & ~0x00000040);
+ }
+ result.receiverChains_ = receiverChains_;
+ } else {
+ result.receiverChains_ = receiverChainsBuilder_.build();
+ }
+ if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+ to_bitField0_ |= 0x00000040;
+ }
+ if (pendingKeyExchangeBuilder_ == null) {
+ result.pendingKeyExchange_ = pendingKeyExchange_;
+ } else {
+ result.pendingKeyExchange_ = pendingKeyExchangeBuilder_.build();
+ }
+ if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+ to_bitField0_ |= 0x00000080;
+ }
+ if (pendingPreKeyBuilder_ == null) {
+ result.pendingPreKey_ = pendingPreKey_;
+ } else {
+ result.pendingPreKey_ = pendingPreKeyBuilder_.build();
+ }
+ if (((from_bitField0_ & 0x00000200) == 0x00000200)) {
+ to_bitField0_ |= 0x00000100;
+ }
+ result.remoteRegistrationId_ = remoteRegistrationId_;
+ if (((from_bitField0_ & 0x00000400) == 0x00000400)) {
+ to_bitField0_ |= 0x00000200;
+ }
+ result.localRegistrationId_ = localRegistrationId_;
+ if (((from_bitField0_ & 0x00000800) == 0x00000800)) {
+ to_bitField0_ |= 0x00000400;
+ }
+ result.needsRefresh_ = needsRefresh_;
+ if (((from_bitField0_ & 0x00001000) == 0x00001000)) {
+ to_bitField0_ |= 0x00000800;
+ }
+ result.aliceBaseKey_ = aliceBaseKey_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance()) return this;
+ if (other.hasSessionVersion()) {
+ setSessionVersion(other.getSessionVersion());
+ }
+ if (other.hasLocalIdentityPublic()) {
+ setLocalIdentityPublic(other.getLocalIdentityPublic());
+ }
+ if (other.hasRemoteIdentityPublic()) {
+ setRemoteIdentityPublic(other.getRemoteIdentityPublic());
+ }
+ if (other.hasRootKey()) {
+ setRootKey(other.getRootKey());
+ }
+ if (other.hasPreviousCounter()) {
+ setPreviousCounter(other.getPreviousCounter());
+ }
+ if (other.hasSenderChain()) {
+ mergeSenderChain(other.getSenderChain());
+ }
+ if (receiverChainsBuilder_ == null) {
+ if (!other.receiverChains_.isEmpty()) {
+ if (receiverChains_.isEmpty()) {
+ receiverChains_ = other.receiverChains_;
+ bitField0_ = (bitField0_ & ~0x00000040);
+ } else {
+ ensureReceiverChainsIsMutable();
+ receiverChains_.addAll(other.receiverChains_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.receiverChains_.isEmpty()) {
+ if (receiverChainsBuilder_.isEmpty()) {
+ receiverChainsBuilder_.dispose();
+ receiverChainsBuilder_ = null;
+ receiverChains_ = other.receiverChains_;
+ bitField0_ = (bitField0_ & ~0x00000040);
+ receiverChainsBuilder_ =
+ com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+ getReceiverChainsFieldBuilder() : null;
+ } else {
+ receiverChainsBuilder_.addAllMessages(other.receiverChains_);
+ }
+ }
+ }
+ if (other.hasPendingKeyExchange()) {
+ mergePendingKeyExchange(other.getPendingKeyExchange());
+ }
+ if (other.hasPendingPreKey()) {
+ mergePendingPreKey(other.getPendingPreKey());
+ }
+ if (other.hasRemoteRegistrationId()) {
+ setRemoteRegistrationId(other.getRemoteRegistrationId());
+ }
+ if (other.hasLocalRegistrationId()) {
+ setLocalRegistrationId(other.getLocalRegistrationId());
+ }
+ if (other.hasNeedsRefresh()) {
+ setNeedsRefresh(other.getNeedsRefresh());
+ }
+ if (other.hasAliceBaseKey()) {
+ setAliceBaseKey(other.getAliceBaseKey());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 sessionVersion = 1;
+ private int sessionVersion_ ;
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ public boolean hasSessionVersion() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ public int getSessionVersion() {
+ return sessionVersion_;
+ }
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ public Builder setSessionVersion(int value) {
+ bitField0_ |= 0x00000001;
+ sessionVersion_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 sessionVersion = 1;</code>
+ */
+ public Builder clearSessionVersion() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ sessionVersion_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes localIdentityPublic = 2;
+ private com.google.protobuf.ByteString localIdentityPublic_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ public boolean hasLocalIdentityPublic() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ public com.google.protobuf.ByteString getLocalIdentityPublic() {
+ return localIdentityPublic_;
+ }
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ public Builder setLocalIdentityPublic(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ localIdentityPublic_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes localIdentityPublic = 2;</code>
+ */
+ public Builder clearLocalIdentityPublic() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ localIdentityPublic_ = getDefaultInstance().getLocalIdentityPublic();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes remoteIdentityPublic = 3;
+ private com.google.protobuf.ByteString remoteIdentityPublic_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ public boolean hasRemoteIdentityPublic() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ public com.google.protobuf.ByteString getRemoteIdentityPublic() {
+ return remoteIdentityPublic_;
+ }
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ public Builder setRemoteIdentityPublic(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ remoteIdentityPublic_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes remoteIdentityPublic = 3;</code>
+ */
+ public Builder clearRemoteIdentityPublic() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ remoteIdentityPublic_ = getDefaultInstance().getRemoteIdentityPublic();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes rootKey = 4;
+ private com.google.protobuf.ByteString rootKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ public boolean hasRootKey() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ public com.google.protobuf.ByteString getRootKey() {
+ return rootKey_;
+ }
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ public Builder setRootKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ rootKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes rootKey = 4;</code>
+ */
+ public Builder clearRootKey() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ rootKey_ = getDefaultInstance().getRootKey();
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 previousCounter = 5;
+ private int previousCounter_ ;
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ public boolean hasPreviousCounter() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ public int getPreviousCounter() {
+ return previousCounter_;
+ }
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ public Builder setPreviousCounter(int value) {
+ bitField0_ |= 0x00000010;
+ previousCounter_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 previousCounter = 5;</code>
+ */
+ public Builder clearPreviousCounter() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ previousCounter_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional .textsecure.SessionStructure.Chain senderChain = 6;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain senderChain_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder> senderChainBuilder_;
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public boolean hasSenderChain() {
+ return ((bitField0_ & 0x00000020) == 0x00000020);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain getSenderChain() {
+ if (senderChainBuilder_ == null) {
+ return senderChain_;
+ } else {
+ return senderChainBuilder_.getMessage();
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public Builder setSenderChain(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain value) {
+ if (senderChainBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ senderChain_ = value;
+ onChanged();
+ } else {
+ senderChainBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000020;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public Builder setSenderChain(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder builderForValue) {
+ if (senderChainBuilder_ == null) {
+ senderChain_ = builderForValue.build();
+ onChanged();
+ } else {
+ senderChainBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000020;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public Builder mergeSenderChain(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain value) {
+ if (senderChainBuilder_ == null) {
+ if (((bitField0_ & 0x00000020) == 0x00000020) &&
+ senderChain_ != org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance()) {
+ senderChain_ =
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.newBuilder(senderChain_).mergeFrom(value).buildPartial();
+ } else {
+ senderChain_ = value;
+ }
+ onChanged();
+ } else {
+ senderChainBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000020;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public Builder clearSenderChain() {
+ if (senderChainBuilder_ == null) {
+ senderChain_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance();
+ onChanged();
+ } else {
+ senderChainBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000020);
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder getSenderChainBuilder() {
+ bitField0_ |= 0x00000020;
+ onChanged();
+ return getSenderChainFieldBuilder().getBuilder();
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder getSenderChainOrBuilder() {
+ if (senderChainBuilder_ != null) {
+ return senderChainBuilder_.getMessageOrBuilder();
+ } else {
+ return senderChain_;
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.Chain senderChain = 6;</code>
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder>
+ getSenderChainFieldBuilder() {
+ if (senderChainBuilder_ == null) {
+ senderChainBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder>(
+ senderChain_,
+ getParentForChildren(),
+ isClean());
+ senderChain_ = null;
+ }
+ return senderChainBuilder_;
+ }
+
+ // repeated .textsecure.SessionStructure.Chain receiverChains = 7;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain> receiverChains_ =
+ java.util.Collections.emptyList();
+ private void ensureReceiverChainsIsMutable() {
+ if (!((bitField0_ & 0x00000040) == 0x00000040)) {
+ receiverChains_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain>(receiverChains_);
+ bitField0_ |= 0x00000040;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder> receiverChainsBuilder_;
+
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain> getReceiverChainsList() {
+ if (receiverChainsBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(receiverChains_);
+ } else {
+ return receiverChainsBuilder_.getMessageList();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public int getReceiverChainsCount() {
+ if (receiverChainsBuilder_ == null) {
+ return receiverChains_.size();
+ } else {
+ return receiverChainsBuilder_.getCount();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain getReceiverChains(int index) {
+ if (receiverChainsBuilder_ == null) {
+ return receiverChains_.get(index);
+ } else {
+ return receiverChainsBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder setReceiverChains(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain value) {
+ if (receiverChainsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureReceiverChainsIsMutable();
+ receiverChains_.set(index, value);
+ onChanged();
+ } else {
+ receiverChainsBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder setReceiverChains(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder builderForValue) {
+ if (receiverChainsBuilder_ == null) {
+ ensureReceiverChainsIsMutable();
+ receiverChains_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ receiverChainsBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder addReceiverChains(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain value) {
+ if (receiverChainsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureReceiverChainsIsMutable();
+ receiverChains_.add(value);
+ onChanged();
+ } else {
+ receiverChainsBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder addReceiverChains(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain value) {
+ if (receiverChainsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureReceiverChainsIsMutable();
+ receiverChains_.add(index, value);
+ onChanged();
+ } else {
+ receiverChainsBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder addReceiverChains(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder builderForValue) {
+ if (receiverChainsBuilder_ == null) {
+ ensureReceiverChainsIsMutable();
+ receiverChains_.add(builderForValue.build());
+ onChanged();
+ } else {
+ receiverChainsBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder addReceiverChains(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder builderForValue) {
+ if (receiverChainsBuilder_ == null) {
+ ensureReceiverChainsIsMutable();
+ receiverChains_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ receiverChainsBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder addAllReceiverChains(
+ java.lang.Iterable<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain> values) {
+ if (receiverChainsBuilder_ == null) {
+ ensureReceiverChainsIsMutable();
+ super.addAll(values, receiverChains_);
+ onChanged();
+ } else {
+ receiverChainsBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder clearReceiverChains() {
+ if (receiverChainsBuilder_ == null) {
+ receiverChains_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000040);
+ onChanged();
+ } else {
+ receiverChainsBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public Builder removeReceiverChains(int index) {
+ if (receiverChainsBuilder_ == null) {
+ ensureReceiverChainsIsMutable();
+ receiverChains_.remove(index);
+ onChanged();
+ } else {
+ receiverChainsBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder getReceiverChainsBuilder(
+ int index) {
+ return getReceiverChainsFieldBuilder().getBuilder(index);
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder getReceiverChainsOrBuilder(
+ int index) {
+ if (receiverChainsBuilder_ == null) {
+ return receiverChains_.get(index); } else {
+ return receiverChainsBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder>
+ getReceiverChainsOrBuilderList() {
+ if (receiverChainsBuilder_ != null) {
+ return receiverChainsBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(receiverChains_);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder addReceiverChainsBuilder() {
+ return getReceiverChainsFieldBuilder().addBuilder(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder addReceiverChainsBuilder(
+ int index) {
+ return getReceiverChainsFieldBuilder().addBuilder(
+ index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure.Chain receiverChains = 7;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder>
+ getReceiverChainsBuilderList() {
+ return getReceiverChainsFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder>
+ getReceiverChainsFieldBuilder() {
+ if (receiverChainsBuilder_ == null) {
+ receiverChainsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Chain.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.ChainOrBuilder>(
+ receiverChains_,
+ ((bitField0_ & 0x00000040) == 0x00000040),
+ getParentForChildren(),
+ isClean());
+ receiverChains_ = null;
+ }
+ return receiverChainsBuilder_;
+ }
+
+ // optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange pendingKeyExchange_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchangeOrBuilder> pendingKeyExchangeBuilder_;
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public boolean hasPendingKeyExchange() {
+ return ((bitField0_ & 0x00000080) == 0x00000080);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange getPendingKeyExchange() {
+ if (pendingKeyExchangeBuilder_ == null) {
+ return pendingKeyExchange_;
+ } else {
+ return pendingKeyExchangeBuilder_.getMessage();
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public Builder setPendingKeyExchange(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange value) {
+ if (pendingKeyExchangeBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ pendingKeyExchange_ = value;
+ onChanged();
+ } else {
+ pendingKeyExchangeBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000080;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public Builder setPendingKeyExchange(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder builderForValue) {
+ if (pendingKeyExchangeBuilder_ == null) {
+ pendingKeyExchange_ = builderForValue.build();
+ onChanged();
+ } else {
+ pendingKeyExchangeBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000080;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public Builder mergePendingKeyExchange(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange value) {
+ if (pendingKeyExchangeBuilder_ == null) {
+ if (((bitField0_ & 0x00000080) == 0x00000080) &&
+ pendingKeyExchange_ != org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.getDefaultInstance()) {
+ pendingKeyExchange_ =
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.newBuilder(pendingKeyExchange_).mergeFrom(value).buildPartial();
+ } else {
+ pendingKeyExchange_ = value;
+ }
+ onChanged();
+ } else {
+ pendingKeyExchangeBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000080;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public Builder clearPendingKeyExchange() {
+ if (pendingKeyExchangeBuilder_ == null) {
+ pendingKeyExchange_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.getDefaultInstance();
+ onChanged();
+ } else {
+ pendingKeyExchangeBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000080);
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder getPendingKeyExchangeBuilder() {
+ bitField0_ |= 0x00000080;
+ onChanged();
+ return getPendingKeyExchangeFieldBuilder().getBuilder();
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchangeOrBuilder getPendingKeyExchangeOrBuilder() {
+ if (pendingKeyExchangeBuilder_ != null) {
+ return pendingKeyExchangeBuilder_.getMessageOrBuilder();
+ } else {
+ return pendingKeyExchange_;
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingKeyExchange pendingKeyExchange = 8;</code>
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchangeOrBuilder>
+ getPendingKeyExchangeFieldBuilder() {
+ if (pendingKeyExchangeBuilder_ == null) {
+ pendingKeyExchangeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchange.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingKeyExchangeOrBuilder>(
+ pendingKeyExchange_,
+ getParentForChildren(),
+ isClean());
+ pendingKeyExchange_ = null;
+ }
+ return pendingKeyExchangeBuilder_;
+ }
+
+ // optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey pendingPreKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKeyOrBuilder> pendingPreKeyBuilder_;
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public boolean hasPendingPreKey() {
+ return ((bitField0_ & 0x00000100) == 0x00000100);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey getPendingPreKey() {
+ if (pendingPreKeyBuilder_ == null) {
+ return pendingPreKey_;
+ } else {
+ return pendingPreKeyBuilder_.getMessage();
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public Builder setPendingPreKey(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey value) {
+ if (pendingPreKeyBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ pendingPreKey_ = value;
+ onChanged();
+ } else {
+ pendingPreKeyBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000100;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public Builder setPendingPreKey(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder builderForValue) {
+ if (pendingPreKeyBuilder_ == null) {
+ pendingPreKey_ = builderForValue.build();
+ onChanged();
+ } else {
+ pendingPreKeyBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000100;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public Builder mergePendingPreKey(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey value) {
+ if (pendingPreKeyBuilder_ == null) {
+ if (((bitField0_ & 0x00000100) == 0x00000100) &&
+ pendingPreKey_ != org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.getDefaultInstance()) {
+ pendingPreKey_ =
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.newBuilder(pendingPreKey_).mergeFrom(value).buildPartial();
+ } else {
+ pendingPreKey_ = value;
+ }
+ onChanged();
+ } else {
+ pendingPreKeyBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000100;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public Builder clearPendingPreKey() {
+ if (pendingPreKeyBuilder_ == null) {
+ pendingPreKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.getDefaultInstance();
+ onChanged();
+ } else {
+ pendingPreKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000100);
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder getPendingPreKeyBuilder() {
+ bitField0_ |= 0x00000100;
+ onChanged();
+ return getPendingPreKeyFieldBuilder().getBuilder();
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKeyOrBuilder getPendingPreKeyOrBuilder() {
+ if (pendingPreKeyBuilder_ != null) {
+ return pendingPreKeyBuilder_.getMessageOrBuilder();
+ } else {
+ return pendingPreKey_;
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure.PendingPreKey pendingPreKey = 9;</code>
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKeyOrBuilder>
+ getPendingPreKeyFieldBuilder() {
+ if (pendingPreKeyBuilder_ == null) {
+ pendingPreKeyBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PendingPreKeyOrBuilder>(
+ pendingPreKey_,
+ getParentForChildren(),
+ isClean());
+ pendingPreKey_ = null;
+ }
+ return pendingPreKeyBuilder_;
+ }
+
+ // optional uint32 remoteRegistrationId = 10;
+ private int remoteRegistrationId_ ;
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ public boolean hasRemoteRegistrationId() {
+ return ((bitField0_ & 0x00000200) == 0x00000200);
+ }
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ public int getRemoteRegistrationId() {
+ return remoteRegistrationId_;
+ }
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ public Builder setRemoteRegistrationId(int value) {
+ bitField0_ |= 0x00000200;
+ remoteRegistrationId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 remoteRegistrationId = 10;</code>
+ */
+ public Builder clearRemoteRegistrationId() {
+ bitField0_ = (bitField0_ & ~0x00000200);
+ remoteRegistrationId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 localRegistrationId = 11;
+ private int localRegistrationId_ ;
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ public boolean hasLocalRegistrationId() {
+ return ((bitField0_ & 0x00000400) == 0x00000400);
+ }
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ public int getLocalRegistrationId() {
+ return localRegistrationId_;
+ }
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ public Builder setLocalRegistrationId(int value) {
+ bitField0_ |= 0x00000400;
+ localRegistrationId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 localRegistrationId = 11;</code>
+ */
+ public Builder clearLocalRegistrationId() {
+ bitField0_ = (bitField0_ & ~0x00000400);
+ localRegistrationId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bool needsRefresh = 12;
+ private boolean needsRefresh_ ;
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ public boolean hasNeedsRefresh() {
+ return ((bitField0_ & 0x00000800) == 0x00000800);
+ }
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ public boolean getNeedsRefresh() {
+ return needsRefresh_;
+ }
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ public Builder setNeedsRefresh(boolean value) {
+ bitField0_ |= 0x00000800;
+ needsRefresh_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bool needsRefresh = 12;</code>
+ */
+ public Builder clearNeedsRefresh() {
+ bitField0_ = (bitField0_ & ~0x00000800);
+ needsRefresh_ = false;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes aliceBaseKey = 13;
+ private com.google.protobuf.ByteString aliceBaseKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ public boolean hasAliceBaseKey() {
+ return ((bitField0_ & 0x00001000) == 0x00001000);
+ }
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ public com.google.protobuf.ByteString getAliceBaseKey() {
+ return aliceBaseKey_;
+ }
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ public Builder setAliceBaseKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00001000;
+ aliceBaseKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes aliceBaseKey = 13;</code>
+ */
+ public Builder clearAliceBaseKey() {
+ bitField0_ = (bitField0_ & ~0x00001000);
+ aliceBaseKey_ = getDefaultInstance().getAliceBaseKey();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SessionStructure)
+ }
+
+ static {
+ defaultInstance = new SessionStructure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SessionStructure)
+ }
+
+ public interface RecordStructureOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional .textsecure.SessionStructure currentSession = 1;
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ boolean hasCurrentSession();
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure getCurrentSession();
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder getCurrentSessionOrBuilder();
+
+ // repeated .textsecure.SessionStructure previousSessions = 2;
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure>
+ getPreviousSessionsList();
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure getPreviousSessions(int index);
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ int getPreviousSessionsCount();
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder>
+ getPreviousSessionsOrBuilderList();
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder getPreviousSessionsOrBuilder(
+ int index);
+ }
+ /**
+ * Protobuf type {@code textsecure.RecordStructure}
+ */
+ public static final class RecordStructure extends
+ com.google.protobuf.GeneratedMessage
+ implements RecordStructureOrBuilder {
+ // Use RecordStructure.newBuilder() to construct.
+ private RecordStructure(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private RecordStructure(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final RecordStructure defaultInstance;
+ public static RecordStructure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public RecordStructure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private RecordStructure(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 10: {
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ subBuilder = currentSession_.toBuilder();
+ }
+ currentSession_ = input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(currentSession_);
+ currentSession_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000001;
+ break;
+ }
+ case 18: {
+ if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
+ previousSessions_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure>();
+ mutable_bitField0_ |= 0x00000002;
+ }
+ previousSessions_.add(input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.PARSER, extensionRegistry));
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
+ previousSessions_ = java.util.Collections.unmodifiableList(previousSessions_);
+ }
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_RecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_RecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<RecordStructure> PARSER =
+ new com.google.protobuf.AbstractParser<RecordStructure>() {
+ public RecordStructure parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new RecordStructure(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<RecordStructure> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional .textsecure.SessionStructure currentSession = 1;
+ public static final int CURRENTSESSION_FIELD_NUMBER = 1;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure currentSession_;
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public boolean hasCurrentSession() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure getCurrentSession() {
+ return currentSession_;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder getCurrentSessionOrBuilder() {
+ return currentSession_;
+ }
+
+ // repeated .textsecure.SessionStructure previousSessions = 2;
+ public static final int PREVIOUSSESSIONS_FIELD_NUMBER = 2;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure> previousSessions_;
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure> getPreviousSessionsList() {
+ return previousSessions_;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder>
+ getPreviousSessionsOrBuilderList() {
+ return previousSessions_;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public int getPreviousSessionsCount() {
+ return previousSessions_.size();
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure getPreviousSessions(int index) {
+ return previousSessions_.get(index);
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder getPreviousSessionsOrBuilder(
+ int index) {
+ return previousSessions_.get(index);
+ }
+
+ private void initFields() {
+ currentSession_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance();
+ previousSessions_ = java.util.Collections.emptyList();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeMessage(1, currentSession_);
+ }
+ for (int i = 0; i < previousSessions_.size(); i++) {
+ output.writeMessage(2, previousSessions_.get(i));
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, currentSession_);
+ }
+ for (int i = 0; i < previousSessions_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, previousSessions_.get(i));
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.RecordStructure}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.RecordStructureOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_RecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_RecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ getCurrentSessionFieldBuilder();
+ getPreviousSessionsFieldBuilder();
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ if (currentSessionBuilder_ == null) {
+ currentSession_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance();
+ } else {
+ currentSessionBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000001);
+ if (previousSessionsBuilder_ == null) {
+ previousSessions_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ } else {
+ previousSessionsBuilder_.clear();
+ }
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_RecordStructure_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure result = new org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ if (currentSessionBuilder_ == null) {
+ result.currentSession_ = currentSession_;
+ } else {
+ result.currentSession_ = currentSessionBuilder_.build();
+ }
+ if (previousSessionsBuilder_ == null) {
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ previousSessions_ = java.util.Collections.unmodifiableList(previousSessions_);
+ bitField0_ = (bitField0_ & ~0x00000002);
+ }
+ result.previousSessions_ = previousSessions_;
+ } else {
+ result.previousSessions_ = previousSessionsBuilder_.build();
+ }
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure.getDefaultInstance()) return this;
+ if (other.hasCurrentSession()) {
+ mergeCurrentSession(other.getCurrentSession());
+ }
+ if (previousSessionsBuilder_ == null) {
+ if (!other.previousSessions_.isEmpty()) {
+ if (previousSessions_.isEmpty()) {
+ previousSessions_ = other.previousSessions_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ } else {
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.addAll(other.previousSessions_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.previousSessions_.isEmpty()) {
+ if (previousSessionsBuilder_.isEmpty()) {
+ previousSessionsBuilder_.dispose();
+ previousSessionsBuilder_ = null;
+ previousSessions_ = other.previousSessions_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ previousSessionsBuilder_ =
+ com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+ getPreviousSessionsFieldBuilder() : null;
+ } else {
+ previousSessionsBuilder_.addAllMessages(other.previousSessions_);
+ }
+ }
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.RecordStructure) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional .textsecure.SessionStructure currentSession = 1;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure currentSession_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder> currentSessionBuilder_;
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public boolean hasCurrentSession() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure getCurrentSession() {
+ if (currentSessionBuilder_ == null) {
+ return currentSession_;
+ } else {
+ return currentSessionBuilder_.getMessage();
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public Builder setCurrentSession(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure value) {
+ if (currentSessionBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ currentSession_ = value;
+ onChanged();
+ } else {
+ currentSessionBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public Builder setCurrentSession(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder builderForValue) {
+ if (currentSessionBuilder_ == null) {
+ currentSession_ = builderForValue.build();
+ onChanged();
+ } else {
+ currentSessionBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public Builder mergeCurrentSession(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure value) {
+ if (currentSessionBuilder_ == null) {
+ if (((bitField0_ & 0x00000001) == 0x00000001) &&
+ currentSession_ != org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance()) {
+ currentSession_ =
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.newBuilder(currentSession_).mergeFrom(value).buildPartial();
+ } else {
+ currentSession_ = value;
+ }
+ onChanged();
+ } else {
+ currentSessionBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000001;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public Builder clearCurrentSession() {
+ if (currentSessionBuilder_ == null) {
+ currentSession_ = org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance();
+ onChanged();
+ } else {
+ currentSessionBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000001);
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder getCurrentSessionBuilder() {
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return getCurrentSessionFieldBuilder().getBuilder();
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder getCurrentSessionOrBuilder() {
+ if (currentSessionBuilder_ != null) {
+ return currentSessionBuilder_.getMessageOrBuilder();
+ } else {
+ return currentSession_;
+ }
+ }
+ /**
+ * <code>optional .textsecure.SessionStructure currentSession = 1;</code>
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder>
+ getCurrentSessionFieldBuilder() {
+ if (currentSessionBuilder_ == null) {
+ currentSessionBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder>(
+ currentSession_,
+ getParentForChildren(),
+ isClean());
+ currentSession_ = null;
+ }
+ return currentSessionBuilder_;
+ }
+
+ // repeated .textsecure.SessionStructure previousSessions = 2;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure> previousSessions_ =
+ java.util.Collections.emptyList();
+ private void ensurePreviousSessionsIsMutable() {
+ if (!((bitField0_ & 0x00000002) == 0x00000002)) {
+ previousSessions_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure>(previousSessions_);
+ bitField0_ |= 0x00000002;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder> previousSessionsBuilder_;
+
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure> getPreviousSessionsList() {
+ if (previousSessionsBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(previousSessions_);
+ } else {
+ return previousSessionsBuilder_.getMessageList();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public int getPreviousSessionsCount() {
+ if (previousSessionsBuilder_ == null) {
+ return previousSessions_.size();
+ } else {
+ return previousSessionsBuilder_.getCount();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure getPreviousSessions(int index) {
+ if (previousSessionsBuilder_ == null) {
+ return previousSessions_.get(index);
+ } else {
+ return previousSessionsBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder setPreviousSessions(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure value) {
+ if (previousSessionsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.set(index, value);
+ onChanged();
+ } else {
+ previousSessionsBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder setPreviousSessions(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder builderForValue) {
+ if (previousSessionsBuilder_ == null) {
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ previousSessionsBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder addPreviousSessions(org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure value) {
+ if (previousSessionsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.add(value);
+ onChanged();
+ } else {
+ previousSessionsBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder addPreviousSessions(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure value) {
+ if (previousSessionsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.add(index, value);
+ onChanged();
+ } else {
+ previousSessionsBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder addPreviousSessions(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder builderForValue) {
+ if (previousSessionsBuilder_ == null) {
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.add(builderForValue.build());
+ onChanged();
+ } else {
+ previousSessionsBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder addPreviousSessions(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder builderForValue) {
+ if (previousSessionsBuilder_ == null) {
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ previousSessionsBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder addAllPreviousSessions(
+ java.lang.Iterable<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure> values) {
+ if (previousSessionsBuilder_ == null) {
+ ensurePreviousSessionsIsMutable();
+ super.addAll(values, previousSessions_);
+ onChanged();
+ } else {
+ previousSessionsBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder clearPreviousSessions() {
+ if (previousSessionsBuilder_ == null) {
+ previousSessions_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ onChanged();
+ } else {
+ previousSessionsBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public Builder removePreviousSessions(int index) {
+ if (previousSessionsBuilder_ == null) {
+ ensurePreviousSessionsIsMutable();
+ previousSessions_.remove(index);
+ onChanged();
+ } else {
+ previousSessionsBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder getPreviousSessionsBuilder(
+ int index) {
+ return getPreviousSessionsFieldBuilder().getBuilder(index);
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder getPreviousSessionsOrBuilder(
+ int index) {
+ if (previousSessionsBuilder_ == null) {
+ return previousSessions_.get(index); } else {
+ return previousSessionsBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder>
+ getPreviousSessionsOrBuilderList() {
+ if (previousSessionsBuilder_ != null) {
+ return previousSessionsBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(previousSessions_);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder addPreviousSessionsBuilder() {
+ return getPreviousSessionsFieldBuilder().addBuilder(
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder addPreviousSessionsBuilder(
+ int index) {
+ return getPreviousSessionsFieldBuilder().addBuilder(
+ index, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SessionStructure previousSessions = 2;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder>
+ getPreviousSessionsBuilderList() {
+ return getPreviousSessionsFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder>
+ getPreviousSessionsFieldBuilder() {
+ if (previousSessionsBuilder_ == null) {
+ previousSessionsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SessionStructureOrBuilder>(
+ previousSessions_,
+ ((bitField0_ & 0x00000002) == 0x00000002),
+ getParentForChildren(),
+ isClean());
+ previousSessions_ = null;
+ }
+ return previousSessionsBuilder_;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.RecordStructure)
+ }
+
+ static {
+ defaultInstance = new RecordStructure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.RecordStructure)
+ }
+
+ public interface PreKeyRecordStructureOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 id = 1;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ boolean hasId();
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ int getId();
+
+ // optional bytes publicKey = 2;
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ boolean hasPublicKey();
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getPublicKey();
+
+ // optional bytes privateKey = 3;
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ boolean hasPrivateKey();
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ com.google.protobuf.ByteString getPrivateKey();
+ }
+ /**
+ * Protobuf type {@code textsecure.PreKeyRecordStructure}
+ */
+ public static final class PreKeyRecordStructure extends
+ com.google.protobuf.GeneratedMessage
+ implements PreKeyRecordStructureOrBuilder {
+ // Use PreKeyRecordStructure.newBuilder() to construct.
+ private PreKeyRecordStructure(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private PreKeyRecordStructure(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final PreKeyRecordStructure defaultInstance;
+ public static PreKeyRecordStructure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PreKeyRecordStructure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private PreKeyRecordStructure(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ id_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ publicKey_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ privateKey_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<PreKeyRecordStructure> PARSER =
+ new com.google.protobuf.AbstractParser<PreKeyRecordStructure>() {
+ public PreKeyRecordStructure parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new PreKeyRecordStructure(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<PreKeyRecordStructure> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 id = 1;
+ public static final int ID_FIELD_NUMBER = 1;
+ private int id_;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+
+ // optional bytes publicKey = 2;
+ public static final int PUBLICKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString publicKey_;
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public boolean hasPublicKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPublicKey() {
+ return publicKey_;
+ }
+
+ // optional bytes privateKey = 3;
+ public static final int PRIVATEKEY_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString privateKey_;
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public boolean hasPrivateKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getPrivateKey() {
+ return privateKey_;
+ }
+
+ private void initFields() {
+ id_ = 0;
+ publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, publicKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, privateKey_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, publicKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, privateKey_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.PreKeyRecordStructure}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructureOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ id_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure result = new org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.id_ = id_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.publicKey_ = publicKey_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.privateKey_ = privateKey_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasPublicKey()) {
+ setPublicKey(other.getPublicKey());
+ }
+ if (other.hasPrivateKey()) {
+ setPrivateKey(other.getPrivateKey());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.PreKeyRecordStructure) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 id = 1;
+ private int id_ ;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder setId(int value) {
+ bitField0_ |= 0x00000001;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes publicKey = 2;
+ private com.google.protobuf.ByteString publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public boolean hasPublicKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPublicKey() {
+ return publicKey_;
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public Builder setPublicKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ publicKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public Builder clearPublicKey() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ publicKey_ = getDefaultInstance().getPublicKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes privateKey = 3;
+ private com.google.protobuf.ByteString privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public boolean hasPrivateKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getPrivateKey() {
+ return privateKey_;
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public Builder setPrivateKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ privateKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public Builder clearPrivateKey() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ privateKey_ = getDefaultInstance().getPrivateKey();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.PreKeyRecordStructure)
+ }
+
+ static {
+ defaultInstance = new PreKeyRecordStructure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.PreKeyRecordStructure)
+ }
+
+ public interface SignedPreKeyRecordStructureOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 id = 1;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ boolean hasId();
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ int getId();
+
+ // optional bytes publicKey = 2;
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ boolean hasPublicKey();
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getPublicKey();
+
+ // optional bytes privateKey = 3;
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ boolean hasPrivateKey();
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ com.google.protobuf.ByteString getPrivateKey();
+
+ // optional bytes signature = 4;
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ boolean hasSignature();
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ com.google.protobuf.ByteString getSignature();
+
+ // optional fixed64 timestamp = 5;
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ boolean hasTimestamp();
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ long getTimestamp();
+ }
+ /**
+ * Protobuf type {@code textsecure.SignedPreKeyRecordStructure}
+ */
+ public static final class SignedPreKeyRecordStructure extends
+ com.google.protobuf.GeneratedMessage
+ implements SignedPreKeyRecordStructureOrBuilder {
+ // Use SignedPreKeyRecordStructure.newBuilder() to construct.
+ private SignedPreKeyRecordStructure(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SignedPreKeyRecordStructure(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SignedPreKeyRecordStructure defaultInstance;
+ public static SignedPreKeyRecordStructure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SignedPreKeyRecordStructure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SignedPreKeyRecordStructure(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ id_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ publicKey_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ privateKey_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ signature_ = input.readBytes();
+ break;
+ }
+ case 41: {
+ bitField0_ |= 0x00000010;
+ timestamp_ = input.readFixed64();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SignedPreKeyRecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SignedPreKeyRecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SignedPreKeyRecordStructure> PARSER =
+ new com.google.protobuf.AbstractParser<SignedPreKeyRecordStructure>() {
+ public SignedPreKeyRecordStructure parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SignedPreKeyRecordStructure(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SignedPreKeyRecordStructure> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 id = 1;
+ public static final int ID_FIELD_NUMBER = 1;
+ private int id_;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+
+ // optional bytes publicKey = 2;
+ public static final int PUBLICKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString publicKey_;
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public boolean hasPublicKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPublicKey() {
+ return publicKey_;
+ }
+
+ // optional bytes privateKey = 3;
+ public static final int PRIVATEKEY_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString privateKey_;
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public boolean hasPrivateKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getPrivateKey() {
+ return privateKey_;
+ }
+
+ // optional bytes signature = 4;
+ public static final int SIGNATURE_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString signature_;
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ public boolean hasSignature() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ public com.google.protobuf.ByteString getSignature() {
+ return signature_;
+ }
+
+ // optional fixed64 timestamp = 5;
+ public static final int TIMESTAMP_FIELD_NUMBER = 5;
+ private long timestamp_;
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ public boolean hasTimestamp() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ public long getTimestamp() {
+ return timestamp_;
+ }
+
+ private void initFields() {
+ id_ = 0;
+ publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ signature_ = com.google.protobuf.ByteString.EMPTY;
+ timestamp_ = 0L;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, publicKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, privateKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, signature_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ output.writeFixed64(5, timestamp_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, publicKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, privateKey_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, signature_);
+ }
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeFixed64Size(5, timestamp_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SignedPreKeyRecordStructure}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructureOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SignedPreKeyRecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SignedPreKeyRecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ id_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ signature_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ timestamp_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SignedPreKeyRecordStructure_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure result = new org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.id_ = id_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.publicKey_ = publicKey_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.privateKey_ = privateKey_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.signature_ = signature_;
+ if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+ to_bitField0_ |= 0x00000010;
+ }
+ result.timestamp_ = timestamp_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasPublicKey()) {
+ setPublicKey(other.getPublicKey());
+ }
+ if (other.hasPrivateKey()) {
+ setPrivateKey(other.getPrivateKey());
+ }
+ if (other.hasSignature()) {
+ setSignature(other.getSignature());
+ }
+ if (other.hasTimestamp()) {
+ setTimestamp(other.getTimestamp());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SignedPreKeyRecordStructure) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 id = 1;
+ private int id_ ;
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public int getId() {
+ return id_;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder setId(int value) {
+ bitField0_ |= 0x00000001;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 id = 1;</code>
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes publicKey = 2;
+ private com.google.protobuf.ByteString publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public boolean hasPublicKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPublicKey() {
+ return publicKey_;
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public Builder setPublicKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ publicKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes publicKey = 2;</code>
+ */
+ public Builder clearPublicKey() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ publicKey_ = getDefaultInstance().getPublicKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes privateKey = 3;
+ private com.google.protobuf.ByteString privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public boolean hasPrivateKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public com.google.protobuf.ByteString getPrivateKey() {
+ return privateKey_;
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public Builder setPrivateKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ privateKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes privateKey = 3;</code>
+ */
+ public Builder clearPrivateKey() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ privateKey_ = getDefaultInstance().getPrivateKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes signature = 4;
+ private com.google.protobuf.ByteString signature_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ public boolean hasSignature() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ public com.google.protobuf.ByteString getSignature() {
+ return signature_;
+ }
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ public Builder setSignature(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ signature_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes signature = 4;</code>
+ */
+ public Builder clearSignature() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ signature_ = getDefaultInstance().getSignature();
+ onChanged();
+ return this;
+ }
+
+ // optional fixed64 timestamp = 5;
+ private long timestamp_ ;
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ public boolean hasTimestamp() {
+ return ((bitField0_ & 0x00000010) == 0x00000010);
+ }
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ public long getTimestamp() {
+ return timestamp_;
+ }
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ public Builder setTimestamp(long value) {
+ bitField0_ |= 0x00000010;
+ timestamp_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional fixed64 timestamp = 5;</code>
+ */
+ public Builder clearTimestamp() {
+ bitField0_ = (bitField0_ & ~0x00000010);
+ timestamp_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SignedPreKeyRecordStructure)
+ }
+
+ static {
+ defaultInstance = new SignedPreKeyRecordStructure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SignedPreKeyRecordStructure)
+ }
+
+ public interface IdentityKeyPairStructureOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional bytes publicKey = 1;
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ boolean hasPublicKey();
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ com.google.protobuf.ByteString getPublicKey();
+
+ // optional bytes privateKey = 2;
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ boolean hasPrivateKey();
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ com.google.protobuf.ByteString getPrivateKey();
+ }
+ /**
+ * Protobuf type {@code textsecure.IdentityKeyPairStructure}
+ */
+ public static final class IdentityKeyPairStructure extends
+ com.google.protobuf.GeneratedMessage
+ implements IdentityKeyPairStructureOrBuilder {
+ // Use IdentityKeyPairStructure.newBuilder() to construct.
+ private IdentityKeyPairStructure(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private IdentityKeyPairStructure(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final IdentityKeyPairStructure defaultInstance;
+ public static IdentityKeyPairStructure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public IdentityKeyPairStructure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private IdentityKeyPairStructure(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ publicKey_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ privateKey_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_IdentityKeyPairStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_IdentityKeyPairStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<IdentityKeyPairStructure> PARSER =
+ new com.google.protobuf.AbstractParser<IdentityKeyPairStructure>() {
+ public IdentityKeyPairStructure parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new IdentityKeyPairStructure(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<IdentityKeyPairStructure> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional bytes publicKey = 1;
+ public static final int PUBLICKEY_FIELD_NUMBER = 1;
+ private com.google.protobuf.ByteString publicKey_;
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ public boolean hasPublicKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ public com.google.protobuf.ByteString getPublicKey() {
+ return publicKey_;
+ }
+
+ // optional bytes privateKey = 2;
+ public static final int PRIVATEKEY_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString privateKey_;
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ public boolean hasPrivateKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPrivateKey() {
+ return privateKey_;
+ }
+
+ private void initFields() {
+ publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, publicKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, privateKey_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, publicKey_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, privateKey_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.IdentityKeyPairStructure}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructureOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_IdentityKeyPairStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_IdentityKeyPairStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_IdentityKeyPairStructure_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure result = new org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.publicKey_ = publicKey_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.privateKey_ = privateKey_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure.getDefaultInstance()) return this;
+ if (other.hasPublicKey()) {
+ setPublicKey(other.getPublicKey());
+ }
+ if (other.hasPrivateKey()) {
+ setPrivateKey(other.getPrivateKey());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.IdentityKeyPairStructure) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional bytes publicKey = 1;
+ private com.google.protobuf.ByteString publicKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ public boolean hasPublicKey() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ public com.google.protobuf.ByteString getPublicKey() {
+ return publicKey_;
+ }
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ public Builder setPublicKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ publicKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes publicKey = 1;</code>
+ */
+ public Builder clearPublicKey() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ publicKey_ = getDefaultInstance().getPublicKey();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes privateKey = 2;
+ private com.google.protobuf.ByteString privateKey_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ public boolean hasPrivateKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPrivateKey() {
+ return privateKey_;
+ }
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ public Builder setPrivateKey(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ privateKey_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes privateKey = 2;</code>
+ */
+ public Builder clearPrivateKey() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ privateKey_ = getDefaultInstance().getPrivateKey();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.IdentityKeyPairStructure)
+ }
+
+ static {
+ defaultInstance = new IdentityKeyPairStructure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.IdentityKeyPairStructure)
+ }
+
+ public interface SenderKeyStateStructureOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 senderKeyId = 1;
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ boolean hasSenderKeyId();
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ int getSenderKeyId();
+
+ // optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ boolean hasSenderChainKey();
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey getSenderChainKey();
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKeyOrBuilder getSenderChainKeyOrBuilder();
+
+ // optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ boolean hasSenderSigningKey();
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey getSenderSigningKey();
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKeyOrBuilder getSenderSigningKeyOrBuilder();
+
+ // repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey>
+ getSenderMessageKeysList();
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey getSenderMessageKeys(int index);
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ int getSenderMessageKeysCount();
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder>
+ getSenderMessageKeysOrBuilderList();
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder getSenderMessageKeysOrBuilder(
+ int index);
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure}
+ */
+ public static final class SenderKeyStateStructure extends
+ com.google.protobuf.GeneratedMessage
+ implements SenderKeyStateStructureOrBuilder {
+ // Use SenderKeyStateStructure.newBuilder() to construct.
+ private SenderKeyStateStructure(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SenderKeyStateStructure(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SenderKeyStateStructure defaultInstance;
+ public static SenderKeyStateStructure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SenderKeyStateStructure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SenderKeyStateStructure(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ senderKeyId_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ subBuilder = senderChainKey_.toBuilder();
+ }
+ senderChainKey_ = input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(senderChainKey_);
+ senderChainKey_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000002;
+ break;
+ }
+ case 26: {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ subBuilder = senderSigningKey_.toBuilder();
+ }
+ senderSigningKey_ = input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(senderSigningKey_);
+ senderSigningKey_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000004;
+ break;
+ }
+ case 34: {
+ if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+ senderMessageKeys_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey>();
+ mutable_bitField0_ |= 0x00000008;
+ }
+ senderMessageKeys_.add(input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.PARSER, extensionRegistry));
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+ senderMessageKeys_ = java.util.Collections.unmodifiableList(senderMessageKeys_);
+ }
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SenderKeyStateStructure> PARSER =
+ new com.google.protobuf.AbstractParser<SenderKeyStateStructure>() {
+ public SenderKeyStateStructure parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SenderKeyStateStructure(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SenderKeyStateStructure> getParserForType() {
+ return PARSER;
+ }
+
+ public interface SenderChainKeyOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 iteration = 1;
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ boolean hasIteration();
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ int getIteration();
+
+ // optional bytes seed = 2;
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ boolean hasSeed();
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ com.google.protobuf.ByteString getSeed();
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure.SenderChainKey}
+ */
+ public static final class SenderChainKey extends
+ com.google.protobuf.GeneratedMessage
+ implements SenderChainKeyOrBuilder {
+ // Use SenderChainKey.newBuilder() to construct.
+ private SenderChainKey(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SenderChainKey(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SenderChainKey defaultInstance;
+ public static SenderChainKey getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SenderChainKey getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SenderChainKey(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ iteration_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ seed_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SenderChainKey> PARSER =
+ new com.google.protobuf.AbstractParser<SenderChainKey>() {
+ public SenderChainKey parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SenderChainKey(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SenderChainKey> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 iteration = 1;
+ public static final int ITERATION_FIELD_NUMBER = 1;
+ private int iteration_;
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+
+ // optional bytes seed = 2;
+ public static final int SEED_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString seed_;
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public boolean hasSeed() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public com.google.protobuf.ByteString getSeed() {
+ return seed_;
+ }
+
+ private void initFields() {
+ iteration_ = 0;
+ seed_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, iteration_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, seed_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, iteration_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, seed_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure.SenderChainKey}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKeyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ iteration_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ seed_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey result = new org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.iteration_ = iteration_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.seed_ = seed_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.getDefaultInstance()) return this;
+ if (other.hasIteration()) {
+ setIteration(other.getIteration());
+ }
+ if (other.hasSeed()) {
+ setSeed(other.getSeed());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 iteration = 1;
+ private int iteration_ ;
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public Builder setIteration(int value) {
+ bitField0_ |= 0x00000001;
+ iteration_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public Builder clearIteration() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ iteration_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes seed = 2;
+ private com.google.protobuf.ByteString seed_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public boolean hasSeed() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public com.google.protobuf.ByteString getSeed() {
+ return seed_;
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public Builder setSeed(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ seed_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public Builder clearSeed() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ seed_ = getDefaultInstance().getSeed();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SenderKeyStateStructure.SenderChainKey)
+ }
+
+ static {
+ defaultInstance = new SenderChainKey(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure.SenderChainKey)
+ }
+
+ public interface SenderMessageKeyOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint32 iteration = 1;
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ boolean hasIteration();
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ int getIteration();
+
+ // optional bytes seed = 2;
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ boolean hasSeed();
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ com.google.protobuf.ByteString getSeed();
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure.SenderMessageKey}
+ */
+ public static final class SenderMessageKey extends
+ com.google.protobuf.GeneratedMessage
+ implements SenderMessageKeyOrBuilder {
+ // Use SenderMessageKey.newBuilder() to construct.
+ private SenderMessageKey(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SenderMessageKey(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SenderMessageKey defaultInstance;
+ public static SenderMessageKey getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SenderMessageKey getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SenderMessageKey(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ iteration_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ seed_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SenderMessageKey> PARSER =
+ new com.google.protobuf.AbstractParser<SenderMessageKey>() {
+ public SenderMessageKey parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SenderMessageKey(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SenderMessageKey> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint32 iteration = 1;
+ public static final int ITERATION_FIELD_NUMBER = 1;
+ private int iteration_;
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+
+ // optional bytes seed = 2;
+ public static final int SEED_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString seed_;
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public boolean hasSeed() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public com.google.protobuf.ByteString getSeed() {
+ return seed_;
+ }
+
+ private void initFields() {
+ iteration_ = 0;
+ seed_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, iteration_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, seed_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, iteration_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, seed_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure.SenderMessageKey}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ iteration_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ seed_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey result = new org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.iteration_ = iteration_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.seed_ = seed_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.getDefaultInstance()) return this;
+ if (other.hasIteration()) {
+ setIteration(other.getIteration());
+ }
+ if (other.hasSeed()) {
+ setSeed(other.getSeed());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 iteration = 1;
+ private int iteration_ ;
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public boolean hasIteration() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public int getIteration() {
+ return iteration_;
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public Builder setIteration(int value) {
+ bitField0_ |= 0x00000001;
+ iteration_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 iteration = 1;</code>
+ */
+ public Builder clearIteration() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ iteration_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes seed = 2;
+ private com.google.protobuf.ByteString seed_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public boolean hasSeed() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public com.google.protobuf.ByteString getSeed() {
+ return seed_;
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public Builder setSeed(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ seed_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes seed = 2;</code>
+ */
+ public Builder clearSeed() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ seed_ = getDefaultInstance().getSeed();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SenderKeyStateStructure.SenderMessageKey)
+ }
+
+ static {
+ defaultInstance = new SenderMessageKey(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure.SenderMessageKey)
+ }
+
+ public interface SenderSigningKeyOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional bytes public = 1;
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ boolean hasPublic();
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ com.google.protobuf.ByteString getPublic();
+
+ // optional bytes private = 2;
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ boolean hasPrivate();
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ com.google.protobuf.ByteString getPrivate();
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure.SenderSigningKey}
+ */
+ public static final class SenderSigningKey extends
+ com.google.protobuf.GeneratedMessage
+ implements SenderSigningKeyOrBuilder {
+ // Use SenderSigningKey.newBuilder() to construct.
+ private SenderSigningKey(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SenderSigningKey(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SenderSigningKey defaultInstance;
+ public static SenderSigningKey getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SenderSigningKey getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SenderSigningKey(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ public_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ private_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SenderSigningKey> PARSER =
+ new com.google.protobuf.AbstractParser<SenderSigningKey>() {
+ public SenderSigningKey parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SenderSigningKey(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SenderSigningKey> getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional bytes public = 1;
+ public static final int PUBLIC_FIELD_NUMBER = 1;
+ private com.google.protobuf.ByteString public_;
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ public boolean hasPublic() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ public com.google.protobuf.ByteString getPublic() {
+ return public_;
+ }
+
+ // optional bytes private = 2;
+ public static final int PRIVATE_FIELD_NUMBER = 2;
+ private com.google.protobuf.ByteString private_;
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ public boolean hasPrivate() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPrivate() {
+ return private_;
+ }
+
+ private void initFields() {
+ public_ = com.google.protobuf.ByteString.EMPTY;
+ private_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, public_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, private_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, public_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, private_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure.SenderSigningKey}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKeyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ public_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ private_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey result = new org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.public_ = public_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.private_ = private_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.getDefaultInstance()) return this;
+ if (other.hasPublic()) {
+ setPublic(other.getPublic());
+ }
+ if (other.hasPrivate()) {
+ setPrivate(other.getPrivate());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional bytes public = 1;
+ private com.google.protobuf.ByteString public_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ public boolean hasPublic() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ public com.google.protobuf.ByteString getPublic() {
+ return public_;
+ }
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ public Builder setPublic(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ public_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes public = 1;</code>
+ */
+ public Builder clearPublic() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ public_ = getDefaultInstance().getPublic();
+ onChanged();
+ return this;
+ }
+
+ // optional bytes private = 2;
+ private com.google.protobuf.ByteString private_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ public boolean hasPrivate() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ public com.google.protobuf.ByteString getPrivate() {
+ return private_;
+ }
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ public Builder setPrivate(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ private_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes private = 2;</code>
+ */
+ public Builder clearPrivate() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ private_ = getDefaultInstance().getPrivate();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SenderKeyStateStructure.SenderSigningKey)
+ }
+
+ static {
+ defaultInstance = new SenderSigningKey(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure.SenderSigningKey)
+ }
+
+ private int bitField0_;
+ // optional uint32 senderKeyId = 1;
+ public static final int SENDERKEYID_FIELD_NUMBER = 1;
+ private int senderKeyId_;
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ public boolean hasSenderKeyId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ public int getSenderKeyId() {
+ return senderKeyId_;
+ }
+
+ // optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;
+ public static final int SENDERCHAINKEY_FIELD_NUMBER = 2;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey senderChainKey_;
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public boolean hasSenderChainKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey getSenderChainKey() {
+ return senderChainKey_;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKeyOrBuilder getSenderChainKeyOrBuilder() {
+ return senderChainKey_;
+ }
+
+ // optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;
+ public static final int SENDERSIGNINGKEY_FIELD_NUMBER = 3;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey senderSigningKey_;
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public boolean hasSenderSigningKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey getSenderSigningKey() {
+ return senderSigningKey_;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKeyOrBuilder getSenderSigningKeyOrBuilder() {
+ return senderSigningKey_;
+ }
+
+ // repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;
+ public static final int SENDERMESSAGEKEYS_FIELD_NUMBER = 4;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey> senderMessageKeys_;
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey> getSenderMessageKeysList() {
+ return senderMessageKeys_;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder>
+ getSenderMessageKeysOrBuilderList() {
+ return senderMessageKeys_;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public int getSenderMessageKeysCount() {
+ return senderMessageKeys_.size();
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey getSenderMessageKeys(int index) {
+ return senderMessageKeys_.get(index);
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder getSenderMessageKeysOrBuilder(
+ int index) {
+ return senderMessageKeys_.get(index);
+ }
+
+ private void initFields() {
+ senderKeyId_ = 0;
+ senderChainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.getDefaultInstance();
+ senderSigningKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.getDefaultInstance();
+ senderMessageKeys_ = java.util.Collections.emptyList();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt32(1, senderKeyId_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeMessage(2, senderChainKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, senderSigningKey_);
+ }
+ for (int i = 0; i < senderMessageKeys_.size(); i++) {
+ output.writeMessage(4, senderMessageKeys_.get(i));
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, senderKeyId_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, senderChainKey_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, senderSigningKey_);
+ }
+ for (int i = 0; i < senderMessageKeys_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, senderMessageKeys_.get(i));
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyStateStructure}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ getSenderChainKeyFieldBuilder();
+ getSenderSigningKeyFieldBuilder();
+ getSenderMessageKeysFieldBuilder();
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ senderKeyId_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ if (senderChainKeyBuilder_ == null) {
+ senderChainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.getDefaultInstance();
+ } else {
+ senderChainKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000002);
+ if (senderSigningKeyBuilder_ == null) {
+ senderSigningKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.getDefaultInstance();
+ } else {
+ senderSigningKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000004);
+ if (senderMessageKeysBuilder_ == null) {
+ senderMessageKeys_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ senderMessageKeysBuilder_.clear();
+ }
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyStateStructure_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure result = new org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.senderKeyId_ = senderKeyId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ if (senderChainKeyBuilder_ == null) {
+ result.senderChainKey_ = senderChainKey_;
+ } else {
+ result.senderChainKey_ = senderChainKeyBuilder_.build();
+ }
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ if (senderSigningKeyBuilder_ == null) {
+ result.senderSigningKey_ = senderSigningKey_;
+ } else {
+ result.senderSigningKey_ = senderSigningKeyBuilder_.build();
+ }
+ if (senderMessageKeysBuilder_ == null) {
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ senderMessageKeys_ = java.util.Collections.unmodifiableList(senderMessageKeys_);
+ bitField0_ = (bitField0_ & ~0x00000008);
+ }
+ result.senderMessageKeys_ = senderMessageKeys_;
+ } else {
+ result.senderMessageKeys_ = senderMessageKeysBuilder_.build();
+ }
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.getDefaultInstance()) return this;
+ if (other.hasSenderKeyId()) {
+ setSenderKeyId(other.getSenderKeyId());
+ }
+ if (other.hasSenderChainKey()) {
+ mergeSenderChainKey(other.getSenderChainKey());
+ }
+ if (other.hasSenderSigningKey()) {
+ mergeSenderSigningKey(other.getSenderSigningKey());
+ }
+ if (senderMessageKeysBuilder_ == null) {
+ if (!other.senderMessageKeys_.isEmpty()) {
+ if (senderMessageKeys_.isEmpty()) {
+ senderMessageKeys_ = other.senderMessageKeys_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ } else {
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.addAll(other.senderMessageKeys_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.senderMessageKeys_.isEmpty()) {
+ if (senderMessageKeysBuilder_.isEmpty()) {
+ senderMessageKeysBuilder_.dispose();
+ senderMessageKeysBuilder_ = null;
+ senderMessageKeys_ = other.senderMessageKeys_;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ senderMessageKeysBuilder_ =
+ com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+ getSenderMessageKeysFieldBuilder() : null;
+ } else {
+ senderMessageKeysBuilder_.addAllMessages(other.senderMessageKeys_);
+ }
+ }
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint32 senderKeyId = 1;
+ private int senderKeyId_ ;
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ public boolean hasSenderKeyId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ public int getSenderKeyId() {
+ return senderKeyId_;
+ }
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ public Builder setSenderKeyId(int value) {
+ bitField0_ |= 0x00000001;
+ senderKeyId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 senderKeyId = 1;</code>
+ */
+ public Builder clearSenderKeyId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ senderKeyId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey senderChainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKeyOrBuilder> senderChainKeyBuilder_;
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public boolean hasSenderChainKey() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey getSenderChainKey() {
+ if (senderChainKeyBuilder_ == null) {
+ return senderChainKey_;
+ } else {
+ return senderChainKeyBuilder_.getMessage();
+ }
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public Builder setSenderChainKey(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey value) {
+ if (senderChainKeyBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ senderChainKey_ = value;
+ onChanged();
+ } else {
+ senderChainKeyBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public Builder setSenderChainKey(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder builderForValue) {
+ if (senderChainKeyBuilder_ == null) {
+ senderChainKey_ = builderForValue.build();
+ onChanged();
+ } else {
+ senderChainKeyBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public Builder mergeSenderChainKey(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey value) {
+ if (senderChainKeyBuilder_ == null) {
+ if (((bitField0_ & 0x00000002) == 0x00000002) &&
+ senderChainKey_ != org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.getDefaultInstance()) {
+ senderChainKey_ =
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.newBuilder(senderChainKey_).mergeFrom(value).buildPartial();
+ } else {
+ senderChainKey_ = value;
+ }
+ onChanged();
+ } else {
+ senderChainKeyBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public Builder clearSenderChainKey() {
+ if (senderChainKeyBuilder_ == null) {
+ senderChainKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.getDefaultInstance();
+ onChanged();
+ } else {
+ senderChainKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder getSenderChainKeyBuilder() {
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return getSenderChainKeyFieldBuilder().getBuilder();
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKeyOrBuilder getSenderChainKeyOrBuilder() {
+ if (senderChainKeyBuilder_ != null) {
+ return senderChainKeyBuilder_.getMessageOrBuilder();
+ } else {
+ return senderChainKey_;
+ }
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderChainKey senderChainKey = 2;</code>
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKeyOrBuilder>
+ getSenderChainKeyFieldBuilder() {
+ if (senderChainKeyBuilder_ == null) {
+ senderChainKeyBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderChainKeyOrBuilder>(
+ senderChainKey_,
+ getParentForChildren(),
+ isClean());
+ senderChainKey_ = null;
+ }
+ return senderChainKeyBuilder_;
+ }
+
+ // optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;
+ private org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey senderSigningKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKeyOrBuilder> senderSigningKeyBuilder_;
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public boolean hasSenderSigningKey() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey getSenderSigningKey() {
+ if (senderSigningKeyBuilder_ == null) {
+ return senderSigningKey_;
+ } else {
+ return senderSigningKeyBuilder_.getMessage();
+ }
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public Builder setSenderSigningKey(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey value) {
+ if (senderSigningKeyBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ senderSigningKey_ = value;
+ onChanged();
+ } else {
+ senderSigningKeyBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public Builder setSenderSigningKey(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder builderForValue) {
+ if (senderSigningKeyBuilder_ == null) {
+ senderSigningKey_ = builderForValue.build();
+ onChanged();
+ } else {
+ senderSigningKeyBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public Builder mergeSenderSigningKey(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey value) {
+ if (senderSigningKeyBuilder_ == null) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ senderSigningKey_ != org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.getDefaultInstance()) {
+ senderSigningKey_ =
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.newBuilder(senderSigningKey_).mergeFrom(value).buildPartial();
+ } else {
+ senderSigningKey_ = value;
+ }
+ onChanged();
+ } else {
+ senderSigningKeyBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public Builder clearSenderSigningKey() {
+ if (senderSigningKeyBuilder_ == null) {
+ senderSigningKey_ = org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.getDefaultInstance();
+ onChanged();
+ } else {
+ senderSigningKeyBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder getSenderSigningKeyBuilder() {
+ bitField0_ |= 0x00000004;
+ onChanged();
+ return getSenderSigningKeyFieldBuilder().getBuilder();
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKeyOrBuilder getSenderSigningKeyOrBuilder() {
+ if (senderSigningKeyBuilder_ != null) {
+ return senderSigningKeyBuilder_.getMessageOrBuilder();
+ } else {
+ return senderSigningKey_;
+ }
+ }
+ /**
+ * <code>optional .textsecure.SenderKeyStateStructure.SenderSigningKey senderSigningKey = 3;</code>
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKeyOrBuilder>
+ getSenderSigningKeyFieldBuilder() {
+ if (senderSigningKeyBuilder_ == null) {
+ senderSigningKeyBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderSigningKeyOrBuilder>(
+ senderSigningKey_,
+ getParentForChildren(),
+ isClean());
+ senderSigningKey_ = null;
+ }
+ return senderSigningKeyBuilder_;
+ }
+
+ // repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey> senderMessageKeys_ =
+ java.util.Collections.emptyList();
+ private void ensureSenderMessageKeysIsMutable() {
+ if (!((bitField0_ & 0x00000008) == 0x00000008)) {
+ senderMessageKeys_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey>(senderMessageKeys_);
+ bitField0_ |= 0x00000008;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder> senderMessageKeysBuilder_;
+
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey> getSenderMessageKeysList() {
+ if (senderMessageKeysBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(senderMessageKeys_);
+ } else {
+ return senderMessageKeysBuilder_.getMessageList();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public int getSenderMessageKeysCount() {
+ if (senderMessageKeysBuilder_ == null) {
+ return senderMessageKeys_.size();
+ } else {
+ return senderMessageKeysBuilder_.getCount();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey getSenderMessageKeys(int index) {
+ if (senderMessageKeysBuilder_ == null) {
+ return senderMessageKeys_.get(index);
+ } else {
+ return senderMessageKeysBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder setSenderMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey value) {
+ if (senderMessageKeysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.set(index, value);
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder setSenderMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder builderForValue) {
+ if (senderMessageKeysBuilder_ == null) {
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder addSenderMessageKeys(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey value) {
+ if (senderMessageKeysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.add(value);
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder addSenderMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey value) {
+ if (senderMessageKeysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.add(index, value);
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder addSenderMessageKeys(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder builderForValue) {
+ if (senderMessageKeysBuilder_ == null) {
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.add(builderForValue.build());
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder addSenderMessageKeys(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder builderForValue) {
+ if (senderMessageKeysBuilder_ == null) {
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder addAllSenderMessageKeys(
+ java.lang.Iterable<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey> values) {
+ if (senderMessageKeysBuilder_ == null) {
+ ensureSenderMessageKeysIsMutable();
+ super.addAll(values, senderMessageKeys_);
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder clearSenderMessageKeys() {
+ if (senderMessageKeysBuilder_ == null) {
+ senderMessageKeys_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000008);
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public Builder removeSenderMessageKeys(int index) {
+ if (senderMessageKeysBuilder_ == null) {
+ ensureSenderMessageKeysIsMutable();
+ senderMessageKeys_.remove(index);
+ onChanged();
+ } else {
+ senderMessageKeysBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder getSenderMessageKeysBuilder(
+ int index) {
+ return getSenderMessageKeysFieldBuilder().getBuilder(index);
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder getSenderMessageKeysOrBuilder(
+ int index) {
+ if (senderMessageKeysBuilder_ == null) {
+ return senderMessageKeys_.get(index); } else {
+ return senderMessageKeysBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder>
+ getSenderMessageKeysOrBuilderList() {
+ if (senderMessageKeysBuilder_ != null) {
+ return senderMessageKeysBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(senderMessageKeys_);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder addSenderMessageKeysBuilder() {
+ return getSenderMessageKeysFieldBuilder().addBuilder(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder addSenderMessageKeysBuilder(
+ int index) {
+ return getSenderMessageKeysFieldBuilder().addBuilder(
+ index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure.SenderMessageKey senderMessageKeys = 4;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder>
+ getSenderMessageKeysBuilderList() {
+ return getSenderMessageKeysFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder>
+ getSenderMessageKeysFieldBuilder() {
+ if (senderMessageKeysBuilder_ == null) {
+ senderMessageKeysBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKey.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.SenderMessageKeyOrBuilder>(
+ senderMessageKeys_,
+ ((bitField0_ & 0x00000008) == 0x00000008),
+ getParentForChildren(),
+ isClean());
+ senderMessageKeys_ = null;
+ }
+ return senderMessageKeysBuilder_;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SenderKeyStateStructure)
+ }
+
+ static {
+ defaultInstance = new SenderKeyStateStructure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SenderKeyStateStructure)
+ }
+
+ public interface SenderKeyRecordStructureOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure>
+ getSenderKeyStatesList();
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure getSenderKeyStates(int index);
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ int getSenderKeyStatesCount();
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder>
+ getSenderKeyStatesOrBuilderList();
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder getSenderKeyStatesOrBuilder(
+ int index);
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyRecordStructure}
+ */
+ public static final class SenderKeyRecordStructure extends
+ com.google.protobuf.GeneratedMessage
+ implements SenderKeyRecordStructureOrBuilder {
+ // Use SenderKeyRecordStructure.newBuilder() to construct.
+ private SenderKeyRecordStructure(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private SenderKeyRecordStructure(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final SenderKeyRecordStructure defaultInstance;
+ public static SenderKeyRecordStructure getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public SenderKeyRecordStructure getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private SenderKeyRecordStructure(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 10: {
+ if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+ senderKeyStates_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure>();
+ mutable_bitField0_ |= 0x00000001;
+ }
+ senderKeyStates_.add(input.readMessage(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.PARSER, extensionRegistry));
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+ senderKeyStates_ = java.util.Collections.unmodifiableList(senderKeyStates_);
+ }
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyRecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyRecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser<SenderKeyRecordStructure> PARSER =
+ new com.google.protobuf.AbstractParser<SenderKeyRecordStructure>() {
+ public SenderKeyRecordStructure parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new SenderKeyRecordStructure(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<SenderKeyRecordStructure> getParserForType() {
+ return PARSER;
+ }
+
+ // repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;
+ public static final int SENDERKEYSTATES_FIELD_NUMBER = 1;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure> senderKeyStates_;
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure> getSenderKeyStatesList() {
+ return senderKeyStates_;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder>
+ getSenderKeyStatesOrBuilderList() {
+ return senderKeyStates_;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public int getSenderKeyStatesCount() {
+ return senderKeyStates_.size();
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure getSenderKeyStates(int index) {
+ return senderKeyStates_.get(index);
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder getSenderKeyStatesOrBuilder(
+ int index) {
+ return senderKeyStates_.get(index);
+ }
+
+ private void initFields() {
+ senderKeyStates_ = java.util.Collections.emptyList();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ for (int i = 0; i < senderKeyStates_.size(); i++) {
+ output.writeMessage(1, senderKeyStates_.get(i));
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ for (int i = 0; i < senderKeyStates_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, senderKeyStates_.get(i));
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.SenderKeyRecordStructure}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder>
+ implements org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructureOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyRecordStructure_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyRecordStructure_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure.class, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure.Builder.class);
+ }
+
+ // Construct using org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ getSenderKeyStatesFieldBuilder();
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ if (senderKeyStatesBuilder_ == null) {
+ senderKeyStates_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ } else {
+ senderKeyStatesBuilder_.clear();
+ }
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.internal_static_textsecure_SenderKeyRecordStructure_descriptor;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure getDefaultInstanceForType() {
+ return org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure.getDefaultInstance();
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure build() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure buildPartial() {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure result = new org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure(this);
+ int from_bitField0_ = bitField0_;
+ if (senderKeyStatesBuilder_ == null) {
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ senderKeyStates_ = java.util.Collections.unmodifiableList(senderKeyStates_);
+ bitField0_ = (bitField0_ & ~0x00000001);
+ }
+ result.senderKeyStates_ = senderKeyStates_;
+ } else {
+ result.senderKeyStates_ = senderKeyStatesBuilder_.build();
+ }
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure) {
+ return mergeFrom((org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure other) {
+ if (other == org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure.getDefaultInstance()) return this;
+ if (senderKeyStatesBuilder_ == null) {
+ if (!other.senderKeyStates_.isEmpty()) {
+ if (senderKeyStates_.isEmpty()) {
+ senderKeyStates_ = other.senderKeyStates_;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ } else {
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.addAll(other.senderKeyStates_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.senderKeyStates_.isEmpty()) {
+ if (senderKeyStatesBuilder_.isEmpty()) {
+ senderKeyStatesBuilder_.dispose();
+ senderKeyStatesBuilder_ = null;
+ senderKeyStates_ = other.senderKeyStates_;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ senderKeyStatesBuilder_ =
+ com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+ getSenderKeyStatesFieldBuilder() : null;
+ } else {
+ senderKeyStatesBuilder_.addAllMessages(other.senderKeyStates_);
+ }
+ }
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyRecordStructure) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;
+ private java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure> senderKeyStates_ =
+ java.util.Collections.emptyList();
+ private void ensureSenderKeyStatesIsMutable() {
+ if (!((bitField0_ & 0x00000001) == 0x00000001)) {
+ senderKeyStates_ = new java.util.ArrayList<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure>(senderKeyStates_);
+ bitField0_ |= 0x00000001;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder> senderKeyStatesBuilder_;
+
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure> getSenderKeyStatesList() {
+ if (senderKeyStatesBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(senderKeyStates_);
+ } else {
+ return senderKeyStatesBuilder_.getMessageList();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public int getSenderKeyStatesCount() {
+ if (senderKeyStatesBuilder_ == null) {
+ return senderKeyStates_.size();
+ } else {
+ return senderKeyStatesBuilder_.getCount();
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure getSenderKeyStates(int index) {
+ if (senderKeyStatesBuilder_ == null) {
+ return senderKeyStates_.get(index);
+ } else {
+ return senderKeyStatesBuilder_.getMessage(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder setSenderKeyStates(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure value) {
+ if (senderKeyStatesBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.set(index, value);
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder setSenderKeyStates(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder builderForValue) {
+ if (senderKeyStatesBuilder_ == null) {
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder addSenderKeyStates(org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure value) {
+ if (senderKeyStatesBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.add(value);
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder addSenderKeyStates(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure value) {
+ if (senderKeyStatesBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.add(index, value);
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder addSenderKeyStates(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder builderForValue) {
+ if (senderKeyStatesBuilder_ == null) {
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.add(builderForValue.build());
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder addSenderKeyStates(
+ int index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder builderForValue) {
+ if (senderKeyStatesBuilder_ == null) {
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder addAllSenderKeyStates(
+ java.lang.Iterable<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure> values) {
+ if (senderKeyStatesBuilder_ == null) {
+ ensureSenderKeyStatesIsMutable();
+ super.addAll(values, senderKeyStates_);
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder clearSenderKeyStates() {
+ if (senderKeyStatesBuilder_ == null) {
+ senderKeyStates_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public Builder removeSenderKeyStates(int index) {
+ if (senderKeyStatesBuilder_ == null) {
+ ensureSenderKeyStatesIsMutable();
+ senderKeyStates_.remove(index);
+ onChanged();
+ } else {
+ senderKeyStatesBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder getSenderKeyStatesBuilder(
+ int index) {
+ return getSenderKeyStatesFieldBuilder().getBuilder(index);
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder getSenderKeyStatesOrBuilder(
+ int index) {
+ if (senderKeyStatesBuilder_ == null) {
+ return senderKeyStates_.get(index); } else {
+ return senderKeyStatesBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public java.util.List<? extends org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder>
+ getSenderKeyStatesOrBuilderList() {
+ if (senderKeyStatesBuilder_ != null) {
+ return senderKeyStatesBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(senderKeyStates_);
+ }
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder addSenderKeyStatesBuilder() {
+ return getSenderKeyStatesFieldBuilder().addBuilder(
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder addSenderKeyStatesBuilder(
+ int index) {
+ return getSenderKeyStatesFieldBuilder().addBuilder(
+ index, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.getDefaultInstance());
+ }
+ /**
+ * <code>repeated .textsecure.SenderKeyStateStructure senderKeyStates = 1;</code>
+ */
+ public java.util.List<org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder>
+ getSenderKeyStatesBuilderList() {
+ return getSenderKeyStatesFieldBuilder().getBuilderList();
+ }
+ private com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder>
+ getSenderKeyStatesFieldBuilder() {
+ if (senderKeyStatesBuilder_ == null) {
+ senderKeyStatesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+ org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructure.Builder, org.whispersystems.libaxolotl.state.StorageProtos.SenderKeyStateStructureOrBuilder>(
+ senderKeyStates_,
+ ((bitField0_ & 0x00000001) == 0x00000001),
+ getParentForChildren(),
+ isClean());
+ senderKeyStates_ = null;
+ }
+ return senderKeyStatesBuilder_;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.SenderKeyRecordStructure)
+ }
+
+ static {
+ defaultInstance = new SenderKeyRecordStructure(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.SenderKeyRecordStructure)
+ }
+
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SessionStructure_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SessionStructure_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SessionStructure_Chain_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SessionStructure_Chain_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SessionStructure_Chain_ChainKey_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SessionStructure_Chain_ChainKey_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SessionStructure_Chain_MessageKey_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SessionStructure_Chain_MessageKey_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SessionStructure_PendingKeyExchange_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SessionStructure_PendingPreKey_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_RecordStructure_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_RecordStructure_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_PreKeyRecordStructure_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SignedPreKeyRecordStructure_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SignedPreKeyRecordStructure_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_IdentityKeyPairStructure_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_IdentityKeyPairStructure_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SenderKeyStateStructure_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SenderKeyStateStructure_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_SenderKeyRecordStructure_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_SenderKeyRecordStructure_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\032LocalStorageProtocol.proto\022\ntextsecure" +
+ "\"\323\010\n\020SessionStructure\022\026\n\016sessionVersion\030" +
+ "\001 \001(\r\022\033\n\023localIdentityPublic\030\002 \001(\014\022\034\n\024re" +
+ "moteIdentityPublic\030\003 \001(\014\022\017\n\007rootKey\030\004 \001(" +
+ "\014\022\027\n\017previousCounter\030\005 \001(\r\0227\n\013senderChai" +
+ "n\030\006 \001(\0132\".textsecure.SessionStructure.Ch" +
+ "ain\022:\n\016receiverChains\030\007 \003(\0132\".textsecure" +
+ ".SessionStructure.Chain\022K\n\022pendingKeyExc" +
+ "hange\030\010 \001(\0132/.textsecure.SessionStructur" +
+ "e.PendingKeyExchange\022A\n\rpendingPreKey\030\t ",
+ "\001(\0132*.textsecure.SessionStructure.Pendin" +
+ "gPreKey\022\034\n\024remoteRegistrationId\030\n \001(\r\022\033\n" +
+ "\023localRegistrationId\030\013 \001(\r\022\024\n\014needsRefre" +
+ "sh\030\014 \001(\010\022\024\n\014aliceBaseKey\030\r \001(\014\032\271\002\n\005Chain" +
+ "\022\030\n\020senderRatchetKey\030\001 \001(\014\022\037\n\027senderRatc" +
+ "hetKeyPrivate\030\002 \001(\014\022=\n\010chainKey\030\003 \001(\0132+." +
+ "textsecure.SessionStructure.Chain.ChainK" +
+ "ey\022B\n\013messageKeys\030\004 \003(\0132-.textsecure.Ses" +
+ "sionStructure.Chain.MessageKey\032&\n\010ChainK" +
+ "ey\022\r\n\005index\030\001 \001(\r\022\013\n\003key\030\002 \001(\014\032J\n\nMessag",
+ "eKey\022\r\n\005index\030\001 \001(\r\022\021\n\tcipherKey\030\002 \001(\014\022\016" +
+ "\n\006macKey\030\003 \001(\014\022\n\n\002iv\030\004 \001(\014\032\315\001\n\022PendingKe" +
+ "yExchange\022\020\n\010sequence\030\001 \001(\r\022\024\n\014localBase" +
+ "Key\030\002 \001(\014\022\033\n\023localBaseKeyPrivate\030\003 \001(\014\022\027" +
+ "\n\017localRatchetKey\030\004 \001(\014\022\036\n\026localRatchetK" +
+ "eyPrivate\030\005 \001(\014\022\030\n\020localIdentityKey\030\007 \001(" +
+ "\014\022\037\n\027localIdentityKeyPrivate\030\010 \001(\014\032J\n\rPe" +
+ "ndingPreKey\022\020\n\010preKeyId\030\001 \001(\r\022\026\n\016signedP" +
+ "reKeyId\030\003 \001(\005\022\017\n\007baseKey\030\002 \001(\014\"\177\n\017Record" +
+ "Structure\0224\n\016currentSession\030\001 \001(\0132\034.text",
+ "secure.SessionStructure\0226\n\020previousSessi" +
+ "ons\030\002 \003(\0132\034.textsecure.SessionStructure\"" +
+ "J\n\025PreKeyRecordStructure\022\n\n\002id\030\001 \001(\r\022\021\n\t" +
+ "publicKey\030\002 \001(\014\022\022\n\nprivateKey\030\003 \001(\014\"v\n\033S" +
+ "ignedPreKeyRecordStructure\022\n\n\002id\030\001 \001(\r\022\021" +
+ "\n\tpublicKey\030\002 \001(\014\022\022\n\nprivateKey\030\003 \001(\014\022\021\n" +
+ "\tsignature\030\004 \001(\014\022\021\n\ttimestamp\030\005 \001(\006\"A\n\030I" +
+ "dentityKeyPairStructure\022\021\n\tpublicKey\030\001 \001" +
+ "(\014\022\022\n\nprivateKey\030\002 \001(\014\"\270\003\n\027SenderKeyStat" +
+ "eStructure\022\023\n\013senderKeyId\030\001 \001(\r\022J\n\016sende",
+ "rChainKey\030\002 \001(\01322.textsecure.SenderKeySt" +
+ "ateStructure.SenderChainKey\022N\n\020senderSig" +
+ "ningKey\030\003 \001(\01324.textsecure.SenderKeyStat" +
+ "eStructure.SenderSigningKey\022O\n\021senderMes" +
+ "sageKeys\030\004 \003(\01324.textsecure.SenderKeySta" +
+ "teStructure.SenderMessageKey\0321\n\016SenderCh" +
+ "ainKey\022\021\n\titeration\030\001 \001(\r\022\014\n\004seed\030\002 \001(\014\032" +
+ "3\n\020SenderMessageKey\022\021\n\titeration\030\001 \001(\r\022\014" +
+ "\n\004seed\030\002 \001(\014\0323\n\020SenderSigningKey\022\016\n\006publ" +
+ "ic\030\001 \001(\014\022\017\n\007private\030\002 \001(\014\"X\n\030SenderKeyRe",
+ "cordStructure\022<\n\017senderKeyStates\030\001 \003(\0132#" +
+ ".textsecure.SenderKeyStateStructureB4\n#o" +
+ "rg.whispersystems.libaxolotl.stateB\rStor" +
+ "ageProtos"
+ };
+ com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+ new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+ public com.google.protobuf.ExtensionRegistry assignDescriptors(
+ com.google.protobuf.Descriptors.FileDescriptor root) {
+ descriptor = root;
+ internal_static_textsecure_SessionStructure_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_textsecure_SessionStructure_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SessionStructure_descriptor,
+ new java.lang.String[] { "SessionVersion", "LocalIdentityPublic", "RemoteIdentityPublic", "RootKey", "PreviousCounter", "SenderChain", "ReceiverChains", "PendingKeyExchange", "PendingPreKey", "RemoteRegistrationId", "LocalRegistrationId", "NeedsRefresh", "AliceBaseKey", });
+ internal_static_textsecure_SessionStructure_Chain_descriptor =
+ internal_static_textsecure_SessionStructure_descriptor.getNestedTypes().get(0);
+ internal_static_textsecure_SessionStructure_Chain_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SessionStructure_Chain_descriptor,
+ new java.lang.String[] { "SenderRatchetKey", "SenderRatchetKeyPrivate", "ChainKey", "MessageKeys", });
+ internal_static_textsecure_SessionStructure_Chain_ChainKey_descriptor =
+ internal_static_textsecure_SessionStructure_Chain_descriptor.getNestedTypes().get(0);
+ internal_static_textsecure_SessionStructure_Chain_ChainKey_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SessionStructure_Chain_ChainKey_descriptor,
+ new java.lang.String[] { "Index", "Key", });
+ internal_static_textsecure_SessionStructure_Chain_MessageKey_descriptor =
+ internal_static_textsecure_SessionStructure_Chain_descriptor.getNestedTypes().get(1);
+ internal_static_textsecure_SessionStructure_Chain_MessageKey_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SessionStructure_Chain_MessageKey_descriptor,
+ new java.lang.String[] { "Index", "CipherKey", "MacKey", "Iv", });
+ internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor =
+ internal_static_textsecure_SessionStructure_descriptor.getNestedTypes().get(1);
+ internal_static_textsecure_SessionStructure_PendingKeyExchange_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SessionStructure_PendingKeyExchange_descriptor,
+ new java.lang.String[] { "Sequence", "LocalBaseKey", "LocalBaseKeyPrivate", "LocalRatchetKey", "LocalRatchetKeyPrivate", "LocalIdentityKey", "LocalIdentityKeyPrivate", });
+ internal_static_textsecure_SessionStructure_PendingPreKey_descriptor =
+ internal_static_textsecure_SessionStructure_descriptor.getNestedTypes().get(2);
+ internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SessionStructure_PendingPreKey_descriptor,
+ new java.lang.String[] { "PreKeyId", "SignedPreKeyId", "BaseKey", });
+ internal_static_textsecure_RecordStructure_descriptor =
+ getDescriptor().getMessageTypes().get(1);
+ internal_static_textsecure_RecordStructure_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_RecordStructure_descriptor,
+ new java.lang.String[] { "CurrentSession", "PreviousSessions", });
+ internal_static_textsecure_PreKeyRecordStructure_descriptor =
+ getDescriptor().getMessageTypes().get(2);
+ internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_PreKeyRecordStructure_descriptor,
+ new java.lang.String[] { "Id", "PublicKey", "PrivateKey", });
+ internal_static_textsecure_SignedPreKeyRecordStructure_descriptor =
+ getDescriptor().getMessageTypes().get(3);
+ internal_static_textsecure_SignedPreKeyRecordStructure_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SignedPreKeyRecordStructure_descriptor,
+ new java.lang.String[] { "Id", "PublicKey", "PrivateKey", "Signature", "Timestamp", });
+ internal_static_textsecure_IdentityKeyPairStructure_descriptor =
+ getDescriptor().getMessageTypes().get(4);
+ internal_static_textsecure_IdentityKeyPairStructure_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_IdentityKeyPairStructure_descriptor,
+ new java.lang.String[] { "PublicKey", "PrivateKey", });
+ internal_static_textsecure_SenderKeyStateStructure_descriptor =
+ getDescriptor().getMessageTypes().get(5);
+ internal_static_textsecure_SenderKeyStateStructure_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SenderKeyStateStructure_descriptor,
+ new java.lang.String[] { "SenderKeyId", "SenderChainKey", "SenderSigningKey", "SenderMessageKeys", });
+ internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_descriptor =
+ internal_static_textsecure_SenderKeyStateStructure_descriptor.getNestedTypes().get(0);
+ internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SenderKeyStateStructure_SenderChainKey_descriptor,
+ new java.lang.String[] { "Iteration", "Seed", });
+ internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_descriptor =
+ internal_static_textsecure_SenderKeyStateStructure_descriptor.getNestedTypes().get(1);
+ internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SenderKeyStateStructure_SenderMessageKey_descriptor,
+ new java.lang.String[] { "Iteration", "Seed", });
+ internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_descriptor =
+ internal_static_textsecure_SenderKeyStateStructure_descriptor.getNestedTypes().get(2);
+ internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SenderKeyStateStructure_SenderSigningKey_descriptor,
+ new java.lang.String[] { "Public", "Private", });
+ internal_static_textsecure_SenderKeyRecordStructure_descriptor =
+ getDescriptor().getMessageTypes().get(6);
+ internal_static_textsecure_SenderKeyRecordStructure_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_SenderKeyRecordStructure_descriptor,
+ new java.lang.String[] { "SenderKeyStates", });
+ return null;
+ }
+ };
+ com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ }, assigner);
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java b/src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java
new file mode 100644
index 00000000..c213ba0b
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java
@@ -0,0 +1,248 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.text.ParseException;
+
+public class ByteUtil {
+
+ public static byte[] combine(byte[]... elements) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ for (byte[] element : elements) {
+ baos.write(element);
+ }
+
+ return baos.toByteArray();
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public static byte[][] split(byte[] input, int firstLength, int secondLength) {
+ byte[][] parts = new byte[2][];
+
+ parts[0] = new byte[firstLength];
+ System.arraycopy(input, 0, parts[0], 0, firstLength);
+
+ parts[1] = new byte[secondLength];
+ System.arraycopy(input, firstLength, parts[1], 0, secondLength);
+
+ return parts;
+ }
+
+ public static byte[][] split(byte[] input, int firstLength, int secondLength, int thirdLength)
+ throws ParseException
+ {
+ if (input == null || firstLength < 0 || secondLength < 0 || thirdLength < 0 ||
+ input.length < firstLength + secondLength + thirdLength)
+ {
+ throw new ParseException("Input too small: " + (input == null ? null : Hex.toString(input)), 0);
+ }
+
+ byte[][] parts = new byte[3][];
+
+ parts[0] = new byte[firstLength];
+ System.arraycopy(input, 0, parts[0], 0, firstLength);
+
+ parts[1] = new byte[secondLength];
+ System.arraycopy(input, firstLength, parts[1], 0, secondLength);
+
+ parts[2] = new byte[thirdLength];
+ System.arraycopy(input, firstLength + secondLength, parts[2], 0, thirdLength);
+
+ return parts;
+ }
+
+ public static byte[] trim(byte[] input, int length) {
+ byte[] result = new byte[length];
+ System.arraycopy(input, 0, result, 0, result.length);
+
+ return result;
+ }
+
+ public static byte[] copyFrom(byte[] input) {
+ byte[] output = new byte[input.length];
+ System.arraycopy(input, 0, output, 0, output.length);
+
+ return output;
+ }
+
+ public static byte intsToByteHighAndLow(int highValue, int lowValue) {
+ return (byte)((highValue << 4 | lowValue) & 0xFF);
+ }
+
+ public static int highBitsToInt(byte value) {
+ return (value & 0xFF) >> 4;
+ }
+
+ public static int lowBitsToInt(byte value) {
+ return (value & 0xF);
+ }
+
+ public static int highBitsToMedium(int value) {
+ return (value >> 12);
+ }
+
+ public static int lowBitsToMedium(int value) {
+ return (value & 0xFFF);
+ }
+
+ public static byte[] shortToByteArray(int value) {
+ byte[] bytes = new byte[2];
+ shortToByteArray(bytes, 0, value);
+ return bytes;
+ }
+
+ public static int shortToByteArray(byte[] bytes, int offset, int value) {
+ bytes[offset+1] = (byte)value;
+ bytes[offset] = (byte)(value >> 8);
+ return 2;
+ }
+
+ public static int shortToLittleEndianByteArray(byte[] bytes, int offset, int value) {
+ bytes[offset] = (byte)value;
+ bytes[offset+1] = (byte)(value >> 8);
+ return 2;
+ }
+
+ public static byte[] mediumToByteArray(int value) {
+ byte[] bytes = new byte[3];
+ mediumToByteArray(bytes, 0, value);
+ return bytes;
+ }
+
+ public static int mediumToByteArray(byte[] bytes, int offset, int value) {
+ bytes[offset + 2] = (byte)value;
+ bytes[offset + 1] = (byte)(value >> 8);
+ bytes[offset] = (byte)(value >> 16);
+ return 3;
+ }
+
+ public static byte[] intToByteArray(int value) {
+ byte[] bytes = new byte[4];
+ intToByteArray(bytes, 0, value);
+ return bytes;
+ }
+
+ public static int intToByteArray(byte[] bytes, int offset, int value) {
+ bytes[offset + 3] = (byte)value;
+ bytes[offset + 2] = (byte)(value >> 8);
+ bytes[offset + 1] = (byte)(value >> 16);
+ bytes[offset] = (byte)(value >> 24);
+ return 4;
+ }
+
+ public static int intToLittleEndianByteArray(byte[] bytes, int offset, int value) {
+ bytes[offset] = (byte)value;
+ bytes[offset+1] = (byte)(value >> 8);
+ bytes[offset+2] = (byte)(value >> 16);
+ bytes[offset+3] = (byte)(value >> 24);
+ return 4;
+ }
+
+ public static byte[] longToByteArray(long l) {
+ byte[] bytes = new byte[8];
+ longToByteArray(bytes, 0, l);
+ return bytes;
+ }
+
+ public static int longToByteArray(byte[] bytes, int offset, long value) {
+ bytes[offset + 7] = (byte)value;
+ bytes[offset + 6] = (byte)(value >> 8);
+ bytes[offset + 5] = (byte)(value >> 16);
+ bytes[offset + 4] = (byte)(value >> 24);
+ bytes[offset + 3] = (byte)(value >> 32);
+ bytes[offset + 2] = (byte)(value >> 40);
+ bytes[offset + 1] = (byte)(value >> 48);
+ bytes[offset] = (byte)(value >> 56);
+ return 8;
+ }
+
+ public static int longTo4ByteArray(byte[] bytes, int offset, long value) {
+ bytes[offset + 3] = (byte)value;
+ bytes[offset + 2] = (byte)(value >> 8);
+ bytes[offset + 1] = (byte)(value >> 16);
+ bytes[offset + 0] = (byte)(value >> 24);
+ return 4;
+ }
+
+ public static int byteArrayToShort(byte[] bytes) {
+ return byteArrayToShort(bytes, 0);
+ }
+
+ public static int byteArrayToShort(byte[] bytes, int offset) {
+ return
+ (bytes[offset] & 0xff) << 8 | (bytes[offset + 1] & 0xff);
+ }
+
+ // The SSL patented 3-byte Value.
+ public static int byteArrayToMedium(byte[] bytes, int offset) {
+ return
+ (bytes[offset] & 0xff) << 16 |
+ (bytes[offset + 1] & 0xff) << 8 |
+ (bytes[offset + 2] & 0xff);
+ }
+
+ public static int byteArrayToInt(byte[] bytes) {
+ return byteArrayToInt(bytes, 0);
+ }
+
+ public static int byteArrayToInt(byte[] bytes, int offset) {
+ return
+ (bytes[offset] & 0xff) << 24 |
+ (bytes[offset + 1] & 0xff) << 16 |
+ (bytes[offset + 2] & 0xff) << 8 |
+ (bytes[offset + 3] & 0xff);
+ }
+
+ public static int byteArrayToIntLittleEndian(byte[] bytes, int offset) {
+ return
+ (bytes[offset + 3] & 0xff) << 24 |
+ (bytes[offset + 2] & 0xff) << 16 |
+ (bytes[offset + 1] & 0xff) << 8 |
+ (bytes[offset] & 0xff);
+ }
+
+ public static long byteArrayToLong(byte[] bytes) {
+ return byteArrayToLong(bytes, 0);
+ }
+
+ public static long byteArray4ToLong(byte[] bytes, int offset) {
+ return
+ ((bytes[offset + 0] & 0xffL) << 24) |
+ ((bytes[offset + 1] & 0xffL) << 16) |
+ ((bytes[offset + 2] & 0xffL) << 8) |
+ ((bytes[offset + 3] & 0xffL));
+ }
+
+ public static long byteArrayToLong(byte[] bytes, int offset) {
+ return
+ ((bytes[offset] & 0xffL) << 56) |
+ ((bytes[offset + 1] & 0xffL) << 48) |
+ ((bytes[offset + 2] & 0xffL) << 40) |
+ ((bytes[offset + 3] & 0xffL) << 32) |
+ ((bytes[offset + 4] & 0xffL) << 24) |
+ ((bytes[offset + 5] & 0xffL) << 16) |
+ ((bytes[offset + 6] & 0xffL) << 8) |
+ ((bytes[offset + 7] & 0xffL));
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/Hex.java b/src/main/java/org/whispersystems/libaxolotl/util/Hex.java
new file mode 100644
index 00000000..19285464
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/Hex.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2014 Open Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.util;
+
+import java.io.IOException;
+
+/**
+ * Utility for generating hex dumps.
+ */
+public class Hex {
+
+ private final static char[] HEX_DIGITS = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ public static String toString(byte[] bytes) {
+ return toString(bytes, 0, bytes.length);
+ }
+
+ public static String toString(byte[] bytes, int offset, int length) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < length; i++) {
+ appendHexChar(buf, bytes[offset + i]);
+ buf.append(" ");
+ }
+ return buf.toString();
+ }
+
+ public static String toStringCondensed(byte[] bytes) {
+ StringBuffer buf = new StringBuffer();
+ for (int i=0;i<bytes.length;i++) {
+ appendHexChar(buf, bytes[i]);
+ }
+ return buf.toString();
+ }
+
+ public static byte[] fromStringCondensed(String encoded) throws IOException {
+ final char[] data = encoded.toCharArray();
+ final int len = data.length;
+
+ if ((len & 0x01) != 0) {
+ throw new IOException("Odd number of characters.");
+ }
+
+ final byte[] out = new byte[len >> 1];
+
+ for (int i = 0, j = 0; j < len; i++) {
+ int f = Character.digit(data[j], 16) << 4;
+ j++;
+ f = f | Character.digit(data[j], 16);
+ j++;
+ out[i] = (byte) (f & 0xFF);
+ }
+
+ return out;
+ }
+
+ private static void appendHexChar(StringBuffer buf, int b) {
+ buf.append(HEX_DIGITS[(b >> 4) & 0xf]);
+ buf.append(HEX_DIGITS[b & 0xf]);
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java b/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java
new file mode 100644
index 00000000..96ee6563
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java
@@ -0,0 +1,143 @@
+package org.whispersystems.libaxolotl.util;
+
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.state.PreKeyRecord;
+import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Helper class for generating keys of different types.
+ *
+ * @author Moxie Marlinspike
+ */
+public class KeyHelper {
+
+ private KeyHelper() {}
+
+ /**
+ * Generate an identity key pair. Clients should only do this once,
+ * at install time.
+ *
+ * @return the generated IdentityKeyPair.
+ */
+ public static IdentityKeyPair generateIdentityKeyPair() {
+ ECKeyPair keyPair = Curve.generateKeyPair();
+ IdentityKey publicKey = new IdentityKey(keyPair.getPublicKey());
+ return new IdentityKeyPair(publicKey, keyPair.getPrivateKey());
+ }
+
+ /**
+ * Generate a registration ID. Clients should only do this once,
+ * at install time.
+ *
+ * @param extendedRange By default (false), the generated registration
+ * ID is sized to require the minimal possible protobuf
+ * encoding overhead. Specify true if the caller needs
+ * the full range of MAX_INT at the cost of slightly
+ * higher encoding overhead.
+ * @return the generated registration ID.
+ */
+ public static int generateRegistrationId(boolean extendedRange) {
+ try {
+ SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
+ if (extendedRange) return secureRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
+ else return secureRandom.nextInt(16380) + 1;
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public static int getRandomSequence(int max) {
+ try {
+ return SecureRandom.getInstance("SHA1PRNG").nextInt(max);
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * Generate a list of PreKeys. Clients should do this at install time, and
+ * subsequently any time the list of PreKeys stored on the server runs low.
+ * <p>
+ * PreKey IDs are shorts, so they will eventually be repeated. Clients should
+ * store PreKeys in a circular buffer, so that they are repeated as infrequently
+ * as possible.
+ *
+ * @param start The starting PreKey ID, inclusive.
+ * @param count The number of PreKeys to generate.
+ * @return the list of generated PreKeyRecords.
+ */
+ public static List<PreKeyRecord> generatePreKeys(int start, int count) {
+ List<PreKeyRecord> results = new LinkedList<>();
+
+ start--;
+
+ for (int i=0;i<count;i++) {
+ results.add(new PreKeyRecord(((start + i) % (Medium.MAX_VALUE-1)) + 1, Curve.generateKeyPair()));
+ }
+
+ return results;
+ }
+
+ /**
+ * Generate the last resort PreKey. Clients should do this only once, at install
+ * time, and durably store it for the length of the install.
+ *
+ * @return the generated last resort PreKeyRecord.
+ */
+ public static PreKeyRecord generateLastResortPreKey() {
+ ECKeyPair keyPair = Curve.generateKeyPair();
+ return new PreKeyRecord(Medium.MAX_VALUE, keyPair);
+ }
+
+ /**
+ * Generate a signed PreKey
+ *
+ * @param identityKeyPair The local client's identity key pair.
+ * @param signedPreKeyId The PreKey id to assign the generated signed PreKey
+ *
+ * @return the generated signed PreKey
+ * @throws InvalidKeyException when the provided identity key is invalid
+ */
+ public static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair, int signedPreKeyId)
+ throws InvalidKeyException
+ {
+ ECKeyPair keyPair = Curve.generateKeyPair();
+ byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
+
+ return new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), keyPair, signature);
+ }
+
+
+ public static ECKeyPair generateSenderSigningKey() {
+ return Curve.generateKeyPair();
+ }
+
+ public static byte[] generateSenderKey() {
+ try {
+ byte[] key = new byte[32];
+ SecureRandom.getInstance("SHA1PRNG").nextBytes(key);
+
+ return key;
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public static int generateSenderKeyId() {
+ try {
+ return SecureRandom.getInstance("SHA1PRNG").nextInt(Integer.MAX_VALUE);
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/Medium.java b/src/main/java/org/whispersystems/libaxolotl/util/Medium.java
new file mode 100644
index 00000000..d18b2d66
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/Medium.java
@@ -0,0 +1,5 @@
+package org.whispersystems.libaxolotl.util;
+
+public class Medium {
+ public static int MAX_VALUE = 0xFFFFFF;
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/Pair.java b/src/main/java/org/whispersystems/libaxolotl/util/Pair.java
new file mode 100644
index 00000000..0476d932
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/Pair.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2014 Open WhisperSystems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.whispersystems.libaxolotl.util;
+
+public class Pair<T1, T2> {
+ private final T1 v1;
+ private final T2 v2;
+
+ public Pair(T1 v1, T2 v2) {
+ this.v1 = v1;
+ this.v2 = v2;
+ }
+
+ public T1 first(){
+ return v1;
+ }
+
+ public T2 second(){
+ return v2;
+ }
+
+ public boolean equals(Object o) {
+ return o instanceof Pair &&
+ equal(((Pair) o).first(), first()) &&
+ equal(((Pair) o).second(), second());
+ }
+
+ public int hashCode() {
+ return first().hashCode() ^ second().hashCode();
+ }
+
+ private boolean equal(Object first, Object second) {
+ if (first == null && second == null) return true;
+ if (first == null || second == null) return false;
+ return first.equals(second);
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java b/src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java
new file mode 100644
index 00000000..bd06ded9
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.whispersystems.libaxolotl.util.guava;
+
+import static org.whispersystems.libaxolotl.util.guava.Preconditions.checkNotNull;
+
+
+
+import java.util.Collections;
+import java.util.Set;
+
+
+/**
+ * Implementation of an {@link Optional} not containing a reference.
+ */
+
+final class Absent extends Optional<Object> {
+ static final Absent INSTANCE = new Absent();
+
+ @Override public boolean isPresent() {
+ return false;
+ }
+
+ @Override public Object get() {
+ throw new IllegalStateException("value is absent");
+ }
+
+ @Override public Object or(Object defaultValue) {
+ return checkNotNull(defaultValue, "use orNull() instead of or(null)");
+ }
+
+ @SuppressWarnings("unchecked") // safe covariant cast
+ @Override public Optional<Object> or(Optional<?> secondChoice) {
+ return (Optional) checkNotNull(secondChoice);
+ }
+
+ @Override public Object or(Supplier<?> supplier) {
+ return checkNotNull(supplier.get(),
+ "use orNull() instead of a Supplier that returns null");
+ }
+
+ @Override public Object orNull() {
+ return null;
+ }
+
+ @Override public Set<Object> asSet() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <V> Optional<V> transform(Function<? super Object, V> function) {
+ checkNotNull(function);
+ return Optional.absent();
+ }
+
+ @Override public boolean equals(Object object) {
+ return object == this;
+ }
+
+ @Override public int hashCode() {
+ return 0x598df91c;
+ }
+
+ @Override public String toString() {
+ return "Optional.absent()";
+ }
+
+ private Object readResolve() {
+ return INSTANCE;
+ }
+
+ private static final long serialVersionUID = 0;
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java b/src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java
new file mode 100644
index 00000000..1ad516c5
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.whispersystems.libaxolotl.util.guava;
+
+
+
+/**
+ * Determines an output value based on an input value.
+ *
+ * <p>See the Guava User Guide article on <a href=
+ * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use of {@code
+ * Function}</a>.
+ *
+ * @author Kevin Bourrillion
+ * @since 2.0 (imported from Google Collections Library)
+ */
+
+public interface Function<F, T> {
+ /**
+ * Returns the result of applying this function to {@code input}. This method is <i>generally
+ * expected</i>, but not absolutely required, to have the following properties:
+ *
+ * <ul>
+ * <li>Its execution does not cause any observable side effects.
+ * <li>The computation is <i>consistent with equals</i>; that is, {@link Objects#equal
+ * Objects.equal}{@code (a, b)} implies that {@code Objects.equal(function.apply(a),
+ * function.apply(b))}.
+ * </ul>
+ *
+ * @throws NullPointerException if {@code input} is null and this function does not accept null
+ * arguments
+ */
+ T apply(F input);
+
+ /**
+ * Indicates whether another object is equal to this function.
+ *
+ * <p>Most implementations will have no reason to override the behavior of {@link Object#equals}.
+ * However, an implementation may also choose to return {@code true} whenever {@code object} is a
+ * {@link Function} that it considers <i>interchangeable</i> with this one. "Interchangeable"
+ * <i>typically</i> means that {@code Objects.equal(this.apply(f), that.apply(f))} is true for all
+ * {@code f} of type {@code F}. Note that a {@code false} result from this method does not imply
+ * that the functions are known <i>not</i> to be interchangeable.
+ */
+ @Override
+ boolean equals(Object object);
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java b/src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java
new file mode 100644
index 00000000..4f2de832
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.whispersystems.libaxolotl.util.guava;
+
+import static org.whispersystems.libaxolotl.util.guava.Preconditions.checkNotNull;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.Set;
+
+
+/**
+ * An immutable object that may contain a non-null reference to another object. Each
+ * instance of this type either contains a non-null reference, or contains nothing (in
+ * which case we say that the reference is "absent"); it is never said to "contain {@code
+ * null}".
+ *
+ * <p>A non-null {@code Optional<T>} reference can be used as a replacement for a nullable
+ * {@code T} reference. It allows you to represent "a {@code T} that must be present" and
+ * a "a {@code T} that might be absent" as two distinct types in your program, which can
+ * aid clarity.
+ *
+ * <p>Some uses of this class include
+ *
+ * <ul>
+ * <li>As a method return type, as an alternative to returning {@code null} to indicate
+ * that no value was available
+ * <li>To distinguish between "unknown" (for example, not present in a map) and "known to
+ * have no value" (present in the map, with value {@code Optional.absent()})
+ * <li>To wrap nullable references for storage in a collection that does not support
+ * {@code null} (though there are
+ * <a href="http://code.google.com/p/guava-libraries/wiki/LivingWithNullHostileCollections">
+ * several other approaches to this</a> that should be considered first)
+ * </ul>
+ *
+ * <p>A common alternative to using this class is to find or create a suitable
+ * <a href="http://en.wikipedia.org/wiki/Null_Object_pattern">null object</a> for the
+ * type in question.
+ *
+ * <p>This class is not intended as a direct analogue of any existing "option" or "maybe"
+ * construct from other programming environments, though it may bear some similarities.
+ *
+ * <p>See the Guava User Guide article on <a
+ * href="http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional">
+ * using {@code Optional}</a>.
+ *
+ * @param <T> the type of instance that can be contained. {@code Optional} is naturally
+ * covariant on this type, so it is safe to cast an {@code Optional<T>} to {@code
+ * Optional<S>} for any supertype {@code S} of {@code T}.
+ * @author Kurt Alfred Kluever
+ * @author Kevin Bourrillion
+ * @since 10.0
+ */
+public abstract class Optional<T> implements Serializable {
+ /**
+ * Returns an {@code Optional} instance with no contained reference.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Optional<T> absent() {
+ return (Optional<T>) Absent.INSTANCE;
+ }
+
+ /**
+ * Returns an {@code Optional} instance containing the given non-null reference.
+ */
+ public static <T> Optional<T> of(T reference) {
+ return new Present<T>(checkNotNull(reference));
+ }
+
+ /**
+ * If {@code nullableReference} is non-null, returns an {@code Optional} instance containing that
+ * reference; otherwise returns {@link Optional#absent}.
+ */
+ public static <T> Optional<T> fromNullable(T nullableReference) {
+ return (nullableReference == null)
+ ? Optional.<T>absent()
+ : new Present<T>(nullableReference);
+ }
+
+ Optional() {}
+
+ /**
+ * Returns {@code true} if this holder contains a (non-null) instance.
+ */
+ public abstract boolean isPresent();
+
+ /**
+ * Returns the contained instance, which must be present. If the instance might be
+ * absent, use {@link #or(Object)} or {@link #orNull} instead.
+ *
+ * @throws IllegalStateException if the instance is absent ({@link #isPresent} returns
+ * {@code false})
+ */
+ public abstract T get();
+
+ /**
+ * Returns the contained instance if it is present; {@code defaultValue} otherwise. If
+ * no default value should be required because the instance is known to be present, use
+ * {@link #get()} instead. For a default value of {@code null}, use {@link #orNull}.
+ *
+ * <p>Note about generics: The signature {@code public T or(T defaultValue)} is overly
+ * restrictive. However, the ideal signature, {@code public <S super T> S or(S)}, is not legal
+ * Java. As a result, some sensible operations involving subtypes are compile errors:
+ * <pre> {@code
+ *
+ * Optional<Integer> optionalInt = getSomeOptionalInt();
+ * Number value = optionalInt.or(0.5); // error
+ *
+ * FluentIterable<? extends Number> numbers = getSomeNumbers();
+ * Optional<? extends Number> first = numbers.first();
+ * Number value = first.or(0.5); // error}</pre>
+ *
+ * As a workaround, it is always safe to cast an {@code Optional<? extends T>} to {@code
+ * Optional<T>}. Casting either of the above example {@code Optional} instances to {@code
+ * Optional<Number>} (where {@code Number} is the desired output type) solves the problem:
+ * <pre> {@code
+ *
+ * Optional<Number> optionalInt = (Optional) getSomeOptionalInt();
+ * Number value = optionalInt.or(0.5); // fine
+ *
+ * FluentIterable<? extends Number> numbers = getSomeNumbers();
+ * Optional<Number> first = (Optional) numbers.first();
+ * Number value = first.or(0.5); // fine}</pre>
+ */
+ public abstract T or(T defaultValue);
+
+ /**
+ * Returns this {@code Optional} if it has a value present; {@code secondChoice}
+ * otherwise.
+ */
+ public abstract Optional<T> or(Optional<? extends T> secondChoice);
+
+ /**
+ * Returns the contained instance if it is present; {@code supplier.get()} otherwise. If the
+ * supplier returns {@code null}, a {@link NullPointerException} is thrown.
+ *
+ * @throws NullPointerException if the supplier returns {@code null}
+ */
+ public abstract T or(Supplier<? extends T> supplier);
+
+ /**
+ * Returns the contained instance if it is present; {@code null} otherwise. If the
+ * instance is known to be present, use {@link #get()} instead.
+ */
+ public abstract T orNull();
+
+ /**
+ * Returns an immutable singleton {@link Set} whose only element is the contained instance
+ * if it is present; an empty immutable {@link Set} otherwise.
+ *
+ * @since 11.0
+ */
+ public abstract Set<T> asSet();
+
+ /**
+ * If the instance is present, it is transformed with the given {@link Function}; otherwise,
+ * {@link Optional#absent} is returned. If the function returns {@code null}, a
+ * {@link NullPointerException} is thrown.
+ *
+ * @throws NullPointerException if the function returns {@code null}
+ *
+ * @since 12.0
+ */
+
+ public abstract <V> Optional<V> transform(Function<? super T, V> function);
+
+ /**
+ * Returns {@code true} if {@code object} is an {@code Optional} instance, and either
+ * the contained references are {@linkplain Object#equals equal} to each other or both
+ * are absent. Note that {@code Optional} instances of differing parameterized types can
+ * be equal.
+ */
+ @Override public abstract boolean equals(Object object);
+
+ /**
+ * Returns a hash code for this instance.
+ */
+ @Override public abstract int hashCode();
+
+ /**
+ * Returns a string representation for this instance. The form of this string
+ * representation is unspecified.
+ */
+ @Override public abstract String toString();
+
+ /**
+ * Returns the value of each present instance from the supplied {@code optionals}, in order,
+ * skipping over occurrences of {@link Optional#absent}. Iterators are unmodifiable and are
+ * evaluated lazily.
+ *
+ * @since 11.0 (generics widened in 13.0)
+ */
+
+// public static <T> Iterable<T> presentInstances(
+// final Iterable<? extends Optional<? extends T>> optionals) {
+// checkNotNull(optionals);
+// return new Iterable<T>() {
+// @Override public Iterator<T> iterator() {
+// return new AbstractIterator<T>() {
+// private final Iterator<? extends Optional<? extends T>> iterator =
+// checkNotNull(optionals.iterator());
+//
+// @Override protected T computeNext() {
+// while (iterator.hasNext()) {
+// Optional<? extends T> optional = iterator.next();
+// if (optional.isPresent()) {
+// return optional.get();
+// }
+// }
+// return endOfData();
+// }
+// };
+// };
+// };
+// }
+
+ private static final long serialVersionUID = 0;
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java b/src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java
new file mode 100644
index 00000000..ce253c65
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.whispersystems.libaxolotl.util.guava;
+
+
+import java.util.NoSuchElementException;
+
+
+
+/**
+ * Simple static methods to be called at the start of your own methods to verify
+ * correct arguments and state. This allows constructs such as
+ * <pre>
+ * if (count <= 0) {
+ * throw new IllegalArgumentException("must be positive: " + count);
+ * }</pre>
+ *
+ * to be replaced with the more compact
+ * <pre>
+ * checkArgument(count > 0, "must be positive: %s", count);</pre>
+ *
+ * Note that the sense of the expression is inverted; with {@code Preconditions}
+ * you declare what you expect to be <i>true</i>, just as you do with an
+ * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html">
+ * {@code assert}</a> or a JUnit {@code assertTrue} call.
+ *
+ * <p><b>Warning:</b> only the {@code "%s"} specifier is recognized as a
+ * placeholder in these messages, not the full range of {@link
+ * String#format(String, Object[])} specifiers.
+ *
+ * <p>Take care not to confuse precondition checking with other similar types
+ * of checks! Precondition exceptions -- including those provided here, but also
+ * {@link IndexOutOfBoundsException}, {@link NoSuchElementException}, {@link
+ * UnsupportedOperationException} and others -- are used to signal that the
+ * <i>calling method</i> has made an error. This tells the caller that it should
+ * not have invoked the method when it did, with the arguments it did, or
+ * perhaps ever. Postcondition or other invariant failures should not throw
+ * these types of exceptions.
+ *
+ * <p>See the Guava User Guide on <a href=
+ * "http://code.google.com/p/guava-libraries/wiki/PreconditionsExplained">
+ * using {@code Preconditions}</a>.
+ *
+ * @author Kevin Bourrillion
+ * @since 2.0 (imported from Google Collections Library)
+ */
+
+public final class Preconditions {
+ private Preconditions() {}
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the
+ * calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(boolean expression) {
+ if (!expression) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the
+ * calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessage the exception message to use if the check fails; will
+ * be converted to a string using {@link String#valueOf(Object)}
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(
+ boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the
+ * calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessageTemplate a template for the exception message should the
+ * check fail. The message is formed by replacing each {@code %s}
+ * placeholder in the template with an argument. These are matched by
+ * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+ * Unmatched arguments will be appended to the formatted message in square
+ * braces. Unmatched placeholders will be left as-is.
+ * @param errorMessageArgs the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}.
+ * @throws IllegalArgumentException if {@code expression} is false
+ * @throws NullPointerException if the check fails and either {@code
+ * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+ * this happen)
+ */
+ public static void checkArgument(boolean expression,
+ String errorMessageTemplate,
+ Object... errorMessageArgs) {
+ if (!expression) {
+ throw new IllegalArgumentException(
+ format(errorMessageTemplate, errorMessageArgs));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling
+ * instance, but not involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(boolean expression) {
+ if (!expression) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling
+ * instance, but not involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessage the exception message to use if the check fails; will
+ * be converted to a string using {@link String#valueOf(Object)}
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(
+ boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new IllegalStateException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling
+ * instance, but not involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessageTemplate a template for the exception message should the
+ * check fail. The message is formed by replacing each {@code %s}
+ * placeholder in the template with an argument. These are matched by
+ * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+ * Unmatched arguments will be appended to the formatted message in square
+ * braces. Unmatched placeholders will be left as-is.
+ * @param errorMessageArgs the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}.
+ * @throws IllegalStateException if {@code expression} is false
+ * @throws NullPointerException if the check fails and either {@code
+ * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+ * this happen)
+ */
+ public static void checkState(boolean expression,
+ String errorMessageTemplate,
+ Object... errorMessageArgs) {
+ if (!expression) {
+ throw new IllegalStateException(
+ format(errorMessageTemplate, errorMessageArgs));
+ }
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling
+ * method is not null.
+ *
+ * @param reference an object reference
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ public static <T> T checkNotNull(T reference) {
+ if (reference == null) {
+ throw new NullPointerException();
+ }
+ return reference;
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling
+ * method is not null.
+ *
+ * @param reference an object reference
+ * @param errorMessage the exception message to use if the check fails; will
+ * be converted to a string using {@link String#valueOf(Object)}
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ public static <T> T checkNotNull(T reference, Object errorMessage) {
+ if (reference == null) {
+ throw new NullPointerException(String.valueOf(errorMessage));
+ }
+ return reference;
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling
+ * method is not null.
+ *
+ * @param reference an object reference
+ * @param errorMessageTemplate a template for the exception message should the
+ * check fail. The message is formed by replacing each {@code %s}
+ * placeholder in the template with an argument. These are matched by
+ * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+ * Unmatched arguments will be appended to the formatted message in square
+ * braces. Unmatched placeholders will be left as-is.
+ * @param errorMessageArgs the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}.
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ public static <T> T checkNotNull(T reference,
+ String errorMessageTemplate,
+ Object... errorMessageArgs) {
+ if (reference == null) {
+ // If either of these parameters is null, the right thing happens anyway
+ throw new NullPointerException(
+ format(errorMessageTemplate, errorMessageArgs));
+ }
+ return reference;
+ }
+
+ /*
+ * All recent hotspots (as of 2009) *really* like to have the natural code
+ *
+ * if (guardExpression) {
+ * throw new BadException(messageExpression);
+ * }
+ *
+ * refactored so that messageExpression is moved to a separate
+ * String-returning method.
+ *
+ * if (guardExpression) {
+ * throw new BadException(badMsg(...));
+ * }
+ *
+ * The alternative natural refactorings into void or Exception-returning
+ * methods are much slower. This is a big deal - we're talking factors of
+ * 2-8 in microbenchmarks, not just 10-20%. (This is a hotspot optimizer
+ * bug, which should be fixed, but that's a separate, big project).
+ *
+ * The coding pattern above is heavily used in java.util, e.g. in ArrayList.
+ * There is a RangeCheckMicroBenchmark in the JDK that was used to test this.
+ *
+ * But the methods in this class want to throw different exceptions,
+ * depending on the args, so it appears that this pattern is not directly
+ * applicable. But we can use the ridiculous, devious trick of throwing an
+ * exception in the middle of the construction of another exception.
+ * Hotspot is fine with that.
+ */
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+ * list or string of size {@code size}. An element index may range from zero,
+ * inclusive, to {@code size}, exclusive.
+ *
+ * @param index a user-supplied index identifying an element of an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+ * less than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkElementIndex(int index, int size) {
+ return checkElementIndex(index, size, "index");
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+ * list or string of size {@code size}. An element index may range from zero,
+ * inclusive, to {@code size}, exclusive.
+ *
+ * @param index a user-supplied index identifying an element of an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @param desc the text to use to describe this index in an error message
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+ * less than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkElementIndex(
+ int index, int size, String desc) {
+ // Carefully optimized for execution by hotspot (explanatory comment above)
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
+ }
+ return index;
+ }
+
+ private static String badElementIndex(int index, int size, String desc) {
+ if (index < 0) {
+ return format("%s (%s) must not be negative", desc, index);
+ } else if (size < 0) {
+ throw new IllegalArgumentException("negative size: " + size);
+ } else { // index >= size
+ return format("%s (%s) must be less than size (%s)", desc, index, size);
+ }
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+ * list or string of size {@code size}. A position index may range from zero
+ * to {@code size}, inclusive.
+ *
+ * @param index a user-supplied index identifying a position in an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is
+ * greater than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkPositionIndex(int index, int size) {
+ return checkPositionIndex(index, size, "index");
+ }
+
+ /**
+ * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+ * list or string of size {@code size}. A position index may range from zero
+ * to {@code size}, inclusive.
+ *
+ * @param index a user-supplied index identifying a position in an array, list
+ * or string
+ * @param size the size of that array, list or string
+ * @param desc the text to use to describe this index in an error message
+ * @return the value of {@code index}
+ * @throws IndexOutOfBoundsException if {@code index} is negative or is
+ * greater than {@code size}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static int checkPositionIndex(
+ int index, int size, String desc) {
+ // Carefully optimized for execution by hotspot (explanatory comment above)
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
+ }
+ return index;
+ }
+
+ private static String badPositionIndex(int index, int size, String desc) {
+ if (index < 0) {
+ return format("%s (%s) must not be negative", desc, index);
+ } else if (size < 0) {
+ throw new IllegalArgumentException("negative size: " + size);
+ } else { // index > size
+ return format("%s (%s) must not be greater than size (%s)",
+ desc, index, size);
+ }
+ }
+
+ /**
+ * Ensures that {@code start} and {@code end} specify a valid <i>positions</i>
+ * in an array, list or string of size {@code size}, and are in order. A
+ * position index may range from zero to {@code size}, inclusive.
+ *
+ * @param start a user-supplied index identifying a starting position in an
+ * array, list or string
+ * @param end a user-supplied index identifying a ending position in an array,
+ * list or string
+ * @param size the size of that array, list or string
+ * @throws IndexOutOfBoundsException if either index is negative or is
+ * greater than {@code size}, or if {@code end} is less than {@code start}
+ * @throws IllegalArgumentException if {@code size} is negative
+ */
+ public static void checkPositionIndexes(int start, int end, int size) {
+ // Carefully optimized for execution by hotspot (explanatory comment above)
+ if (start < 0 || end < start || end > size) {
+ throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
+ }
+ }
+
+ private static String badPositionIndexes(int start, int end, int size) {
+ if (start < 0 || start > size) {
+ return badPositionIndex(start, size, "start index");
+ }
+ if (end < 0 || end > size) {
+ return badPositionIndex(end, size, "end index");
+ }
+ // end < start
+ return format("end index (%s) must not be less than start index (%s)",
+ end, start);
+ }
+
+ /**
+ * Substitutes each {@code %s} in {@code template} with an argument. These
+ * are matched by position - the first {@code %s} gets {@code args[0]}, etc.
+ * If there are more arguments than placeholders, the unmatched arguments will
+ * be appended to the end of the formatted message in square braces.
+ *
+ * @param template a non-null string containing 0 or more {@code %s}
+ * placeholders.
+ * @param args the arguments to be substituted into the message
+ * template. Arguments are converted to strings using
+ * {@link String#valueOf(Object)}. Arguments can be null.
+ */
+ static String format(String template,
+ Object... args) {
+ template = String.valueOf(template); // null -> "null"
+
+ // start substituting the arguments into the '%s' placeholders
+ StringBuilder builder = new StringBuilder(
+ template.length() + 16 * args.length);
+ int templateStart = 0;
+ int i = 0;
+ while (i < args.length) {
+ int placeholderStart = template.indexOf("%s", templateStart);
+ if (placeholderStart == -1) {
+ break;
+ }
+ builder.append(template.substring(templateStart, placeholderStart));
+ builder.append(args[i++]);
+ templateStart = placeholderStart + 2;
+ }
+ builder.append(template.substring(templateStart));
+
+ // if we run out of placeholders, append the extra args in square braces
+ if (i < args.length) {
+ builder.append(" [");
+ builder.append(args[i++]);
+ while (i < args.length) {
+ builder.append(", ");
+ builder.append(args[i++]);
+ }
+ builder.append(']');
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java b/src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java
new file mode 100644
index 00000000..630570ff
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.whispersystems.libaxolotl.util.guava;
+
+import static org.whispersystems.libaxolotl.util.guava.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Implementation of an {@link Optional} containing a reference.
+ */
+
+final class Present<T> extends Optional<T> {
+ private final T reference;
+
+ Present(T reference) {
+ this.reference = reference;
+ }
+
+ @Override public boolean isPresent() {
+ return true;
+ }
+
+ @Override public T get() {
+ return reference;
+ }
+
+ @Override public T or(T defaultValue) {
+ checkNotNull(defaultValue, "use orNull() instead of or(null)");
+ return reference;
+ }
+
+ @Override public Optional<T> or(Optional<? extends T> secondChoice) {
+ checkNotNull(secondChoice);
+ return this;
+ }
+
+ @Override public T or(Supplier<? extends T> supplier) {
+ checkNotNull(supplier);
+ return reference;
+ }
+
+ @Override public T orNull() {
+ return reference;
+ }
+
+ @Override public Set<T> asSet() {
+ return Collections.singleton(reference);
+ }
+
+ @Override public <V> Optional<V> transform(Function<? super T, V> function) {
+ return new Present<V>(checkNotNull(function.apply(reference),
+ "Transformation function cannot return null."));
+ }
+
+ @Override public boolean equals(Object object) {
+ if (object instanceof Present) {
+ Present<?> other = (Present<?>) object;
+ return reference.equals(other.reference);
+ }
+ return false;
+ }
+
+ @Override public int hashCode() {
+ return 0x598df91c + reference.hashCode();
+ }
+
+ @Override public String toString() {
+ return "Optional.of(" + reference + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java b/src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java
new file mode 100644
index 00000000..ba880707
--- /dev/null
+++ b/src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.whispersystems.libaxolotl.util.guava;
+
+
+/**
+ * A class that can supply objects of a single type. Semantically, this could
+ * be a factory, generator, builder, closure, or something else entirely. No
+ * guarantees are implied by this interface.
+ *
+ * @author Harry Heymann
+ * @since 2.0 (imported from Google Collections Library)
+ */
+public interface Supplier<T> {
+ /**
+ * Retrieves an instance of the appropriate type. The returned object may or
+ * may not be a new instance, depending on the implementation.
+ *
+ * @return an instance of the appropriate type
+ */
+ T get();
+}