mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-29 13:16:01 +01:00
Move prekey jsonifcation into the push code, add identity key.
This commit is contained in:
@@ -65,22 +65,6 @@ public class PreKeyUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static PreKeyList toJson(List<PreKeyRecord> records) {
|
||||
List<String> encoded = new LinkedList<String>();
|
||||
|
||||
for (PreKeyRecord record : records) {
|
||||
PreKeyEntity entity = PreKeyEntity.newBuilder().setId(record.getId())
|
||||
.setKey(ByteString.copyFrom(KeyUtil.encodePoint(record.getKeyPair().getPublicKey().getQ())))
|
||||
.build();
|
||||
|
||||
String encodedEntity = Base64.encodeBytesWithoutPadding(entity.toByteArray());
|
||||
|
||||
encoded.add(encodedEntity);
|
||||
}
|
||||
|
||||
return new PreKeyList(encoded);
|
||||
}
|
||||
|
||||
private static long getNextPreKeyId(Context context) {
|
||||
try {
|
||||
File directory = getPreKeysDirectory(context);
|
||||
|
||||
@@ -22,7 +22,7 @@ import android.util.Log;
|
||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.whispersystems.textsecure.protocol.Message;
|
||||
import org.whispersystems.textsecure.crypto.protocol.Message;
|
||||
import org.whispersystems.textsecure.storage.CanonicalRecipientAddress;
|
||||
import org.whispersystems.textsecure.storage.InvalidKeyIdException;
|
||||
import org.whispersystems.textsecure.storage.LocalKeyRecord;
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Copyright (C) 2011 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.textsecure.crypto.protocol;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.whispersystems.textsecure.crypto.InvalidKeyException;
|
||||
import org.whispersystems.textsecure.crypto.InvalidMessageException;
|
||||
import org.whispersystems.textsecure.crypto.PublicKey;
|
||||
import org.whispersystems.textsecure.util.Conversions;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Parses and serializes the encrypted message format.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
|
||||
public class Message {
|
||||
|
||||
public static final int SUPPORTED_VERSION = 1;
|
||||
|
||||
private static final int VERSION_LENGTH = 1;
|
||||
private static final int SENDER_KEY_ID_LENGTH = 3;
|
||||
private static final int RECEIVER_KEY_ID_LENGTH = 3;
|
||||
private static final int NEXT_KEY_LENGTH = PublicKey.KEY_SIZE;
|
||||
private static final int COUNTER_LENGTH = 3;
|
||||
public static final int HEADER_LENGTH = VERSION_LENGTH + SENDER_KEY_ID_LENGTH + RECEIVER_KEY_ID_LENGTH + COUNTER_LENGTH + NEXT_KEY_LENGTH;
|
||||
|
||||
private static final int VERSION_OFFSET = 0;
|
||||
private static final int SENDER_KEY_ID_OFFSET = VERSION_OFFSET + VERSION_LENGTH;
|
||||
private static final int RECEIVER_KEY_ID_OFFSET = SENDER_KEY_ID_OFFSET + SENDER_KEY_ID_LENGTH;
|
||||
private static final int NEXT_KEY_OFFSET = RECEIVER_KEY_ID_OFFSET + RECEIVER_KEY_ID_LENGTH;
|
||||
private static final int COUNTER_OFFSET = NEXT_KEY_OFFSET + NEXT_KEY_LENGTH;
|
||||
private static final int TEXT_OFFSET = COUNTER_OFFSET + COUNTER_LENGTH;
|
||||
|
||||
private int senderKeyId;
|
||||
private int receiverKeyId;
|
||||
private int counter;
|
||||
private int messageVersion;
|
||||
private int supportedVersion;
|
||||
private byte[] message;
|
||||
|
||||
private PublicKey nextKey;
|
||||
|
||||
public Message(int senderKeyId, int receiverKeyId, PublicKey nextKey, int counter, byte[] message, int messageVersion, int supportedVersion) {
|
||||
this.senderKeyId = senderKeyId;
|
||||
this.receiverKeyId = receiverKeyId;
|
||||
this.nextKey = nextKey;
|
||||
this.counter = counter;
|
||||
this.message = message;
|
||||
this.messageVersion = messageVersion;
|
||||
this.supportedVersion = supportedVersion;
|
||||
}
|
||||
|
||||
public Message(byte[] messageBytes) throws InvalidMessageException {
|
||||
try {
|
||||
if (messageBytes.length <= HEADER_LENGTH)
|
||||
throw new InvalidMessageException("Message is shorter than headers.");
|
||||
|
||||
this.messageVersion = Conversions.highBitsToInt(messageBytes[VERSION_OFFSET]);
|
||||
this.supportedVersion = Conversions.lowBitsToInt(messageBytes[VERSION_OFFSET]);
|
||||
|
||||
Log.w("Message", "Message Version: " + messageVersion);
|
||||
Log.w("Message", "Supported Version: " + supportedVersion);
|
||||
|
||||
if (messageVersion > SUPPORTED_VERSION)
|
||||
throw new InvalidMessageException("Message protocol version not supported: " + messageVersion);
|
||||
|
||||
this.senderKeyId = Conversions.byteArrayToMedium(messageBytes, SENDER_KEY_ID_OFFSET);
|
||||
this.receiverKeyId = Conversions.byteArrayToMedium(messageBytes, RECEIVER_KEY_ID_OFFSET);
|
||||
this.counter = Conversions.byteArrayToMedium(messageBytes, COUNTER_OFFSET);
|
||||
|
||||
Log.w("Message", "Parsed current version: " + messageVersion + " supported version: " + supportedVersion);
|
||||
|
||||
byte[] nextKeyBytes = new byte[NEXT_KEY_LENGTH];
|
||||
byte[] textBytes = new byte[messageBytes.length - HEADER_LENGTH];
|
||||
|
||||
System.arraycopy(messageBytes, NEXT_KEY_OFFSET, nextKeyBytes, 0, nextKeyBytes.length);
|
||||
System.arraycopy(messageBytes, TEXT_OFFSET, textBytes, 0, textBytes.length);
|
||||
|
||||
Log.w("Message", "Pulling next key out of message...");
|
||||
this.nextKey = new PublicKey(nextKeyBytes);
|
||||
this.message = textBytes;
|
||||
} catch (InvalidKeyException ike) {
|
||||
throw new AssertionError(ike);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(HEADER_LENGTH + message.length);
|
||||
|
||||
Log.w("Message", "Constructing Message Version: (" + messageVersion + "," + supportedVersion + ")");
|
||||
|
||||
byte versionByte = Conversions.intsToByteHighAndLow(messageVersion, supportedVersion);
|
||||
byte[] senderKeyIdBytes = Conversions.mediumToByteArray(senderKeyId);
|
||||
byte[] receiverKeyIdBytes = Conversions.mediumToByteArray(receiverKeyId);
|
||||
Log.w("Message", "Serializing next key into message...");
|
||||
byte[] nextKeyBytes = nextKey.serialize();
|
||||
byte[] counterBytes = Conversions.mediumToByteArray(counter);
|
||||
|
||||
buffer.put(versionByte);
|
||||
buffer.put(senderKeyIdBytes);
|
||||
buffer.put(receiverKeyIdBytes);
|
||||
buffer.put(nextKeyBytes);
|
||||
buffer.put(counterBytes);
|
||||
buffer.put(message);
|
||||
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
public int getHighestMutuallySupportedVersion() {
|
||||
return Math.min(SUPPORTED_VERSION, this.supportedVersion);
|
||||
}
|
||||
|
||||
public int getSenderKeyId() {
|
||||
return this.senderKeyId;
|
||||
}
|
||||
|
||||
public int getReceiverKeyId() {
|
||||
return this.receiverKeyId;
|
||||
}
|
||||
|
||||
public PublicKey getNextKey() {
|
||||
return this.nextKey;
|
||||
}
|
||||
|
||||
public int getCounter() {
|
||||
return this.counter;
|
||||
}
|
||||
|
||||
public byte[] getMessageText() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user