From 327ee4ff62209fb840706618431e6691f52d926d Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Wed, 27 Nov 2013 17:50:38 -0800 Subject: [PATCH] Remove unnecessary classes, up prekey limit to 100 --- library/protobuf/LocalStorageProtocol.proto | 6 + .../textsecure/crypto/PreKeyPair.java | 59 --- .../textsecure/crypto/PreKeyPublic.java | 49 -- .../textsecure/crypto/PreKeyUtil.java | 7 +- .../textsecure/crypto/PublicKey.java | 5 - .../textsecure/push/PreKeyEntity.java | 26 +- .../textsecure/push/PreKeyList.java | 4 + .../textsecure/storage/PreKeyRecord.java | 71 +-- .../textsecure/storage/StorageProtos.java | 477 +++++++++++++++++- .../securesms/RoutingActivity.java | 2 +- .../crypto/KeyExchangeProcessorV2.java | 4 +- 11 files changed, 546 insertions(+), 164 deletions(-) delete mode 100644 library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java delete mode 100644 library/src/org/whispersystems/textsecure/crypto/PreKeyPublic.java diff --git a/library/protobuf/LocalStorageProtocol.proto b/library/protobuf/LocalStorageProtocol.proto index 22378423d8..ff8f8c0b2b 100644 --- a/library/protobuf/LocalStorageProtocol.proto +++ b/library/protobuf/LocalStorageProtocol.proto @@ -51,4 +51,10 @@ message SessionStructure { optional PendingKeyExchange pendingKeyExchange = 8; optional PendingPreKey pendingPreKey = 9; +} + +message PreKeyRecordStructure { + optional uint32 id = 1; + optional bytes publicKey = 2; + optional bytes privateKey = 3; } \ No newline at end of file diff --git a/library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java b/library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java deleted file mode 100644 index e4429b584d..0000000000 --- a/library/src/org/whispersystems/textsecure/crypto/PreKeyPair.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (C) 2013 Open 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 . - */ - -package org.whispersystems.textsecure.crypto; - -import org.whispersystems.textsecure.crypto.ecc.ECKeyPair; -import org.whispersystems.textsecure.crypto.ecc.ECPrivateKey; -import org.whispersystems.textsecure.util.Util; - -public class PreKeyPair { - - private final MasterCipher masterCipher; - private final PreKeyPublic publicKey; - private final ECPrivateKey privateKey; - - public PreKeyPair(MasterSecret masterSecret, ECKeyPair keyPair) { - this.masterCipher = new MasterCipher(masterSecret); - this.publicKey = new PreKeyPublic(keyPair.getPublicKey()); - this.privateKey = keyPair.getPrivateKey(); - } - - public PreKeyPair(MasterSecret masterSecret, byte[] serialized) throws InvalidKeyException { - byte[] privateKeyBytes = new byte[serialized.length - PreKeyPublic.KEY_SIZE]; - System.arraycopy(serialized, PreKeyPublic.KEY_SIZE, privateKeyBytes, 0, privateKeyBytes.length); - - this.masterCipher = new MasterCipher(masterSecret); - this.publicKey = new PreKeyPublic(serialized, 0); - this.privateKey = masterCipher.decryptKey(this.publicKey.getType(), privateKeyBytes); - } - - public PreKeyPublic getPublicKey() { - return publicKey; - } - - public ECKeyPair getKeyPair() { - return new ECKeyPair(publicKey.getPublicKey(), privateKey); - } - - public byte[] serialize() { - 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 deleted file mode 100644 index 8b889b317d..0000000000 --- a/library/src/org/whispersystems/textsecure/crypto/PreKeyPublic.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (C) 2013 Open 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 . - */ - -package org.whispersystems.textsecure.crypto; - -import org.whispersystems.textsecure.crypto.ecc.Curve; -import org.whispersystems.textsecure.crypto.ecc.ECPublicKey; -import org.whispersystems.textsecure.util.Util; - -public class PreKeyPublic { - - public static final int KEY_SIZE = ECPublicKey.KEY_SIZE; - - private final ECPublicKey publicKey; - - public PreKeyPublic(ECPublicKey publicKey) { - this.publicKey = publicKey; - } - - public PreKeyPublic(byte[] serialized, int offset) throws InvalidKeyException { - this.publicKey = Curve.decodePoint(serialized, offset); - } - - public byte[] serialize() { - return publicKey.serialize(); - } - - public ECPublicKey getPublicKey() { - return publicKey; - } - - public int getType() { - return this.publicKey.getType(); - } -} diff --git a/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java b/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java index 9c97a155db..b0f9abc53c 100644 --- a/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java +++ b/library/src/org/whispersystems/textsecure/crypto/PreKeyUtil.java @@ -23,6 +23,7 @@ import android.util.Log; import com.google.thoughtcrimegson.Gson; import org.whispersystems.textsecure.crypto.ecc.Curve25519; +import org.whispersystems.textsecure.crypto.ecc.ECKeyPair; import org.whispersystems.textsecure.storage.InvalidKeyIdException; import org.whispersystems.textsecure.storage.PreKeyRecord; import org.whispersystems.textsecure.util.Medium; @@ -40,7 +41,7 @@ import java.util.List; public class PreKeyUtil { - public static final int BATCH_SIZE = 20; + public static final int BATCH_SIZE = 100; public static List generatePreKeys(Context context, MasterSecret masterSecret) { List records = new LinkedList(); @@ -48,7 +49,7 @@ public class PreKeyUtil { for (int i=0;i, JsonDeserializer + private static class ECPublicKeyJsonAdapter + implements JsonSerializer, JsonDeserializer { @Override - public JsonElement serialize(PreKeyPublic preKeyPublic, Type type, + public JsonElement serialize(ECPublicKey preKeyPublic, Type type, JsonSerializationContext jsonSerializationContext) { return new JsonPrimitive(Base64.encodeBytesWithoutPadding(preKeyPublic.serialize())); } @Override - public PreKeyPublic deserialize(JsonElement jsonElement, Type type, + public ECPublicKey deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { try { - return new PreKeyPublic(Base64.decodeWithoutPadding(jsonElement.getAsJsonPrimitive().getAsString()), 0); + return Curve.decodePoint(Base64.decodeWithoutPadding(jsonElement.getAsJsonPrimitive().getAsString()), 0); } catch (InvalidKeyException e) { throw new JsonParseException(e); } catch (IOException e) { diff --git a/library/src/org/whispersystems/textsecure/push/PreKeyList.java b/library/src/org/whispersystems/textsecure/push/PreKeyList.java index b47c32babb..6571fc4118 100644 --- a/library/src/org/whispersystems/textsecure/push/PreKeyList.java +++ b/library/src/org/whispersystems/textsecure/push/PreKeyList.java @@ -20,6 +20,10 @@ public class PreKeyList { return PreKeyEntity.getBuilder().create().toJson(entity); } + public static PreKeyList fromJson(String serialized) { + return PreKeyEntity.getBuilder().create().fromJson(serialized, PreKeyList.class); + } + public PreKeyEntity getLastResortKey() { return lastResortKey; } diff --git a/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java b/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java index dd67468eee..d5796c054d 100644 --- a/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java +++ b/library/src/org/whispersystems/textsecure/storage/PreKeyRecord.java @@ -3,9 +3,16 @@ package org.whispersystems.textsecure.storage; import android.content.Context; import android.util.Log; +import com.google.protobuf.ByteString; + import org.whispersystems.textsecure.crypto.InvalidKeyException; +import org.whispersystems.textsecure.crypto.InvalidMessageException; +import org.whispersystems.textsecure.crypto.MasterCipher; import org.whispersystems.textsecure.crypto.MasterSecret; -import org.whispersystems.textsecure.crypto.PreKeyPair; +import org.whispersystems.textsecure.crypto.ecc.Curve; +import org.whispersystems.textsecure.crypto.ecc.ECKeyPair; +import org.whispersystems.textsecure.crypto.ecc.ECPrivateKey; +import org.whispersystems.textsecure.crypto.ecc.ECPublicKey; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -19,36 +26,46 @@ public class PreKeyRecord extends Record { private static final int CURRENT_VERSION_MARKER = 1; private final MasterSecret masterSecret; - - private PreKeyPair keyPair; - private int id; + private StorageProtos.PreKeyRecordStructure structure; public PreKeyRecord(Context context, MasterSecret masterSecret, int id) throws InvalidKeyIdException { super(context, PREKEY_DIRECTORY, id+""); - this.id = id; + this.structure = StorageProtos.PreKeyRecordStructure.newBuilder().setId(id).build(); this.masterSecret = masterSecret; loadData(); } public PreKeyRecord(Context context, MasterSecret masterSecret, - int id, PreKeyPair keyPair) + int id, ECKeyPair keyPair) { super(context, PREKEY_DIRECTORY, id+""); - this.id = id; - this.keyPair = keyPair; this.masterSecret = masterSecret; + this.structure = StorageProtos.PreKeyRecordStructure.newBuilder() + .setId(id) + .setPublicKey(ByteString.copyFrom(keyPair.getPublicKey() + .serialize())) + .setPrivateKey(ByteString.copyFrom(keyPair.getPrivateKey() + .serialize())) + .build(); } public int getId() { - return id; + return this.structure.getId(); } - public PreKeyPair getKeyPair() { - return keyPair; + public ECKeyPair getKeyPair() { + try { + ECPublicKey publicKey = Curve.decodePoint(this.structure.getPublicKey().toByteArray(), 0); + ECPrivateKey privateKey = Curve.decodePrivatePoint(publicKey.getType(), this.structure.getPrivateKey().toByteArray()); + + return new ECKeyPair(publicKey, privateKey); + } catch (InvalidKeyException e) { + throw new AssertionError(e); + } } public static boolean hasRecord(Context context, long id) { @@ -67,8 +84,10 @@ public class PreKeyRecord extends Record { FileChannel out = file.getChannel(); out.position(0); + MasterCipher masterCipher = new MasterCipher(masterSecret); + writeInteger(CURRENT_VERSION_MARKER, out); - writeKeyPair(keyPair, out); + writeBlob(masterCipher.encryptBytes(structure.toByteArray()), out); out.force(true); out.truncate(out.position()); @@ -83,15 +102,18 @@ public class PreKeyRecord extends Record { private void loadData() throws InvalidKeyIdException { synchronized (FILE_LOCK) { try { - FileInputStream in = this.openInputStream(); - int recordVersion = readInteger(in); + MasterCipher masterCipher = new MasterCipher(masterSecret); + FileInputStream in = this.openInputStream(); + int recordVersion = readInteger(in); if (recordVersion != CURRENT_VERSION_MARKER) { Log.w("PreKeyRecord", "Invalid version: " + recordVersion); return; } - keyPair = readKeyPair(in); + this.structure = + StorageProtos.PreKeyRecordStructure.parseFrom(masterCipher.decryptBytes(readBlob(in))); + in.close(); } catch (FileNotFoundException e) { Log.w("PreKeyRecord", e); @@ -99,23 +121,10 @@ public class PreKeyRecord extends Record { } catch (IOException ioe) { Log.w("PreKeyRecord", ioe); throw new InvalidKeyIdException(ioe); - } catch (InvalidKeyException ike) { - Log.w("LocalKeyRecord", ike); - throw new InvalidKeyIdException(ike); + } catch (InvalidMessageException ime) { + Log.w("PreKeyRecord", ime); + throw new InvalidKeyIdException(ime); } } } - - private void writeKeyPair(PreKeyPair keyPair, FileChannel out) throws IOException { - byte[] serialized = keyPair.serialize(); - writeBlob(serialized, out); - } - - private PreKeyPair readKeyPair(FileInputStream in) - throws IOException, InvalidKeyException - { - byte[] keyPairBytes = readBlob(in); - return new PreKeyPair(masterSecret, keyPairBytes); - } - } diff --git a/library/src/org/whispersystems/textsecure/storage/StorageProtos.java b/library/src/org/whispersystems/textsecure/storage/StorageProtos.java index 7f51de31f8..0afdf31eb3 100644 --- a/library/src/org/whispersystems/textsecure/storage/StorageProtos.java +++ b/library/src/org/whispersystems/textsecure/storage/StorageProtos.java @@ -4054,6 +4054,464 @@ public final class StorageProtos { // @@protoc_insertion_point(class_scope:textsecure.SessionStructure) } + public interface PreKeyRecordStructureOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // optional uint32 id = 1; + boolean hasId(); + int getId(); + + // optional bytes publicKey = 2; + boolean hasPublicKey(); + com.google.protobuf.ByteString getPublicKey(); + + // optional bytes privateKey = 3; + boolean hasPrivateKey(); + com.google.protobuf.ByteString getPrivateKey(); + } + public static final class PreKeyRecordStructure extends + com.google.protobuf.GeneratedMessage + implements PreKeyRecordStructureOrBuilder { + // Use PreKeyRecordStructure.newBuilder() to construct. + private PreKeyRecordStructure(Builder builder) { + super(builder); + } + private PreKeyRecordStructure(boolean noInit) {} + + private static final PreKeyRecordStructure defaultInstance; + public static PreKeyRecordStructure getDefaultInstance() { + return defaultInstance; + } + + public PreKeyRecordStructure getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.whispersystems.textsecure.storage.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.whispersystems.textsecure.storage.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable; + } + + private int bitField0_; + // optional uint32 id = 1; + public static final int ID_FIELD_NUMBER = 1; + private int id_; + public boolean hasId() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public int getId() { + return id_; + } + + // optional bytes publicKey = 2; + public static final int PUBLICKEY_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 privateKey = 3; + public static final int PRIVATEKEY_FIELD_NUMBER = 3; + private com.google.protobuf.ByteString privateKey_; + public boolean hasPrivateKey() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public com.google.protobuf.ByteString getPrivateKey() { + return privateKey_; + } + + private void initFields() { + id_ = 0; + publicKey_ = com.google.protobuf.ByteString.EMPTY; + privateKey_ = 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.writeUInt32(1, id_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, publicKey_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBytes(3, privateKey_); + } + 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 + .computeUInt32Size(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, privateKey_); + } + 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.storage.StorageProtos.PreKeyRecordStructure parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure 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.storage.StorageProtos.PreKeyRecordStructure parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure 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.storage.StorageProtos.PreKeyRecordStructure 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.storage.StorageProtos.PreKeyRecordStructure 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.storage.StorageProtos.PreKeyRecordStructure parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure 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.storage.StorageProtos.PreKeyRecordStructure 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.storage.StorageProtos.PreKeyRecordStructureOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.whispersystems.textsecure.storage.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.whispersystems.textsecure.storage.StorageProtos.internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable; + } + + // Construct using org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure.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_ = 0; + bitField0_ = (bitField0_ & ~0x00000001); + publicKey_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000002); + privateKey_ = 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.storage.StorageProtos.PreKeyRecordStructure.getDescriptor(); + } + + public org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure getDefaultInstanceForType() { + return org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure.getDefaultInstance(); + } + + public org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure build() { + org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + private org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return result; + } + + public org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure buildPartial() { + org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure result = new org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure(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.privateKey_ = privateKey_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure) { + return mergeFrom((org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure other) { + if (other == org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure.getDefaultInstance()) return this; + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasPublicKey()) { + setPublicKey(other.getPublicKey()); + } + if (other.hasPrivateKey()) { + setPrivateKey(other.getPrivateKey()); + } + 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.readUInt32(); + break; + } + case 18: { + bitField0_ |= 0x00000002; + publicKey_ = input.readBytes(); + break; + } + case 26: { + bitField0_ |= 0x00000004; + privateKey_ = input.readBytes(); + break; + } + } + } + } + + private int bitField0_; + + // optional uint32 id = 1; + private int id_ ; + public boolean hasId() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + public int getId() { + return id_; + } + public Builder setId(int value) { + bitField0_ |= 0x00000001; + id_ = value; + onChanged(); + return this; + } + public Builder clearId() { + bitField0_ = (bitField0_ & ~0x00000001); + id_ = 0; + onChanged(); + return this; + } + + // optional bytes publicKey = 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 privateKey = 3; + private com.google.protobuf.ByteString privateKey_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasPrivateKey() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + public com.google.protobuf.ByteString getPrivateKey() { + return privateKey_; + } + public Builder setPrivateKey(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + privateKey_ = value; + onChanged(); + return this; + } + public Builder clearPrivateKey() { + bitField0_ = (bitField0_ & ~0x00000004); + privateKey_ = getDefaultInstance().getPrivateKey(); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:textsecure.PreKeyRecordStructure) + } + + static { + defaultInstance = new PreKeyRecordStructure(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:textsecure.PreKeyRecordStructure) + } + private static com.google.protobuf.Descriptors.Descriptor internal_static_textsecure_SessionStructure_descriptor; private static @@ -4084,6 +4542,11 @@ public final class StorageProtos { private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_textsecure_SessionStructure_PendingPreKey_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_textsecure_PreKeyRecordStructure_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { @@ -4118,8 +4581,10 @@ public final class StorageProtos { "emeralKeyPrivate\030\005 \001(\014\022\030\n\020localIdentityK" + "ey\030\007 \001(\014\022\037\n\027localIdentityKeyPrivate\030\010 \001(" + "\014\0322\n\rPendingPreKey\022\020\n\010preKeyId\030\001 \001(\r\022\017\n\007" + - "baseKey\030\002 \001(\014B6\n%org.whispersystems.text" + - "secure.storageB\rStorageProtos" + "baseKey\030\002 \001(\014\"J\n\025PreKeyRecordStructure\022\n" + + "\n\002id\030\001 \001(\r\022\021\n\tpublicKey\030\002 \001(\014\022\022\n\nprivate" + + "Key\030\003 \001(\014B6\n%org.whispersystems.textsecu" + + "re.storageB\rStorageProtos" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -4174,6 +4639,14 @@ public final class StorageProtos { new java.lang.String[] { "PreKeyId", "BaseKey", }, org.whispersystems.textsecure.storage.StorageProtos.SessionStructure.PendingPreKey.class, org.whispersystems.textsecure.storage.StorageProtos.SessionStructure.PendingPreKey.Builder.class); + internal_static_textsecure_PreKeyRecordStructure_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_textsecure_PreKeyRecordStructure_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_textsecure_PreKeyRecordStructure_descriptor, + new java.lang.String[] { "Id", "PublicKey", "PrivateKey", }, + org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure.class, + org.whispersystems.textsecure.storage.StorageProtos.PreKeyRecordStructure.Builder.class); return null; } }; diff --git a/src/org/thoughtcrime/securesms/RoutingActivity.java b/src/org/thoughtcrime/securesms/RoutingActivity.java index 958a1dbe76..536ac9e981 100644 --- a/src/org/thoughtcrime/securesms/RoutingActivity.java +++ b/src/org/thoughtcrime/securesms/RoutingActivity.java @@ -3,7 +3,6 @@ package org.thoughtcrime.securesms; import android.content.Intent; import android.net.Uri; -import org.whispersystems.textsecure.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory; @@ -11,6 +10,7 @@ import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.service.ApplicationMigrationService; import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.whispersystems.textsecure.crypto.MasterSecret; public class RoutingActivity extends PassphraseRequiredSherlockActivity { diff --git a/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessorV2.java b/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessorV2.java index 8d4326699e..b0190e4df8 100644 --- a/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessorV2.java +++ b/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessorV2.java @@ -89,7 +89,7 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor { throw new InvalidKeyIdException("No such prekey: " + preKeyId); PreKeyRecord preKeyRecord = new PreKeyRecord(context, masterSecret, preKeyId); - ECKeyPair ourBaseKey = preKeyRecord.getKeyPair().getKeyPair(); + ECKeyPair ourBaseKey = preKeyRecord.getKeyPair(); ECKeyPair ourEphemeralKey = ourBaseKey; IdentityKeyPair ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret, ourBaseKey.getPublicKey().getType()); @@ -113,7 +113,7 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor { { ECKeyPair ourBaseKey = Curve.generateKeyPairForSession(2); ECKeyPair ourEphemeralKey = Curve.generateKeyPairForSession(2); - ECPublicKey theirBaseKey = message.getPublicKey().getPublicKey(); + ECPublicKey theirBaseKey = message.getPublicKey(); ECPublicKey theirEphemeralKey = theirBaseKey; IdentityKey theirIdentityKey = message.getIdentityKey(); IdentityKeyPair ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret,