mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-29 13:16:01 +01:00
Encode prekey as full JSON rather than protobuf blobs.
1) Split prekey messages out into full JSON. 2) Add support for retrieving prekeys.
This commit is contained in:
109
library/src/org/whispersystems/textsecure/push/PreKeyEntity.java
Normal file
109
library/src/org/whispersystems/textsecure/push/PreKeyEntity.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package org.whispersystems.textsecure.push;
|
||||
|
||||
import com.google.thoughtcrimegson.GsonBuilder;
|
||||
import com.google.thoughtcrimegson.JsonDeserializationContext;
|
||||
import com.google.thoughtcrimegson.JsonDeserializer;
|
||||
import com.google.thoughtcrimegson.JsonElement;
|
||||
import com.google.thoughtcrimegson.JsonParseException;
|
||||
import com.google.thoughtcrimegson.JsonPrimitive;
|
||||
import com.google.thoughtcrimegson.JsonSerializationContext;
|
||||
import com.google.thoughtcrimegson.JsonSerializer;
|
||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||
import org.whispersystems.textsecure.crypto.InvalidKeyException;
|
||||
import org.whispersystems.textsecure.crypto.PreKeyPublic;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class PreKeyEntity {
|
||||
|
||||
private long keyId;
|
||||
private PreKeyPublic publicKey;
|
||||
private IdentityKey identityKey;
|
||||
|
||||
public PreKeyEntity(long keyId, PreKeyPublic publicKey, IdentityKey identityKey) {
|
||||
this.keyId = keyId;
|
||||
this.publicKey = publicKey;
|
||||
this.identityKey = identityKey;
|
||||
}
|
||||
|
||||
public long getKeyId() {
|
||||
return keyId;
|
||||
}
|
||||
|
||||
public PreKeyPublic getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public IdentityKey getIdentityKey() {
|
||||
return identityKey;
|
||||
}
|
||||
|
||||
public static String toJson(PreKeyEntity entity) {
|
||||
return getBuilder().create().toJson(entity);
|
||||
}
|
||||
|
||||
public static PreKeyEntity fromJson(String encoded) {
|
||||
return getBuilder().create().fromJson(encoded, PreKeyEntity.class);
|
||||
}
|
||||
|
||||
public static GsonBuilder getBuilder() {
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.registerTypeAdapter(PreKeyPublic.class, new PreKeyPublicJsonAdapter());
|
||||
builder.registerTypeAdapter(IdentityKey.class, new IdentityKeyJsonAdapter());
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static class PreKeyPublicJsonAdapter
|
||||
implements JsonSerializer<PreKeyPublic>, JsonDeserializer<PreKeyPublic>
|
||||
{
|
||||
@Override
|
||||
public JsonElement serialize(PreKeyPublic preKeyPublic, Type type,
|
||||
JsonSerializationContext jsonSerializationContext)
|
||||
{
|
||||
return new JsonPrimitive(Base64.encodeBytesWithoutPadding(preKeyPublic.serialize()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreKeyPublic deserialize(JsonElement jsonElement, Type type,
|
||||
JsonDeserializationContext jsonDeserializationContext)
|
||||
throws JsonParseException
|
||||
{
|
||||
try {
|
||||
return new PreKeyPublic(Base64.decodeWithoutPadding(jsonElement.getAsJsonPrimitive().getAsString()), 0);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new JsonParseException(e);
|
||||
} catch (IOException e) {
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class IdentityKeyJsonAdapter
|
||||
implements JsonSerializer<IdentityKey>, JsonDeserializer<IdentityKey>
|
||||
{
|
||||
@Override
|
||||
public JsonElement serialize(IdentityKey identityKey, Type type,
|
||||
JsonSerializationContext jsonSerializationContext)
|
||||
{
|
||||
return new JsonPrimitive(Base64.encodeBytesWithoutPadding(identityKey.serialize()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityKey deserialize(JsonElement jsonElement, Type type,
|
||||
JsonDeserializationContext jsonDeserializationContext)
|
||||
throws JsonParseException
|
||||
{
|
||||
try {
|
||||
return new IdentityKey(Base64.decodeWithoutPadding(jsonElement.getAsJsonPrimitive().getAsString()), 0);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new JsonParseException(e);
|
||||
} catch (IOException e) {
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,13 +4,17 @@ import java.util.List;
|
||||
|
||||
public class PreKeyList {
|
||||
|
||||
private List<String> keys;
|
||||
private List<PreKeyEntity> keys;
|
||||
|
||||
public PreKeyList(List<String> keys) {
|
||||
public PreKeyList(List<PreKeyEntity> keys) {
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
public List<String> getKeys() {
|
||||
public List<PreKeyEntity> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static String toJson(PreKeyList entity) {
|
||||
return PreKeyEntity.getBuilder().create().toJson(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ import com.google.thoughtcrimegson.Gson;
|
||||
import org.whispersystems.textsecure.R;
|
||||
import org.whispersystems.textsecure.Release;
|
||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||
import org.whispersystems.textsecure.crypto.PreKeyPair;
|
||||
import org.whispersystems.textsecure.crypto.PreKeyPublic;
|
||||
import org.whispersystems.textsecure.directory.DirectoryDescriptor;
|
||||
import org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity;
|
||||
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
import org.whispersystems.textsecure.util.Util;
|
||||
@@ -41,7 +42,7 @@ public class PushServiceSocket {
|
||||
private static final String CREATE_ACCOUNT_VOICE_PATH = "/v1/accounts/voice/%s";
|
||||
private static final String VERIFY_ACCOUNT_PATH = "/v1/accounts/code/%s";
|
||||
private static final String REGISTER_GCM_PATH = "/v1/accounts/gcm/";
|
||||
private static final String PREKEY_PATH = "/v1/keys/";
|
||||
private static final String PREKEY_PATH = "/v1/keys/%s";
|
||||
|
||||
private static final String DIRECTORY_PATH = "/v1/directory/";
|
||||
private static final String MESSAGE_PATH = "/v1/messages/";
|
||||
@@ -111,22 +112,23 @@ public class PushServiceSocket {
|
||||
public void registerPreKeys(IdentityKey identityKey, List<PreKeyRecord> records)
|
||||
throws IOException
|
||||
{
|
||||
List<String> encoded = new LinkedList<String>();
|
||||
List<PreKeyEntity> entities = new LinkedList<PreKeyEntity>();
|
||||
|
||||
for (PreKeyRecord record : records) {
|
||||
PreKeyEntity entity = PreKeyEntity.newBuilder().setId(record.getId())
|
||||
.setPublicKey(ByteString.copyFrom(record.getEncodedPublicKey()))
|
||||
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
|
||||
.build();
|
||||
|
||||
String encodedEntity = Base64.encodeBytesWithoutPadding(entity.toByteArray());
|
||||
|
||||
encoded.add(encodedEntity);
|
||||
PreKeyEntity entity = new PreKeyEntity(record.getId(),
|
||||
record.getKeyPair().getPublicKey(),
|
||||
identityKey);
|
||||
entities.add(entity);
|
||||
}
|
||||
|
||||
makeRequest(PREKEY_PATH, "PUT", new Gson().toJson(new PreKeyList(encoded)));
|
||||
makeRequest(String.format(PREKEY_PATH, ""), "PUT", PreKeyList.toJson(new PreKeyList(entities)));
|
||||
}
|
||||
|
||||
public PreKeyEntity getPreKey(String number) throws IOException {
|
||||
String responseText = makeRequest(String.format(PREKEY_PATH, number), "GET", null);
|
||||
Log.w("PushServiceSocket", "Got prekey: " + responseText);
|
||||
return PreKeyEntity.fromJson(responseText);
|
||||
}
|
||||
|
||||
private List<PushAttachmentPointer> sendAttachments(List<PushAttachmentData> attachments)
|
||||
throws IOException
|
||||
|
||||
Reference in New Issue
Block a user