mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-27 02:13:18 +01:00
Initial multi device support refactoring.
1) Store account data as a json type, which includes all devices in a single object. 2) Simplify message delivery logic. 3) Make federated calls a pass through to standard controllers. 4) Simplify key retrieval logic.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package org.whispersystems.textsecuregcm.entities;
|
||||
|
||||
public class CryptoEncodingException extends Exception {
|
||||
|
||||
public CryptoEncodingException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public CryptoEncodingException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.whispersystems.textsecuregcm.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
public class DeviceResponse {
|
||||
|
||||
@JsonProperty
|
||||
private long deviceId;
|
||||
|
||||
@VisibleForTesting
|
||||
public DeviceResponse() {}
|
||||
|
||||
public DeviceResponse(long deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public long getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class EncryptedOutgoingMessage {
|
||||
this.signalingKey = signalingKey;
|
||||
}
|
||||
|
||||
public String serialize() throws IOException {
|
||||
public String serialize() throws CryptoEncodingException {
|
||||
byte[] plaintext = outgoingMessage.toByteArray();
|
||||
SecretKeySpec cipherKey = getCipherKey (signalingKey);
|
||||
SecretKeySpec macKey = getMacKey(signalingKey);
|
||||
@@ -61,7 +61,7 @@ public class EncryptedOutgoingMessage {
|
||||
}
|
||||
|
||||
private byte[] getCiphertext(byte[] plaintext, SecretKeySpec cipherKey, SecretKeySpec macKey)
|
||||
throws IOException
|
||||
throws CryptoEncodingException
|
||||
{
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
@@ -85,31 +85,39 @@ public class EncryptedOutgoingMessage {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException e) {
|
||||
logger.warn("Invalid Key", e);
|
||||
throw new IOException("Invalid key!");
|
||||
throw new CryptoEncodingException("Invalid key!");
|
||||
}
|
||||
}
|
||||
|
||||
private SecretKeySpec getCipherKey(String signalingKey) throws IOException {
|
||||
byte[] signalingKeyBytes = Base64.decode(signalingKey);
|
||||
byte[] cipherKey = new byte[CIPHER_KEY_SIZE];
|
||||
private SecretKeySpec getCipherKey(String signalingKey) throws CryptoEncodingException {
|
||||
try {
|
||||
byte[] signalingKeyBytes = Base64.decode(signalingKey);
|
||||
byte[] cipherKey = new byte[CIPHER_KEY_SIZE];
|
||||
|
||||
if (signalingKeyBytes.length < CIPHER_KEY_SIZE)
|
||||
throw new IOException("Signaling key too short!");
|
||||
if (signalingKeyBytes.length < CIPHER_KEY_SIZE)
|
||||
throw new CryptoEncodingException("Signaling key too short!");
|
||||
|
||||
System.arraycopy(signalingKeyBytes, 0, cipherKey, 0, cipherKey.length);
|
||||
return new SecretKeySpec(cipherKey, "AES");
|
||||
System.arraycopy(signalingKeyBytes, 0, cipherKey, 0, cipherKey.length);
|
||||
return new SecretKeySpec(cipherKey, "AES");
|
||||
} catch (IOException e) {
|
||||
throw new CryptoEncodingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private SecretKeySpec getMacKey(String signalingKey) throws IOException {
|
||||
byte[] signalingKeyBytes = Base64.decode(signalingKey);
|
||||
byte[] macKey = new byte[MAC_KEY_SIZE];
|
||||
private SecretKeySpec getMacKey(String signalingKey) throws CryptoEncodingException {
|
||||
try {
|
||||
byte[] signalingKeyBytes = Base64.decode(signalingKey);
|
||||
byte[] macKey = new byte[MAC_KEY_SIZE];
|
||||
|
||||
if (signalingKeyBytes.length < CIPHER_KEY_SIZE + MAC_KEY_SIZE)
|
||||
throw new IOException(("Signaling key too short!"));
|
||||
if (signalingKeyBytes.length < CIPHER_KEY_SIZE + MAC_KEY_SIZE)
|
||||
throw new CryptoEncodingException("Signaling key too short!");
|
||||
|
||||
System.arraycopy(signalingKeyBytes, CIPHER_KEY_SIZE, macKey, 0, macKey.length);
|
||||
System.arraycopy(signalingKeyBytes, CIPHER_KEY_SIZE, macKey, 0, macKey.length);
|
||||
|
||||
return new SecretKeySpec(macKey, "HmacSHA256");
|
||||
return new SecretKeySpec(macKey, "HmacSHA256");
|
||||
} catch (IOException e) {
|
||||
throw new CryptoEncodingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,9 +29,20 @@ public class IncomingMessageList {
|
||||
@Valid
|
||||
private List<IncomingMessage> messages;
|
||||
|
||||
@JsonProperty
|
||||
private String relay;
|
||||
|
||||
public IncomingMessageList() {}
|
||||
|
||||
public List<IncomingMessage> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public String getRelay() {
|
||||
return relay;
|
||||
}
|
||||
|
||||
public void setRelay(String relay) {
|
||||
this.relay = relay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.whispersystems.textsecuregcm.entities;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MissingDevices {
|
||||
|
||||
@JsonProperty
|
||||
public List<Long> missingDevices;
|
||||
|
||||
public MissingDevices(List<Long> missingDevices) {
|
||||
this.missingDevices = missingDevices;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,7 +35,6 @@ public class PreKey {
|
||||
private String number;
|
||||
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
private long deviceId;
|
||||
|
||||
@JsonProperty
|
||||
|
||||
@@ -23,14 +23,24 @@ import org.hibernate.validator.constraints.NotEmpty;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class UnstructuredPreKeyList {
|
||||
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
@Valid
|
||||
private List<PreKey> keys;
|
||||
|
||||
@VisibleForTesting
|
||||
public UnstructuredPreKeyList() {}
|
||||
|
||||
public UnstructuredPreKeyList(PreKey preKey) {
|
||||
this.keys = new LinkedList<PreKey>();
|
||||
this.keys.add(preKey);
|
||||
}
|
||||
|
||||
public UnstructuredPreKeyList(List<PreKey> preKeys) {
|
||||
this.keys = preKeys;
|
||||
}
|
||||
@@ -39,7 +49,8 @@ public class UnstructuredPreKeyList {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@VisibleForTesting public boolean equals(Object o) {
|
||||
@VisibleForTesting
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof UnstructuredPreKeyList) ||
|
||||
((UnstructuredPreKeyList) o).keys.size() != keys.size())
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user