diff --git a/library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java b/library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java index b150a940c4..0e24d904bc 100644 --- a/library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java +++ b/library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java @@ -7,13 +7,13 @@ import org.whispersystems.textsecure.util.Util; public class PreKeyPair { - private final MasterCipher masterCipher; + private final MasterCipher masterCipher; private final ECPrivateKeyParameters privateKey; - private final ECPublicKeyParameters publicKey; + private final PreKeyPublic publicKey; public PreKeyPair(MasterSecret masterSecret, AsymmetricCipherKeyPair keyPair) { this.masterCipher = new MasterCipher(masterSecret); - this.publicKey = (ECPublicKeyParameters)keyPair.getPublic(); + this.publicKey = new PreKeyPublic((ECPublicKeyParameters)keyPair.getPublic()); this.privateKey = (ECPrivateKeyParameters)keyPair.getPrivate(); } @@ -25,16 +25,16 @@ public class PreKeyPair { System.arraycopy(serialized, KeyUtil.POINT_SIZE, privateKeyBytes, 0, privateKeyBytes.length); this.masterCipher = new MasterCipher(masterSecret); - this.publicKey = KeyUtil.decodePoint(serialized, 0); + this.publicKey = new PreKeyPublic(serialized, 0); this.privateKey = masterCipher.decryptKey(privateKeyBytes); } - public ECPublicKeyParameters getPublicKey() { + public PreKeyPublic getPublicKey() { return publicKey; } public byte[] serialize() { - byte[] publicKeyBytes = KeyUtil.encodePoint(publicKey.getQ()); + byte[] publicKeyBytes = publicKey.serialize(); byte[] privateKeyBytes = masterCipher.encryptKey(privateKey); return Util.combine(publicKeyBytes, privateKeyBytes); diff --git a/library/src/org/whispersystems/textsecure/crypto/PreKeyPublic.java b/library/src/org/whispersystems/textsecure/crypto/PreKeyPublic.java new file mode 100644 index 0000000000..6053dbc9b0 --- /dev/null +++ b/library/src/org/whispersystems/textsecure/crypto/PreKeyPublic.java @@ -0,0 +1,21 @@ +package org.whispersystems.textsecure.crypto; + +import org.spongycastle.crypto.params.ECPublicKeyParameters; + +public class PreKeyPublic { + + private final ECPublicKeyParameters publicKey; + + public PreKeyPublic(ECPublicKeyParameters publicKey) { + this.publicKey = publicKey; + } + + public PreKeyPublic(byte[] serialized, int offset) throws InvalidKeyException { + this.publicKey = KeyUtil.decodePoint(serialized, offset); + } + + public byte[] serialize() { + return KeyUtil.encodePoint(publicKey.getQ()); + } + +} diff --git a/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java b/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java index 73904706a0..c13b468f88 100644 --- a/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java +++ b/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java @@ -13,6 +13,8 @@ import org.whispersystems.textsecure.util.Base64; import java.io.File; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.util.Arrays; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; @@ -41,6 +43,8 @@ public class PreKeyUtil { File directory = getPreKeysDirectory(context); String[] keyRecordIds = directory.list(); + Arrays.sort(keyRecordIds, new PreKeyRecordIdComparator()); + for (String keyRecordId : keyRecordIds) { try { records.add(new PreKeyRecord(context, masterSecret, Long.parseLong(keyRecordId))); @@ -94,4 +98,20 @@ public class PreKeyUtil { return directory; } + private static class PreKeyRecordIdComparator implements Comparator { + @Override + public int compare(String lhs, String rhs) { + try { + long lhsLong = Long.parseLong(lhs); + long rhsLong = Long.parseLong(rhs); + + if (lhsLong < rhsLong) return -1; + else if (lhsLong > rhsLong) return 1; + else return 0; + } catch (NumberFormatException e) { + return 0; + } + } + } + } diff --git a/library/src/org/whispersystems/textsecure/encoded/PreKeyProtos.java b/library/src/org/whispersystems/textsecure/encoded/PreKeyProtos.java deleted file mode 100644 index 14f9f5fab0..0000000000 --- a/library/src/org/whispersystems/textsecure/encoded/PreKeyProtos.java +++ /dev/null @@ -1,511 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: PreKeyEntity.proto - -package org.whispersystems.textsecure.encoded; - -public final class PreKeyProtos { - private PreKeyProtos() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - } - public interface PreKeyEntityOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional uint64 id = 1; - boolean hasId(); - long getId(); - - // optional bytes public_key = 2; - boolean hasPublicKey(); - com.google.protobuf.ByteString getPublicKey(); - - // optional bytes identity_key = 3; - boolean hasIdentityKey(); - com.google.protobuf.ByteString getIdentityKey(); - } - public static final class PreKeyEntity extends - com.google.protobuf.GeneratedMessage - implements PreKeyEntityOrBuilder { - // Use PreKeyEntity.newBuilder() to construct. - private PreKeyEntity(Builder builder) { - super(builder); - } - private PreKeyEntity(boolean noInit) {} - - private static final PreKeyEntity defaultInstance; - public static PreKeyEntity getDefaultInstance() { - return defaultInstance; - } - - public PreKeyEntity getDefaultInstanceForType() { - return defaultInstance; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.whispersystems.textsecure.encoded.PreKeyProtos.internal_static_textsecure_PreKeyEntity_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.whispersystems.textsecure.encoded.PreKeyProtos.internal_static_textsecure_PreKeyEntity_fieldAccessorTable; - } - - private int bitField0_; - // optional uint64 id = 1; - public static final int ID_FIELD_NUMBER = 1; - private long id_; - public boolean hasId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public long getId() { - return id_; - } - - // optional bytes public_key = 2; - public static final int PUBLIC_KEY_FIELD_NUMBER = 2; - private com.google.protobuf.ByteString publicKey_; - public boolean hasPublicKey() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.google.protobuf.ByteString getPublicKey() { - return publicKey_; - } - - // optional bytes identity_key = 3; - public static final int IDENTITY_KEY_FIELD_NUMBER = 3; - private com.google.protobuf.ByteString identityKey_; - public boolean hasIdentityKey() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public com.google.protobuf.ByteString getIdentityKey() { - return identityKey_; - } - - private void initFields() { - id_ = 0L; - publicKey_ = com.google.protobuf.ByteString.EMPTY; - identityKey_ = com.google.protobuf.ByteString.EMPTY; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeUInt64(1, id_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, publicKey_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeBytes(3, identityKey_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(1, id_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, publicKey_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, identityKey_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data).buildParsed(); - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return newBuilder().mergeFrom(data, extensionRegistry) - .buildParsed(); - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom(java.io.InputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Builder builder = newBuilder(); - if (builder.mergeDelimitedFrom(input, extensionRegistry)) { - return builder.buildParsed(); - } else { - return null; - } - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return newBuilder().mergeFrom(input).buildParsed(); - } - public static org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return newBuilder().mergeFrom(input, extensionRegistry) - .buildParsed(); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntityOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.whispersystems.textsecure.encoded.PreKeyProtos.internal_static_textsecure_PreKeyEntity_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.whispersystems.textsecure.encoded.PreKeyProtos.internal_static_textsecure_PreKeyEntity_fieldAccessorTable; - } - - // Construct using org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder(BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - id_ = 0L; - bitField0_ = (bitField0_ & ~0x00000001); - publicKey_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000002); - identityKey_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000004); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity.getDescriptor(); - } - - public org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity getDefaultInstanceForType() { - return org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity.getDefaultInstance(); - } - - public org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity build() { - org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - private org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity buildParsed() - throws com.google.protobuf.InvalidProtocolBufferException { - org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException( - result).asInvalidProtocolBufferException(); - } - return result; - } - - public org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity buildPartial() { - org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity result = new org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.id_ = id_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.publicKey_ = publicKey_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.identityKey_ = identityKey_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity) { - return mergeFrom((org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity other) { - if (other == org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity.getDefaultInstance()) return this; - if (other.hasId()) { - setId(other.getId()); - } - if (other.hasPublicKey()) { - setPublicKey(other.getPublicKey()); - } - if (other.hasIdentityKey()) { - setIdentityKey(other.getIdentityKey()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder( - this.getUnknownFields()); - while (true) { - int tag = input.readTag(); - switch (tag) { - case 0: - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - this.setUnknownFields(unknownFields.build()); - onChanged(); - return this; - } - break; - } - case 8: { - bitField0_ |= 0x00000001; - id_ = input.readUInt64(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - publicKey_ = input.readBytes(); - break; - } - case 26: { - bitField0_ |= 0x00000004; - identityKey_ = input.readBytes(); - break; - } - } - } - } - - private int bitField0_; - - // optional uint64 id = 1; - private long id_ ; - public boolean hasId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - public long getId() { - return id_; - } - public Builder setId(long value) { - bitField0_ |= 0x00000001; - id_ = value; - onChanged(); - return this; - } - public Builder clearId() { - bitField0_ = (bitField0_ & ~0x00000001); - id_ = 0L; - onChanged(); - return this; - } - - // optional bytes public_key = 2; - private com.google.protobuf.ByteString publicKey_ = com.google.protobuf.ByteString.EMPTY; - public boolean hasPublicKey() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - public com.google.protobuf.ByteString getPublicKey() { - return publicKey_; - } - public Builder setPublicKey(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - publicKey_ = value; - onChanged(); - return this; - } - public Builder clearPublicKey() { - bitField0_ = (bitField0_ & ~0x00000002); - publicKey_ = getDefaultInstance().getPublicKey(); - onChanged(); - return this; - } - - // optional bytes identity_key = 3; - private com.google.protobuf.ByteString identityKey_ = com.google.protobuf.ByteString.EMPTY; - public boolean hasIdentityKey() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - public com.google.protobuf.ByteString getIdentityKey() { - return identityKey_; - } - public Builder setIdentityKey(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - identityKey_ = value; - onChanged(); - return this; - } - public Builder clearIdentityKey() { - bitField0_ = (bitField0_ & ~0x00000004); - identityKey_ = getDefaultInstance().getIdentityKey(); - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:textsecure.PreKeyEntity) - } - - static { - defaultInstance = new PreKeyEntity(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:textsecure.PreKeyEntity) - } - - private static com.google.protobuf.Descriptors.Descriptor - internal_static_textsecure_PreKeyEntity_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_textsecure_PreKeyEntity_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\022PreKeyEntity.proto\022\ntextsecure\"D\n\014PreK" + - "eyEntity\022\n\n\002id\030\001 \001(\004\022\022\n\npublic_key\030\002 \001(\014" + - "\022\024\n\014identity_key\030\003 \001(\014B5\n%org.whispersys" + - "tems.textsecure.encodedB\014PreKeyProtos" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - internal_static_textsecure_PreKeyEntity_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_textsecure_PreKeyEntity_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_textsecure_PreKeyEntity_descriptor, - new java.lang.String[] { "Id", "PublicKey", "IdentityKey", }, - org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity.class, - org.whispersystems.textsecure.encoded.PreKeyProtos.PreKeyEntity.Builder.class); - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/library/src/org/whispersystems/textsecure/push/PreKeyEntity.java b/library/src/org/whispersystems/textsecure/push/PreKeyEntity.java new file mode 100644 index 0000000000..a75c5e4aff --- /dev/null +++ b/library/src/org/whispersystems/textsecure/push/PreKeyEntity.java @@ -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, JsonDeserializer + { + @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, JsonDeserializer + { + @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); + } + } + } + +} diff --git a/library/src/org/whispersystems/textsecure/push/PreKeyList.java b/library/src/org/whispersystems/textsecure/push/PreKeyList.java index 5c1bac15b9..5be530b457 100644 --- a/library/src/org/whispersystems/textsecure/push/PreKeyList.java +++ b/library/src/org/whispersystems/textsecure/push/PreKeyList.java @@ -4,13 +4,17 @@ import java.util.List; public class PreKeyList { - private List keys; + private List keys; - public PreKeyList(List keys) { + public PreKeyList(List keys) { this.keys = keys; } - public List getKeys() { + public List getKeys() { return keys; } + + public static String toJson(PreKeyList entity) { + return PreKeyEntity.getBuilder().create().toJson(entity); + } } diff --git a/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java b/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java index bf8c08b3ca..16eb40d8d8 100644 --- a/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java +++ b/library/src/org/whispersystems/textsecure/push/PushServiceSocket.java @@ -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 records) throws IOException { - List encoded = new LinkedList(); + List entities = new LinkedList(); 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 sendAttachments(List attachments) throws IOException diff --git a/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java b/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java index ce2261cd22..f084c2dc59 100644 --- a/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java +++ b/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java @@ -4,7 +4,6 @@ import android.content.Context; import android.util.Log; import org.whispersystems.textsecure.crypto.InvalidKeyException; -import org.whispersystems.textsecure.crypto.KeyUtil; import org.whispersystems.textsecure.crypto.MasterSecret; import org.whispersystems.textsecure.crypto.PreKeyPair; @@ -52,10 +51,6 @@ public class PreKeyRecord extends Record { return keyPair; } - public byte[] getEncodedPublicKey() { - return KeyUtil.encodePoint(keyPair.getPublicKey().getQ()); - } - public static boolean hasRecord(Context context, long id) { Log.w("PreKeyRecord", "Checking: " + id); return Record.hasRecord(context, PREKEY_DIRECTORY, id+""); diff --git a/src/org/thoughtcrime/securesms/service/RegistrationService.java b/src/org/thoughtcrime/securesms/service/RegistrationService.java index 355d380216..25dd5752f2 100644 --- a/src/org/thoughtcrime/securesms/service/RegistrationService.java +++ b/src/org/thoughtcrime/securesms/service/RegistrationService.java @@ -14,16 +14,16 @@ import android.util.Pair; import com.google.android.gcm.GCMRegistrar; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; -import org.whispersystems.textsecure.crypto.IdentityKey; -import org.whispersystems.textsecure.crypto.MasterSecret; -import org.whispersystems.textsecure.crypto.PreKeyUtil; -import org.whispersystems.textsecure.storage.PreKeyRecord; import org.thoughtcrime.securesms.gcm.GcmIntentService; import org.thoughtcrime.securesms.gcm.GcmRegistrationTimeoutException; import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.whispersystems.textsecure.crypto.IdentityKey; +import org.whispersystems.textsecure.crypto.MasterSecret; +import org.whispersystems.textsecure.crypto.PreKeyUtil; import org.whispersystems.textsecure.directory.DirectoryDescriptor; import org.whispersystems.textsecure.directory.NumberFilter; import org.whispersystems.textsecure.push.PushServiceSocket; +import org.whispersystems.textsecure.storage.PreKeyRecord; import org.whispersystems.textsecure.util.Util; import java.io.File;