Make sure senderkeys encrypt is correctly initialized.

This commit is contained in:
Moxie Marlinspike 2014-09-30 11:58:56 -07:00
parent 9a0ed659f7
commit 5fcc135f81
6 changed files with 43 additions and 26 deletions

View File

@ -6,6 +6,7 @@ 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;
@ -21,7 +22,7 @@ import java.util.List;
public class GroupCipherTest extends AndroidTestCase {
public void testBasicEncryptDecrypt()
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
{
InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
@ -49,7 +50,7 @@ public class GroupCipherTest extends AndroidTestCase {
}
public void testBasicRatchet()
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
{
InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
@ -92,7 +93,7 @@ public class GroupCipherTest extends AndroidTestCase {
}
public void testOutOfOrder()
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
{
InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
@ -129,6 +130,17 @@ public class GroupCipherTest extends AndroidTestCase {
}
}
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);

View File

@ -4,4 +4,8 @@ public class NoSessionException extends Exception {
public NoSessionException(String s) {
super(s);
}
public NoSessionException(Exception nested) {
super(nested);
}
}

View File

@ -1,18 +1,16 @@
package org.whispersystems.libaxolotl.groups;
import android.util.Log;
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.protocol.SenderKeyMessage;
import org.whispersystems.libaxolotl.groups.state.SenderKeyStore;
import org.whispersystems.libaxolotl.protocol.SenderKeyMessage;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
@ -36,23 +34,27 @@ public class GroupCipher {
this.senderKeyId = senderKeyId;
}
public byte[] encrypt(byte[] paddedPlaintext) {
public byte[] encrypt(byte[] paddedPlaintext) throws NoSessionException {
synchronized (LOCK) {
SenderKeyRecord record = senderKeyStore.loadSenderKey(senderKeyId);
SenderKeyState senderKeyState = record.getSenderKeyState();
SenderMessageKey senderKey = senderKeyState.getSenderChainKey().getSenderMessageKey();
byte[] ciphertext = getCipherText(senderKey.getIv(), senderKey.getCipherKey(), paddedPlaintext);
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());
SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyState.getKeyId(),
senderKey.getIteration(),
ciphertext,
senderKeyState.getSigningKeyPrivate());
senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext());
senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext());
senderKeyStore.storeSenderKey(senderKeyId, record);
senderKeyStore.storeSenderKey(senderKeyId, record);
return senderKeyMessage.serialize();
return senderKeyMessage.serialize();
} catch (InvalidKeyIdException e) {
throw new NoSessionException(e);
}
}
}

View File

@ -3,7 +3,6 @@ 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.groups.state.SenderKeyState;
import org.whispersystems.libaxolotl.state.StorageProtos;
import java.io.IOException;
@ -26,8 +25,12 @@ public class SenderKeyRecord {
}
}
public SenderKeyState getSenderKeyState() {
return senderKeyStates.get(0);
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 {

View File

@ -1,7 +1,5 @@
package org.whispersystems.libaxolotl.groups.state;
import android.util.Log;
import com.google.protobuf.ByteString;
import org.whispersystems.libaxolotl.InvalidKeyException;

View File

@ -1,7 +1,5 @@
package org.whispersystems.libaxolotl.groups.state;
import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord;
public interface SenderKeyStore {
public void storeSenderKey(String senderKeyId, SenderKeyRecord record);
public SenderKeyRecord loadSenderKey(String senderKeyId);