aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org/whispersystems/libaxolotl/groups
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/whispersystems/libaxolotl/groups')
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java146
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java38
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java49
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java38
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java64
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java144
-rw-r--r--src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java6
7 files changed, 0 insertions, 485 deletions
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java b/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java
deleted file mode 100644
index 43dac752..00000000
--- a/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java
+++ /dev/null
@@ -1,146 +0,0 @@
-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
deleted file mode 100644
index 8b73484b..00000000
--- a/src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java
+++ /dev/null
@@ -1,38 +0,0 @@
-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
deleted file mode 100644
index 71375923..00000000
--- a/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java
+++ /dev/null
@@ -1,49 +0,0 @@
-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
deleted file mode 100644
index 8808a8e8..00000000
--- a/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java
+++ /dev/null
@@ -1,38 +0,0 @@
-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
deleted file mode 100644
index bb1ba952..00000000
--- a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java
+++ /dev/null
@@ -1,64 +0,0 @@
-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
deleted file mode 100644
index 80498ce0..00000000
--- a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java
+++ /dev/null
@@ -1,144 +0,0 @@
-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
deleted file mode 100644
index da01b1f3..00000000
--- a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.whispersystems.libaxolotl.groups.state;
-
-public interface SenderKeyStore {
- public void storeSenderKey(String senderKeyId, SenderKeyRecord record);
- public SenderKeyRecord loadSenderKey(String senderKeyId);
-}