diff options
author | Moxie Marlinspike <moxie@thoughtcrime.org> | 2014-11-24 12:54:30 -0800 |
---|---|---|
committer | Moxie Marlinspike <moxie@thoughtcrime.org> | 2014-11-24 12:54:30 -0800 |
commit | 60800e155612bea797eed93c67046a23d26054cc (patch) | |
tree | d88368c1c26162e27e790195133ca2b526597afe /src |
Break out into separate repo.
Diffstat (limited to 'src')
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(); +} |