Add last resort key and signaling key.

This commit is contained in:
Moxie Marlinspike
2013-08-28 15:35:30 -07:00
parent 45e380a5bb
commit 68ec0a3727
10 changed files with 110 additions and 30 deletions

View File

@@ -40,6 +40,24 @@ public class PreKeyUtil {
return records;
}
public static PreKeyRecord generateLastResortKey(Context context, MasterSecret masterSecret) {
if (PreKeyRecord.hasRecord(context, Medium.MAX_VALUE)) {
try {
return new PreKeyRecord(context, masterSecret, Medium.MAX_VALUE);
} catch (InvalidKeyIdException e) {
Log.w("PreKeyUtil", e);
PreKeyRecord.delete(context, Medium.MAX_VALUE);
}
}
PreKeyPair keyPair = new PreKeyPair(masterSecret, KeyUtil.generateKeyPair());
PreKeyRecord record = new PreKeyRecord(context, masterSecret, Medium.MAX_VALUE, keyPair);
record.save();
return record;
}
public static List<PreKeyRecord> getPreKeys(Context context, MasterSecret masterSecret) {
List<PreKeyRecord> records = new LinkedList<PreKeyRecord>();
File directory = getPreKeysDirectory(context);
@@ -49,7 +67,9 @@ public class PreKeyUtil {
for (String keyRecordId : keyRecordIds) {
try {
records.add(new PreKeyRecord(context, masterSecret, Integer.parseInt(keyRecordId)));
if (Integer.parseInt(keyRecordId) != Medium.MAX_VALUE) {
records.add(new PreKeyRecord(context, masterSecret, Integer.parseInt(keyRecordId)));
}
} catch (InvalidKeyIdException e) {
Log.w("PreKeyUtil", e);
new File(getPreKeysDirectory(context), keyRecordId).delete();

View File

@@ -4,10 +4,12 @@ import java.util.List;
public class PreKeyList {
private PreKeyEntity lastResortKey;
private List<PreKeyEntity> keys;
public PreKeyList(List<PreKeyEntity> keys) {
this.keys = keys;
public PreKeyList(PreKeyEntity lastResortKey, List<PreKeyEntity> keys) {
this.keys = keys;
this.lastResortKey = lastResortKey;
}
public List<PreKeyEntity> getKeys() {
@@ -17,4 +19,8 @@ public class PreKeyList {
public static String toJson(PreKeyList entity) {
return PreKeyEntity.getBuilder().create().toJson(entity);
}
public PreKeyEntity getLastResortKey() {
return lastResortKey;
}
}

View File

@@ -65,8 +65,9 @@ public class PushServiceSocket {
makeRequest(String.format(path, localNumber), "POST", null);
}
public void verifyAccount(String verificationCode) throws IOException {
makeRequest(String.format(VERIFY_ACCOUNT_PATH, verificationCode), "PUT", null);
public void verifyAccount(String verificationCode, String signalingKey) throws IOException {
SignalingKey signalingKeyEntity = new SignalingKey(signalingKey);
makeRequest(String.format(VERIFY_ACCOUNT_PATH, verificationCode), "PUT", new Gson().toJson(signalingKeyEntity));
}
public void registerGcmId(String gcmRegistrationId) throws IOException {
@@ -109,7 +110,9 @@ public class PushServiceSocket {
throw new IOException("Got send failure: " + response.getFailure().get(0));
}
public void registerPreKeys(IdentityKey identityKey, List<PreKeyRecord> records)
public void registerPreKeys(IdentityKey identityKey,
PreKeyRecord lastResortKey,
List<PreKeyRecord> records)
throws IOException
{
List<PreKeyEntity> entities = new LinkedList<PreKeyEntity>();
@@ -121,7 +124,11 @@ public class PushServiceSocket {
entities.add(entity);
}
makeRequest(String.format(PREKEY_PATH, ""), "PUT", PreKeyList.toJson(new PreKeyList(entities)));
PreKeyEntity lastResortEntity = new PreKeyEntity(lastResortKey.getId(),
lastResortKey.getKeyPair().getPublicKey(),
identityKey);
makeRequest(String.format(PREKEY_PATH, ""), "PUT", PreKeyList.toJson(new PreKeyList(lastResortEntity, entities)));
}
public PreKeyEntity getPreKey(String number) throws IOException {

View File

@@ -0,0 +1,16 @@
package org.whispersystems.textsecure.push;
public class SignalingKey {
private String signalingKey;
public SignalingKey(String signalingKey) {
this.signalingKey = signalingKey;
}
public SignalingKey() {}
public String getSignalingKey() {
return signalingKey;
}
}

View File

@@ -24,6 +24,7 @@ import org.whispersystems.textsecure.crypto.KeyPair;
import org.whispersystems.textsecure.crypto.KeyUtil;
import org.whispersystems.textsecure.crypto.MasterCipher;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.util.Medium;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -65,7 +66,8 @@ public class LocalKeyRecord extends Record {
Log.w("LocalKeyRecord", "Remote client acknowledges receiving key id: " + keyId);
if (keyId == localNextKeyPair.getId()) {
this.localCurrentKeyPair = this.localNextKeyPair;
this.localNextKeyPair = new KeyPair(this.localNextKeyPair.getId()+1, KeyUtil.generateKeyPair(), masterSecret);
this.localNextKeyPair = new KeyPair((this.localNextKeyPair.getId()+1) % Medium.MAX_VALUE,
KeyUtil.generateKeyPair(), masterSecret);
}
}

View File

@@ -22,6 +22,7 @@ import android.util.Log;
import org.whispersystems.textsecure.crypto.InvalidKeyException;
import org.whispersystems.textsecure.crypto.PublicKey;
import org.whispersystems.textsecure.util.Hex;
import org.whispersystems.textsecure.util.Medium;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -62,7 +63,7 @@ public class RemoteKeyRecord extends Record {
public void updateCurrentRemoteKey(PublicKey remoteKey) {
Log.w("RemoteKeyRecord", "Updating current remote key: " + remoteKey.getId());
if (remoteKey.getId() > remoteKeyCurrent.getId()) {
if (isWrappingGreaterThan(remoteKey.getId(), remoteKeyCurrent.getId())) {
this.remoteKeyLast = this.remoteKeyCurrent;
this.remoteKeyCurrent = remoteKey;
}
@@ -112,6 +113,20 @@ public class RemoteKeyRecord extends Record {
}
}
private boolean isWrappingGreaterThan(int receivedValue, int currentValue) {
if (receivedValue > currentValue) {
return true;
}
if (receivedValue == currentValue) {
return false;
}
int gap = (receivedValue - currentValue) + Medium.MAX_VALUE;
return (gap >= 0) && (gap < 5);
}
private void loadData() {
Log.w("RemoteKeyRecord", "Loading remote key record for recipient: " + this.address);
synchronized (FILE_LOCK) {

View File

@@ -1,5 +1,5 @@
package org.whispersystems.textsecure.util;
public class Medium {
public static int MAX_VALUE = 0xFFF;
public static int MAX_VALUE = 0xFFFFFF;
}