mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00: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:
parent
499de2d2bf
commit
edb89ee3e9
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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<String> {
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<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)
|
||||
}
|
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
|
||||
|
@ -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+"");
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user