From 5826648598eb4285cd6061bb74aac11d2fd6d558 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Sat, 13 Jul 2019 09:06:47 -0600 Subject: [PATCH] Losslessly encode protos --- .../src/SMKCertificateValidator.swift | 9 +- .../src/SMKSecretSessionCipher.swift | 12 +- .../src/SMKSenderCertificate.swift | 97 +++---- .../src/SMKServerCertificate.swift | 68 ++--- .../src/SMKUnidentifiedSenderMessage.swift | 69 +++-- .../SMKUnidentifiedSenderMessageContent.swift | 113 +++++--- SignalMetadataKitTests/src/SMKMiscTest.swift | 157 ++++++----- .../src/SMKSecretSessionCipherTest.swift | 99 ++++--- .../src/SMKSenderCertificateTest.swift | 256 ++++++++---------- .../src/SMKServerCertificateTest.swift | 164 +++++------ 10 files changed, 504 insertions(+), 540 deletions(-) diff --git a/SignalMetadataKit/src/SMKCertificateValidator.swift b/SignalMetadataKit/src/SMKCertificateValidator.swift index e79e5e1..5015c62 100644 --- a/SignalMetadataKit/src/SMKCertificateValidator.swift +++ b/SignalMetadataKit/src/SMKCertificateValidator.swift @@ -48,10 +48,9 @@ public enum SMKCertificateError: Error { // if (!Curve.verifySignature(serverCertificate.getKey(), certificate.getCertificate(), certificate.getSignature())) { // throw new InvalidCertificateException("Signature failed"); // } - let certificateData = try senderCertificate.toProto().certificate guard try Ed25519.verifySignature(senderCertificate.signatureData, publicKey: serverCertificate.key.keyData, - data: certificateData) else { + data: senderCertificate.certificateData) else { Logger.error("Sender certificate signature verification failed.") let error = SMKCertificateError.invalidCertificate(description: "Sender certificate signature verification failed.") Logger.error("\(error)") @@ -79,14 +78,10 @@ public enum SMKCertificateError: Error { // if (!Curve.verifySignature(trustRoot, certificate.getCertificate(), certificate.getSignature())) { // throw new InvalidCertificateException("Signature failed"); // } - let certificateBuilder = SMKProtoServerCertificateCertificate.builder(id: serverCertificate.keyId, - key: serverCertificate.key.serialized) - let certificateData = try certificateBuilder.build().serializedData() - // let certificateData = try serverCertificate.toProto().certificate guard try Ed25519.verifySignature(serverCertificate.signatureData, publicKey: trustRoot.keyData, - data: certificateData) else { + data: serverCertificate.certificateData) else { let error = SMKCertificateError.invalidCertificate(description: "Server certificate signature verification failed.") Logger.error("\(error)") throw error diff --git a/SignalMetadataKit/src/SMKSecretSessionCipher.swift b/SignalMetadataKit/src/SMKSecretSessionCipher.swift index 7362b7e..1b304f0 100644 --- a/SignalMetadataKit/src/SMKSecretSessionCipher.swift +++ b/SignalMetadataKit/src/SMKSecretSessionCipher.swift @@ -241,21 +241,21 @@ public class SMKDecryptResult: NSObject { default: throw SMKError.assertionError(description: "\(logTag) Unknown cipher message type.") } - let messageContent = SMKUnidentifiedSenderMessageContent(messageType: messageType, + let messageContent = try SMKUnidentifiedSenderMessageContent(messageType: messageType, senderCertificate: senderCertificate, contentData: encryptedMessageData) // byte[] messageBytes = encrypt(staticKeys.cipherKey, staticKeys.macKey, content.getSerialized()); let messageData = try encrypt(cipherKey: staticKeys.cipherKey, macKey: staticKeys.macKey, - plaintextData: try messageContent.serialized()) + plaintextData: messageContent.serializedData) // return new UnidentifiedSenderMessage(ephemeral.getPublicKey(), staticKeyCiphertext, // messageBytes).getSerialized(); - let message = SMKUnidentifiedSenderMessage(ephemeralKey: try ephemeral.ecPublicKey(), + let message = try SMKUnidentifiedSenderMessage(ephemeralKey: try ephemeral.ecPublicKey(), encryptedStatic: staticKeyCipherData, encryptedMessage: messageData) - return try message.serialized() + return message.serializedData } // public Pair decrypt(CertificateValidator validator, byte[] ciphertext, long @@ -282,7 +282,7 @@ public class SMKDecryptResult: NSObject { } // UnidentifiedSenderMessage wrapper = new UnidentifiedSenderMessage(ciphertext); - let wrapper = try SMKUnidentifiedSenderMessage.parse(dataAndPrefix: cipherTextData) + let wrapper = try SMKUnidentifiedSenderMessage(serializedData: cipherTextData) // byte[] ephemeralSalt = ByteUtil.combine("UnidentifiedDelivery".getBytes(), // ourIdentity.getPublicKey().getPublicKey().serialize(), wrapper.getEphemeral().serialize()); @@ -326,7 +326,7 @@ public class SMKDecryptResult: NSObject { cipherTextWithMac: wrapper.encryptedMessage) // content = new UnidentifiedSenderMessageContent(messageBytes); - let messageContent = try SMKUnidentifiedSenderMessageContent.parse(data: messageBytes) + let messageContent = try SMKUnidentifiedSenderMessageContent(serializedData: messageBytes) let senderRecipientId = messageContent.senderCertificate.senderRecipientId let senderDeviceId = messageContent.senderCertificate.senderDeviceId diff --git a/SignalMetadataKit/src/SMKSenderCertificate.swift b/SignalMetadataKit/src/SMKSenderCertificate.swift index b3f251a..724490d 100644 --- a/SignalMetadataKit/src/SMKSenderCertificate.swift +++ b/SignalMetadataKit/src/SMKSenderCertificate.swift @@ -13,76 +13,41 @@ import Foundation @objc public let senderDeviceId: UInt32 @objc public let senderRecipientId: String @objc public let expirationTimestamp: UInt64 + @objc public let serializedData: Data + @objc public let certificateData: Data @objc public let signatureData: Data - @objc public init(signer: SMKServerCertificate, - key: ECPublicKey, - senderDeviceId: UInt32, - senderRecipientId: String, - expirationTimestamp: UInt64, - signatureData: Data) { - self.signer = signer - self.key = key - self.senderDeviceId = senderDeviceId - self.senderRecipientId = senderRecipientId - self.expirationTimestamp = expirationTimestamp - self.signatureData = signatureData - } + public init(serializedData: Data) throws { + // SignalProtos.SenderCertificate wrapper = SignalProtos.SenderCertificate.parseFrom(serialized); + // + // if (!wrapper.hasSignature() || !wrapper.hasCertificate()) { + // throw new InvalidCertificateException("Missing fields"); + // } + let wrapperProto = try SMKProtoSenderCertificate.parseData(serializedData) - @objc public class func parse(data: Data) throws -> SMKSenderCertificate { - let proto = try SMKProtoSenderCertificate.parseData(data) - return try parse(proto: proto) - } + // SignalProtos.SenderCertificate.Certificate certificate = SignalProtos.SenderCertificate.Certificate.parseFrom(wrapper.getCertificate()); + // + // if (!certificate.hasSigner() || !certificate.hasIdentityKey() || !certificate.hasSenderDevice() || !certificate.hasExpires() || !certificate.hasSender()) { + // throw new InvalidCertificateException("Missing fields"); + // } + let certificateProto = try SMKProtoSenderCertificateCertificate.parseData(wrapperProto.certificate) - @objc public class func parse(proto: SMKProtoSenderCertificate) throws -> SMKSenderCertificate { + // this.signer = new ServerCertificate(certificate.getSigner().toByteArray()); + // this.key = Curve.decodePoint(certificate.getIdentityKey().toByteArray(), 0); + // this.sender = certificate.getSender(); + // this.senderDeviceId = certificate.getSenderDevice(); + // this.expiration = certificate.getExpires(); + self.signer = try SMKServerCertificate(serializedData: certificateProto.signer.serializedData()) + self.key = try ECPublicKey(serializedKeyData: certificateProto.identityKey) + self.senderRecipientId = certificateProto.sender + self.senderDeviceId = certificateProto.senderDevice + self.expirationTimestamp = certificateProto.expires - let certificateData = proto.certificate - let signatureData = proto.signature - - let certificateProto = try SMKProtoSenderCertificateCertificate.parseData(certificateData) - - let keyData = certificateProto.identityKey - let key = try ECPublicKey(serializedKeyData: keyData) - let senderDeviceId = certificateProto.senderDevice - let senderRecipientId = certificateProto.sender - let expirationTimestamp = certificateProto.expires - let signerProto = certificateProto.signer - let signer = try SMKServerCertificate.parse(proto: signerProto) - - return SMKSenderCertificate(signer: signer, key: key, senderDeviceId: senderDeviceId, senderRecipientId: senderRecipientId, expirationTimestamp: expirationTimestamp, signatureData: signatureData) - } - - @objc public func toProto() throws -> SMKProtoSenderCertificate { - let certificateBuilder = SMKProtoSenderCertificateCertificate.builder(sender: senderRecipientId, - senderDevice: senderDeviceId, - expires: expirationTimestamp, - identityKey: key.serialized, - signer: try signer.toProto()) - - let builder = - SMKProtoSenderCertificate.builder(certificate: try certificateBuilder.buildSerializedData(), - signature: signatureData) - return try builder.build() - } - - @objc public func serialized() throws -> Data { - return try toProto().serializedData() - } - - open override func isEqual(_ other: Any?) -> Bool { - if let other = other as? SMKSenderCertificate { - return (signer.isEqual(other.signer) && - key.isEqual(other.key) && - senderDeviceId == other.senderDeviceId && - senderRecipientId == other.senderRecipientId && - expirationTimestamp == other.expirationTimestamp && - signatureData == other.signatureData) - } else { - return false - } - } - - public override var hash: Int { - return signer.hashValue ^ key.hashValue ^ senderDeviceId.hashValue ^ senderRecipientId.hashValue ^ expirationTimestamp.hashValue ^ signatureData.hashValue + // this.serialized = serialized; + // this.certificate = wrapper.getCertificate().toByteArray(); + // this.signature = wrapper.getSignature().toByteArray(); + self.serializedData = serializedData + self.certificateData = wrapperProto.certificate + self.signatureData = wrapperProto.signature } } diff --git a/SignalMetadataKit/src/SMKServerCertificate.swift b/SignalMetadataKit/src/SMKServerCertificate.swift index 0a01878..1841502 100644 --- a/SignalMetadataKit/src/SMKServerCertificate.swift +++ b/SignalMetadataKit/src/SMKServerCertificate.swift @@ -10,55 +10,37 @@ import Foundation @objc public let keyId: UInt32 @objc public let key: ECPublicKey + @objc public let serializedData: Data + @objc public let certificateData: Data @objc public let signatureData: Data - public init(keyId: UInt32, - key: ECPublicKey, - signatureData: Data) { - self.keyId = keyId - self.key = key - self.signatureData = signatureData - } + // public ServerCertificate(byte[] serialized) throws InvalidCertificateException { + public init(serializedData: Data) throws { + // SignalProtos.ServerCertificate wrapper = SignalProtos.ServerCertificate.parseFrom(serialized); + // if (!wrapper.hasCertificate() || !wrapper.hasSignature()) { + // throw new InvalidCertificateException("Missing fields"); + // } + let wrapperProto = try SMKProtoServerCertificate.parseData(serializedData) - @objc public class func parse(data: Data) throws -> SMKServerCertificate { - let proto = try SMKProtoServerCertificate.parseData(data) - return try parse(proto: proto) - } + // SignalProtos.ServerCertificate.Certificate certificate = // SignalProtos.ServerCertificate.Certificate.parseFrom(wrapper.getCertificate()); + // + // if (!certificate.hasId() || !certificate.hasKey()) { + // throw new InvalidCertificateException("Missing fields"); + // } + let certificateProto = try SMKProtoServerCertificateCertificate.parseData(wrapperProto.certificate) - @objc public class func parse(proto: SMKProtoServerCertificate) throws -> SMKServerCertificate { - let signatureData = proto.signature - let certificateData = proto.certificate - let certificateProto = try SMKProtoServerCertificateCertificate.parseData(certificateData) - let keyId = certificateProto.id - let keyData = certificateProto.key - let key = try ECPublicKey(serializedKeyData: keyData) - return SMKServerCertificate(keyId: keyId, key: key, signatureData: signatureData) - } + // this.keyId = certificate.getId(); + self.keyId = certificateProto.id - @objc public func toProto() throws -> SMKProtoServerCertificate { - let certificateBuilder = SMKProtoServerCertificateCertificate.builder(id: keyId, key: key.serialized) + // this.key = Curve.decodePoint(certificate.getKey().toByteArray(), 0); + self.key = try ECPublicKey(serializedKeyData: certificateProto.key) - let builder = - SMKProtoServerCertificate.builder(certificate: try certificateBuilder.buildSerializedData(), - signature: signatureData) - return try builder.build() - } + // this.serialized = serialized; + self.serializedData = serializedData - @objc public func serialized() throws -> Data { - return try toProto().serializedData() - } - - open override func isEqual(_ other: Any?) -> Bool { - if let other = other as? SMKServerCertificate { - return (keyId == other.keyId && - key.isEqual(other.key) && - (signatureData == other.signatureData)) - } else { - return false - } - } - - public override var hash: Int { - return keyId.hashValue ^ key.hashValue ^ signatureData.hashValue + // this.certificate = wrapper.getCertificate().toByteArray(); + // this.signature = wrapper.getSignature().toByteArray(); + self.certificateData = wrapperProto.certificate + self.signatureData = wrapperProto.signature } } diff --git a/SignalMetadataKit/src/SMKUnidentifiedSenderMessage.swift b/SignalMetadataKit/src/SMKUnidentifiedSenderMessage.swift index 6cd4a67..deb3729 100644 --- a/SignalMetadataKit/src/SMKUnidentifiedSenderMessage.swift +++ b/SignalMetadataKit/src/SMKUnidentifiedSenderMessage.swift @@ -13,41 +13,23 @@ import Foundation public let ephemeralKey: ECPublicKey public let encryptedStatic: Data public let encryptedMessage: Data + public let serializedData: Data - public init(cipherTextVersion: UInt, - ephemeralKey: ECPublicKey, - encryptedStatic: Data, - encryptedMessage: Data) { - self.cipherTextVersion = cipherTextVersion - self.ephemeralKey = ephemeralKey - self.encryptedStatic = encryptedStatic - self.encryptedMessage = encryptedMessage - } - - public init(ephemeralKey: ECPublicKey, - encryptedStatic: Data, - encryptedMessage: Data) { - self.cipherTextVersion = SMKUnidentifiedSenderMessage.kSMKMessageCipherTextVersion - self.ephemeralKey = ephemeralKey - self.encryptedStatic = encryptedStatic - self.encryptedMessage = encryptedMessage - } - - @objc public class func parse(dataAndPrefix: Data) throws -> SMKUnidentifiedSenderMessage { + public init(serializedData: Data) throws { // public UnidentifiedSenderMessage(byte[] serialized) // throws InvalidMetadataMessageException, InvalidMetadataVersionException - let parser = OWSDataParser(data: dataAndPrefix) + let parser = OWSDataParser(data: serializedData) // this.version = ByteUtil.highBitsToInt(serialized[0]); let versionByte = try parser.nextByte(name: "version byte") - let cipherTextVersion = UInt(SerializationUtilities.highBitsToInt(fromByte: versionByte)) + self.cipherTextVersion = UInt(SerializationUtilities.highBitsToInt(fromByte: versionByte)) // if (version > CIPHERTEXT_VERSION) { // throw new InvalidMetadataVersionException("Unknown version: " + this.version); // } guard cipherTextVersion <= SMKUnidentifiedSenderMessage.kSMKMessageCipherTextVersion else { - throw SMKError.assertionError(description: "\(logTag) unknown cipher text version: \(cipherTextVersion)") + throw SMKError.assertionError(description: "\(type(of: self)) unknown cipherTextVersion: \(cipherTextVersion)") } // SignalProtos.UnidentifiedSenderMessage unidentifiedSenderMessage = @@ -65,30 +47,45 @@ import Foundation // this.ephemeral = Curve.decodePoint(unidentifiedSenderMessage.getEphemeralPublic().toByteArray(), 0); let ephemeralKeyData = proto.ephemeralPublic - let ephemeralKey = try ECPublicKey(serializedKeyData: ephemeralKeyData) + self.ephemeralKey = try ECPublicKey(serializedKeyData: ephemeralKeyData) // this.encryptedStatic = unidentifiedSenderMessage.getEncryptedStatic().toByteArray(); - let encryptedStatic = proto.encryptedStatic + self.encryptedStatic = proto.encryptedStatic // this.encryptedMessage = unidentifiedSenderMessage.getEncryptedMessage().toByteArray(); - let encryptedMessage = proto.encryptedMessage + self.encryptedMessage = proto.encryptedMessage - return SMKUnidentifiedSenderMessage(cipherTextVersion: cipherTextVersion, ephemeralKey: ephemeralKey, encryptedStatic: encryptedStatic, encryptedMessage: encryptedMessage) + // this.serialized = serialized; + self.serializedData = serializedData } - @objc public func toProto() throws -> SMKProtoUnidentifiedSenderMessage { - let builder = SMKProtoUnidentifiedSenderMessage.builder(ephemeralPublic: ephemeralKey.serialized, - encryptedStatic: encryptedStatic, - encryptedMessage: encryptedMessage) - return try builder.build() - } + // public UnidentifiedSenderMessage(ECPublicKey ephemeral, byte[] encryptedStatic, byte[] encryptedMessage) { + public init(ephemeralKey: ECPublicKey, encryptedStatic: Data, encryptedMessage: Data) throws { + // this.version = CIPHERTEXT_VERSION; + // this.ephemeral = ephemeral; + // this.encryptedStatic = encryptedStatic; + // this.encryptedMessage = encryptedMessage; + self.cipherTextVersion = SMKUnidentifiedSenderMessage.kSMKMessageCipherTextVersion + self.ephemeralKey = ephemeralKey + self.encryptedStatic = encryptedStatic + self.encryptedMessage = encryptedMessage - @objc public func serialized() throws -> Data { + // byte[] versionBytes = {ByteUtil.intsToByteHighAndLow(CIPHERTEXT_VERSION, CIPHERTEXT_VERSION)}; let versionByte: UInt8 = UInt8((self.cipherTextVersion << 4 | self.cipherTextVersion) & 0xFF) let versionBytes = [versionByte] let versionData = Data(versionBytes) - let messageData = try toProto().serializedData() - return NSData.join([versionData, messageData]) + // byte[] messageBytes = SignalProtos.UnidentifiedSenderMessage.newBuilder() + // .setEncryptedMessage(ByteString.copyFrom(encryptedMessage)) + // .setEncryptedStatic(ByteString.copyFrom(encryptedStatic)) + // .setEphemeralPublic(ByteString.copyFrom(ephemeral.serialize())) + // .build() + // .toByteArray(); + let messageData = try SMKProtoUnidentifiedSenderMessage.builder(ephemeralPublic: ephemeralKey.serialized, + encryptedStatic: encryptedStatic, + encryptedMessage: encryptedMessage).buildSerializedData() + + // this.serialized = ByteUtil.combine(versionBytes, messageBytes); + self.serializedData = NSData.join([versionData, messageData]) } } diff --git a/SignalMetadataKit/src/SMKUnidentifiedSenderMessageContent.swift b/SignalMetadataKit/src/SMKUnidentifiedSenderMessageContent.swift index 5e24461..bb712a8 100644 --- a/SignalMetadataKit/src/SMKUnidentifiedSenderMessageContent.swift +++ b/SignalMetadataKit/src/SMKUnidentifiedSenderMessageContent.swift @@ -16,53 +16,80 @@ import Foundation @objc public let messageType: SMKMessageType @objc public let senderCertificate: SMKSenderCertificate @objc public let contentData: Data + @objc public let serializedData: Data - @objc public init(messageType: SMKMessageType, - senderCertificate: SMKSenderCertificate, - contentData: Data) { + // public UnidentifiedSenderMessageContent(byte[] serialized) throws InvalidMetadataMessageException, InvalidCertificateException { + public init(serializedData: Data) throws { + // SignalProtos.UnidentifiedSenderMessage.Message message = SignalProtos.UnidentifiedSenderMessage.Message.parseFrom(serialized); + // + // if (!message.hasType() || !message.hasSenderCertificate() || !message.hasContent()) { + // throw new InvalidMetadataMessageException("Missing fields"); + // } + let proto = try SMKProtoUnidentifiedSenderMessageMessage.parseData(serializedData) + + // switch (message.getType()) { + // case MESSAGE: this.type = CiphertextMessage.WHISPER_TYPE; break; + // case PREKEY_MESSAGE: this.type = CiphertextMessage.PREKEY_TYPE; break; + // default: throw new InvalidMetadataMessageException("Unknown type: " + message.getType().getNumber()); + // } + switch (proto.type) { + case .prekeyMessage?: + self.messageType = .prekey + case .message?: + self.messageType = .whisper + default: + throw SMKProtoError.invalidProtobuf(description: "\(type(of: self)) missing required field: proto.type") + } + + // this.senderCertificate = new SenderCertificate(message.getSenderCertificate().toByteArray()); + // this.content = message.getContent().toByteArray(); + // this.serialized = serialized; + self.senderCertificate = try SMKSenderCertificate(serializedData: proto.senderCertificate.serializedData()) + self.contentData = proto.content + self.serializedData = serializedData + } + + // public UnidentifiedSenderMessageContent(int type, SenderCertificate senderCertificate, byte[] content) { + public init(messageType: SMKMessageType, senderCertificate: SMKSenderCertificate, contentData: Data) throws { + // try { + // this.serialized = SignalProtos.UnidentifiedSenderMessage.Message.newBuilder() + // .setType(SignalProtos.UnidentifiedSenderMessage.Message.Type.valueOf(getProtoType(type))) + // .setSenderCertificate(SignalProtos.SenderCertificate.parseFrom(senderCertificate.getSerialized())) + // .setContent(ByteString.copyFrom(content)) + // .build() + // .toByteArray(); + let senderCertificateProto = try SMKProtoSenderCertificate.parseData(senderCertificate.serializedData) + let messageProtoBuilder = SMKProtoUnidentifiedSenderMessageMessage.builder(senderCertificate: senderCertificateProto, + content: contentData) + messageProtoBuilder.setType(messageType.protoType) + self.serializedData = try messageProtoBuilder.buildSerializedData() + + // this.type = type; + // this.senderCertificate = senderCertificate; + // this.content = content; self.messageType = messageType self.senderCertificate = senderCertificate self.contentData = contentData - } - @objc public class func parse(data: Data) throws -> SMKUnidentifiedSenderMessageContent { - - let proto = try SMKProtoUnidentifiedSenderMessageMessage.parseData(data) - - // TODO: Should we have a default case in our switches? Probably. - var messageType: SMKMessageType - switch (proto.type) { - case .prekeyMessage?: - messageType = .prekey - case .message?: - messageType = .whisper - case .none: - throw SMKProtoError.invalidProtobuf(description: "\(logTag) missing required field: proto.type") - } - - let contentData = proto.content - let senderCertificateProto = proto.senderCertificate - let senderCertificate = try SMKSenderCertificate.parse(proto: senderCertificateProto) - - return SMKUnidentifiedSenderMessageContent(messageType: messageType, senderCertificate: senderCertificate, contentData: contentData) - } - - @objc public func toProto() throws -> SMKProtoUnidentifiedSenderMessageMessage { - let builderType: SMKProtoUnidentifiedSenderMessageMessage.SMKProtoUnidentifiedSenderMessageMessageType - switch messageType { - case .whisper: - builderType = .message - case .prekey: - builderType = .prekeyMessage - } - - let builder = SMKProtoUnidentifiedSenderMessageMessage.builder(senderCertificate: try senderCertificate.toProto(), - content: contentData) - builder.setType(builderType) - return try builder.build() - } - - @objc public func serialized() throws -> Data { - return try toProto().serializedData() + // } catch (InvalidProtocolBufferException e) { + // throw new AssertionError(e); + // } + } +} + +fileprivate extension SMKMessageType { + // private int getProtoType(int type) { + var protoType: SMKProtoUnidentifiedSenderMessageMessage.SMKProtoUnidentifiedSenderMessageMessageType { + // switch (type) { + // case CiphertextMessage.WHISPER_TYPE: return SignalProtos.UnidentifiedSenderMessage.Message.Type.MESSAGE_VALUE; + // case CiphertextMessage.PREKEY_TYPE: return SignalProtos.UnidentifiedSenderMessage.Message.Type.PREKEY_MESSAGE_VALUE; + // default: throw new AssertionError(type); + // } + switch self { + case .whisper: + return .message + case .prekey: + return .prekeyMessage + } } } diff --git a/SignalMetadataKitTests/src/SMKMiscTest.swift b/SignalMetadataKitTests/src/SMKMiscTest.swift index 27f7142..58790ec 100644 --- a/SignalMetadataKitTests/src/SMKMiscTest.swift +++ b/SignalMetadataKitTests/src/SMKMiscTest.swift @@ -41,11 +41,10 @@ class SMKTest: XCTestCase { let encryptedStatic = Randomness.generateRandomBytes(100)! let encryptedMessage = Randomness.generateRandomBytes(200)! - let message = SMKUnidentifiedSenderMessage(ephemeralKey: ephemeralKey, + let message = try! SMKUnidentifiedSenderMessage(ephemeralKey: ephemeralKey, encryptedStatic: encryptedStatic, encryptedMessage: encryptedMessage) - let messageData = try! message.serialized() - let parsedMessage = try! SMKUnidentifiedSenderMessage.parse(dataAndPrefix: messageData) + let parsedMessage = try! SMKUnidentifiedSenderMessage(serializedData: message.serializedData) XCTAssertEqual(message.cipherTextVersion, parsedMessage.cipherTextVersion) XCTAssertEqual(message.ephemeralKey.keyData, parsedMessage.ephemeralKey.keyData) XCTAssertEqual(message.encryptedStatic, parsedMessage.encryptedStatic) @@ -53,68 +52,49 @@ class SMKTest: XCTestCase { } func testUDServerCertificate() { - let keyId: UInt32 = 123 - let key = try! ECPublicKey(keyData: Randomness.generateRandomBytes(Int32(ECCKeyLength))!) - let signatureData = Randomness.generateRandomBytes(100)! + let serializedData = try! buildServerCertificateProto().serializedData() - let serverCertificate = SMKServerCertificate(keyId: keyId, - key: key, - signatureData: signatureData) - let serializedData = try! serverCertificate.serialized() - let parsed = try! SMKServerCertificate.parse(data: serializedData) + let serverCertificate = try! SMKServerCertificate(serializedData: serializedData) + let roundTripped = try! SMKServerCertificate(serializedData: serverCertificate.serializedData) - XCTAssertEqual(serverCertificate.keyId, parsed.keyId) - XCTAssertEqual(serverCertificate.key, parsed.key) - XCTAssertEqual(serverCertificate.signatureData, parsed.signatureData) + XCTAssertEqual(serverCertificate.keyId, roundTripped.keyId) + XCTAssertEqual(serverCertificate.key, roundTripped.key) + XCTAssertEqual(serverCertificate.signatureData, roundTripped.signatureData) } func testUDSenderCertificate() { - let serverCertificate = SMKServerCertificate(keyId: 123, - key: try! ECPublicKey(keyData: Randomness.generateRandomBytes(Int32(ECCKeyLength))!), - signatureData: Randomness.generateRandomBytes(100)!) + let serializedData = try! buildSenderCertificateProto().serializedData() - let key = try! ECPublicKey(keyData: Randomness.generateRandomBytes(Int32(ECCKeyLength))!) - let senderDeviceId: UInt32 = 456 - let senderRecipientId = "+13213214321" - let expirationTimestamp: UInt64 = 789 - let signatureData = Randomness.generateRandomBytes(100)! - let senderCertificate = SMKSenderCertificate(signer: serverCertificate, - key: key, - senderDeviceId: senderDeviceId, - senderRecipientId: senderRecipientId, - expirationTimestamp: expirationTimestamp, - signatureData: signatureData) - let serializedData = try! senderCertificate.serialized() - let parsed = try! SMKSenderCertificate.parse(data: serializedData) + let senderCertificate = try! SMKSenderCertificate(serializedData: serializedData) + let roundTripped = try! SMKSenderCertificate(serializedData: senderCertificate.serializedData) - XCTAssertEqual(senderCertificate.signer, parsed.signer) - XCTAssertEqual(senderCertificate.key, parsed.key) - XCTAssertEqual(senderCertificate.senderDeviceId, parsed.senderDeviceId) - XCTAssertEqual(senderCertificate.senderRecipientId, parsed.senderRecipientId) - XCTAssertEqual(senderCertificate.expirationTimestamp, parsed.expirationTimestamp) - XCTAssertEqual(senderCertificate.signatureData, parsed.signatureData) + XCTAssertEqual(senderCertificate.signer.serializedData, roundTripped.signer.serializedData) + XCTAssertEqual(senderCertificate.key, roundTripped.key) + XCTAssertEqual(senderCertificate.senderDeviceId, roundTripped.senderDeviceId) + XCTAssertEqual(senderCertificate.senderRecipientId, roundTripped.senderRecipientId) + XCTAssertEqual(senderCertificate.expirationTimestamp, roundTripped.expirationTimestamp) + XCTAssertEqual(senderCertificate.signatureData, roundTripped.signatureData) } func testUDMessageContent() { - let serverCertificate = SMKServerCertificate(keyId: 123, - key: try! ECPublicKey(keyData: Randomness.generateRandomBytes(Int32(ECCKeyLength))!), - signatureData: Randomness.generateRandomBytes(100)!) - let senderCertificate = SMKSenderCertificate(signer: serverCertificate, - key: try! ECPublicKey(keyData: Randomness.generateRandomBytes(Int32(ECCKeyLength))!), - senderDeviceId: 456, - senderRecipientId: "+13213214321", - expirationTimestamp: 789, - signatureData: Randomness.generateRandomBytes(100)!) - let contentData = Randomness.generateRandomBytes(200)! + let senderCertificateProto = buildSenderCertificateProto() + let senderCertificate = try! SMKSenderCertificate(serializedData: try! senderCertificateProto.serializedData()) - let message = SMKUnidentifiedSenderMessageContent(messageType: .whisper, - senderCertificate: senderCertificate, - contentData: contentData) - let messageData = try! message.serialized() - let parsed = try! SMKUnidentifiedSenderMessageContent.parse(data: messageData) + let contentData = Randomness.generateRandomBytes(200)! + let serializedData: Data = { + let builder = SMKProtoUnidentifiedSenderMessageMessage.builder(senderCertificate: senderCertificateProto, + content: contentData) + builder.setType(.message) + return try! builder.buildSerializedData() + }() + + let parsed = try! SMKUnidentifiedSenderMessageContent(serializedData: serializedData) + let message = try! SMKUnidentifiedSenderMessageContent(messageType: .whisper, + senderCertificate: senderCertificate, + contentData: contentData) XCTAssertEqual(message.messageType, parsed.messageType) - XCTAssertEqual(message.senderCertificate, parsed.senderCertificate) + XCTAssertEqual(message.senderCertificate.serializedData, parsed.senderCertificate.serializedData) XCTAssertEqual(message.contentData, parsed.contentData) } @@ -144,32 +124,73 @@ class SMKTest: XCTestCase { let plaintext = Randomness.generateRandomBytes(200)! let paddedPlaintext = (plaintext as NSData).paddedMessageBody()! - let serverCertificate = SMKServerCertificate(keyId: 123, - key: try! ECPublicKey(keyData: Randomness.generateRandomBytes(Int32(ECCKeyLength))!), - signatureData: Randomness.generateRandomBytes(100)!) - let senderCertificate = SMKSenderCertificate(signer: serverCertificate, - key: try! aliceMockClient.identityKeyPair.ecPublicKey(), - senderDeviceId: UInt32(aliceMockClient.deviceId), - senderRecipientId: aliceMockClient.recipientId, - expirationTimestamp: 789, - signatureData: Randomness.generateRandomBytes(100)!) + let senderCertificate = try! SMKSenderCertificate(serializedData: try! buildSenderCertificateProto(senderClient: aliceMockClient).serializedData()) let encryptedMessage = try! aliceToBobCipher.throwswrapped_encryptMessage(recipientId: bobMockClient.recipientId, - deviceId: bobMockClient.deviceId, - paddedPlaintext: paddedPlaintext, senderCertificate: senderCertificate, protocolContext: nil) + deviceId: bobMockClient.deviceId, + paddedPlaintext: paddedPlaintext, + senderCertificate: senderCertificate, + protocolContext: nil) let messageTimestamp = NSDate.ows_millisecondTimeStamp() let bobToAliceCipher = try! bobMockClient.createSecretSessionCipher() let decryptedMessage = try! bobToAliceCipher.throwswrapped_decryptMessage(certificateValidator: certificateValidator, - cipherTextData: encryptedMessage, - timestamp: messageTimestamp, - localRecipientId: bobMockClient.recipientId, - localDeviceId: bobMockClient.deviceId, - protocolContext: nil) + cipherTextData: encryptedMessage, + timestamp: messageTimestamp, + localRecipientId: bobMockClient.recipientId, + localDeviceId: bobMockClient.deviceId, + protocolContext: nil) let payload = (decryptedMessage.paddedPayload as NSData).removePadding() XCTAssertEqual(aliceMockClient.recipientId, decryptedMessage.senderRecipientId) XCTAssertEqual(aliceMockClient.deviceId, Int32(decryptedMessage.senderDeviceId)) XCTAssertEqual(plaintext, payload) } + + // MARK: - Util + + func buildServerCertificateProto() -> SMKProtoServerCertificate { + let serverKey = try! Curve25519.generateKeyPair().ecPublicKey().serialized + let certificateData = try! SMKProtoServerCertificateCertificate.builder(id: 123, + key: serverKey ).buildSerializedData() + + let signatureData = Randomness.generateRandomBytes(ECCSignatureLength)! + + let wrapperProto = SMKProtoServerCertificate.builder(certificate: certificateData, + signature: signatureData) + + return try! wrapperProto.build() + } + + func buildSenderCertificateProto(senderClient: MockClient? = nil) -> SMKProtoSenderCertificate { + let sender: String + let senderDevice: UInt32 + let expires = NSDate.ows_millisecondTimeStamp() + kWeekInMs + let identityKey: ECPublicKey + let signer = buildServerCertificateProto() + + if let senderClient = senderClient { + sender = senderClient.recipientId + senderDevice = UInt32(senderClient.deviceId) + identityKey = try! senderClient.identityKeyPair.ecPublicKey() + } else { + sender = "+1235551234" + senderDevice = 123 + identityKey = try! Curve25519.generateKeyPair().ecPublicKey() + } + + let certificateData = try! SMKProtoSenderCertificateCertificate.builder(sender: sender, + senderDevice: senderDevice, + expires: expires, + identityKey: identityKey.serialized, + signer: signer) + .buildSerializedData() + + let signatureData = Randomness.generateRandomBytes(ECCSignatureLength)! + + let wrapperProto = try! SMKProtoSenderCertificate.builder(certificate: certificateData, + signature: signatureData).build() + + return wrapperProto + } } diff --git a/SignalMetadataKitTests/src/SMKSecretSessionCipherTest.swift b/SignalMetadataKitTests/src/SMKSecretSessionCipherTest.swift index b1f5d27..e7129b3 100644 --- a/SignalMetadataKitTests/src/SMKSecretSessionCipherTest.swift +++ b/SignalMetadataKitTests/src/SMKSecretSessionCipherTest.swift @@ -272,62 +272,61 @@ class SMKSecretSessionCipherTest: XCTestCase { // ECKeyPair serverKey = Curve.generateKeyPair(); let serverKey = Curve25519.generateKeyPair() -// byte[] serverCertificateBytes = SignalProtos.ServerCertificate.Certificate.newBuilder() -// .setId(1) -// .setKey(ByteString.copyFrom(serverKey.getPublicKey().serialize())) -// .build() -// .toByteArray(); - let keyId: UInt32 = 1 - let unsignedServerCertificateBuilder = SMKProtoServerCertificateCertificate.builder(id: keyId, - key: try! serverKey.ecPublicKey().serialized) - let unsignedServerCertificateData = try! unsignedServerCertificateBuilder.build().serializedData() + // byte[] serverCertificateBytes = SignalProtos.ServerCertificate.Certificate.newBuilder() + // .setId(1) + // .setKey(ByteString.copyFrom(serverKey.getPublicKey().serialize())) + // .build() + // .toByteArray(); + let serverCertificateBuilder = SMKProtoServerCertificateCertificate.builder(id: 1, + key: try! serverKey.ecPublicKey().serialized) + let serverCertificateData = try! serverCertificateBuilder.build().serializedData() -// byte[] serverCertificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), serverCertificateBytes); - let serverCertificateSignature = try! Ed25519.sign(unsignedServerCertificateData, with: trustRoot) + // byte[] serverCertificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), serverCertificateBytes); + let serverCertificateSignature = try! Ed25519.sign(serverCertificateData, with: trustRoot) -// ServerCertificate serverCertificate = new ServerCertificate(SignalProtos.ServerCertificate.newBuilder() -// .setCertificate(ByteString.copyFrom(serverCertificateBytes)) -// .setSignature(ByteString.copyFrom(serverCertificateSignature)) -// .build() -// .toByteArray()); - let signedServerCertificate = SMKServerCertificate(keyId: keyId, - key: try! serverKey.ecPublicKey(), - signatureData: serverCertificateSignature) - XCTAssertEqual(try! signedServerCertificate.toProto().certificate, unsignedServerCertificateData) - _ = try! signedServerCertificate.serialized() + // ServerCertificate serverCertificate = new ServerCertificate(SignalProtos.ServerCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(serverCertificateBytes)) + // .setSignature(ByteString.copyFrom(serverCertificateSignature)) + // .build() + // .toByteArray()); + let serverCertificate: SMKServerCertificate = { + let builder = SMKProtoServerCertificate.builder(certificate: serverCertificateData, + signature: serverCertificateSignature) -// byte[] senderCertificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() -// .setSender(sender) -// .setSenderDevice(deviceId) -// .setIdentityKey(ByteString.copyFrom(identityKey.serialize())) -// .setExpires(expires) -// .setSigner(SignalProtos.ServerCertificate.parseFrom(serverCertificate.getSerialized())) -// .build() -// .toByteArray(); - let unsignedSenderCertificateBuilder = SMKProtoSenderCertificateCertificate.builder(sender: senderRecipientId, - senderDevice: senderDeviceId, - expires: expirationTimestamp, - identityKey: identityKey.serialized, - signer: try! signedServerCertificate.toProto()) - let unsignedSenderCertificateData = try! unsignedSenderCertificateBuilder.build().serializedData() + return try! SMKServerCertificate(serializedData: try! builder.buildSerializedData()) + }() -// byte[] senderCertificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), senderCertificateBytes); - let senderCertificateSignature = try! Ed25519.sign(unsignedSenderCertificateData, with: serverKey) + // byte[] senderCertificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() + // .setSender(sender) + // .setSenderDevice(deviceId) + // .setIdentityKey(ByteString.copyFrom(identityKey.serialize())) + // .setExpires(expires) + // .setSigner(SignalProtos.ServerCertificate.parseFrom(serverCertificate.getSerialized())) + // .build() + // .toByteArray(); + let senderCertificateData: Data = { + let signer = try! SMKProtoServerCertificate.parseData(serverCertificate.serializedData) + let builder = SMKProtoSenderCertificateCertificate.builder(sender: senderRecipientId, + senderDevice: senderDeviceId, + expires: expirationTimestamp, + identityKey: identityKey.serialized, + signer: signer) + return try! builder.buildSerializedData() + }() -// return new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() -// .setCertificate(ByteString.copyFrom(senderCertificateBytes)) -// .setSignature(ByteString.copyFrom(senderCertificateSignature)) -// .build() -// .toByteArray()); + // byte[] senderCertificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), senderCertificateBytes); + let senderCertificateSignature = try! Ed25519.sign(senderCertificateData, with: serverKey) - let signedSenderCertificate = SMKSenderCertificate(signer: signedServerCertificate, - key: identityKey, - senderDeviceId: senderDeviceId, - senderRecipientId: senderRecipientId, - expirationTimestamp: expirationTimestamp, - signatureData: senderCertificateSignature) - XCTAssertEqual(try! signedSenderCertificate.signer.toProto().certificate, unsignedServerCertificateData) - return signedSenderCertificate + // return new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(senderCertificateBytes)) + // .setSignature(ByteString.copyFrom(senderCertificateSignature)) + // .build() + // .toByteArray()); + return { + let builder = SMKProtoSenderCertificate.builder(certificate: senderCertificateData, + signature: senderCertificateSignature) + return try! SMKSenderCertificate(serializedData: try! builder.buildSerializedData()) + }() } // private void initializeSessions(TestInMemorySignalProtocolStore aliceStore, TestInMemorySignalProtocolStore bobStore) diff --git a/SignalMetadataKitTests/src/SMKSenderCertificateTest.swift b/SignalMetadataKitTests/src/SMKSenderCertificateTest.swift index 3fb9d47..5d21237 100644 --- a/SignalMetadataKitTests/src/SMKSenderCertificateTest.swift +++ b/SignalMetadataKitTests/src/SMKSenderCertificateTest.swift @@ -30,46 +30,37 @@ class SMKSenderCertificateTest: XCTestCase { let serverKey = Curve25519.generateKeyPair() let key = Curve25519.generateKeyPair() - // byte[] certificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() - // .setSender("+14152222222") - // .setSenderDevice(1) - // .setExpires(31337) - // .setIdentityKey(ByteString.copyFrom(key.getPublicKey().serialize())) - // .setSigner(getServerCertificate(serverKey)) - // .build() - // .toByteArray(); + // byte[] certificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() + // .setSender("+14152222222") + // .setSenderDevice(1) + // .setExpires(31337) + // .setIdentityKey(ByteString.copyFrom(key.getPublicKey().serialize())) + // .setSigner(getServerCertificate(serverKey)) + // .build() + // .toByteArray(); + let signer = try! getServerCertificate(serverKey: serverKey) + let certificateData = try! SMKProtoSenderCertificateCertificate.builder(sender: "+14152222222", + senderDevice: 1, + expires: 31337, + identityKey: key.ecPublicKey().serialized, + signer: signer).buildSerializedData() - let senderRecipientId = "+14152222222" - let senderDeviceId: UInt32 = 1 - let expirationTimestamp: UInt64 = 31337 + // byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes); + let certificateSignature = try! Ed25519.sign(certificateData, with: serverKey) - let serverCertificate = getServerCertificate(serverKey: serverKey, trustRoot: trustRoot) - let unsignedCertificateBuilder = SMKProtoSenderCertificateCertificate.builder(sender: senderRecipientId, - senderDevice: senderDeviceId, - expires: expirationTimestamp, - identityKey: try! key.ecPublicKey().serialized, - signer: try! serverCertificate.toProto()) - unsignedCertificateBuilder.setSigner(try! serverCertificate.toProto()) - let unsignedSenderCertificateData = try! unsignedCertificateBuilder.build().serializedData() + // SenderCertificate senderCertificate = new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(certificateBytes)) + // .setSignature(ByteString.copyFrom(certificateSignature)) + // .build() + // .toByteArray()); + let senderCertificateData = try! SMKProtoSenderCertificate.builder(certificate: certificateData, + signature: certificateSignature) + .buildSerializedData() + let senderCertificate = try! SMKSenderCertificate(serializedData: senderCertificateData) - // byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes); - let senderCertificateSignature = try! Ed25519.sign(unsignedSenderCertificateData, with: serverKey) - - // SenderCertificate senderCertificate = new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() - // .setCertificate(ByteString.copyFrom(certificateBytes)) - // .setSignature(ByteString.copyFrom(certificateSignature)) - // .build() - // .toByteArray()); - let signedSenderCertificate = SMKSenderCertificate(signer: serverCertificate, - key: try! key.ecPublicKey(), - senderDeviceId: senderDeviceId, - senderRecipientId: senderRecipientId, - expirationTimestamp: expirationTimestamp, - signatureData: senderCertificateSignature) - - // new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31336); + // new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31336); let certificateValidator = try! SMKCertificateDefaultValidator(trustRoot: trustRoot.ecPublicKey()) - try! certificateValidator.throwswrapped_validate(senderCertificate: signedSenderCertificate, validationTime: 31336) + try! certificateValidator.throwswrapped_validate(senderCertificate: senderCertificate, validationTime: 31336) } // public void testExpiredSignature() throws InvalidCertificateException, InvalidKeyException { @@ -77,51 +68,44 @@ class SMKSenderCertificateTest: XCTestCase { // ECKeyPair serverKey = Curve.generateKeyPair(); // ECKeyPair key = Curve.generateKeyPair(); let serverKey = Curve25519.generateKeyPair() - let key = Curve25519.generateKeyPair() + let key = Curve25519.generateKeyPair() - // byte[] certificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() - // .setSender("+14152222222") - // .setSenderDevice(1) - // .setExpires(31337) - // .setIdentityKey(ByteString.copyFrom(key.getPublicKey().serialize())) - // .setSigner(getServerCertificate(serverKey)) - // .build() - // .toByteArray(); - let senderRecipientId = "+14152222222" - let senderDeviceId: UInt32 = 1 - let expirationTimestamp: UInt64 = 31337 + // byte[] certificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() + // .setSender("+14152222222") + // .setSenderDevice(1) + // .setExpires(31337) + // .setIdentityKey(ByteString.copyFrom(key.getPublicKey().serialize())) + // .setSigner(getServerCertificate(serverKey)) + // .build() + // .toByteArray(); + let signer = try! getServerCertificate(serverKey: serverKey) + let certificateData = try! SMKProtoSenderCertificateCertificate.builder(sender: "+14152222222", + senderDevice: 1, + expires: 31337, + identityKey: key.ecPublicKey().serialized, + signer: signer).buildSerializedData() - let serverCertificate = getServerCertificate(serverKey: serverKey, trustRoot: trustRoot) - let unsignedCertificateBuilder = SMKProtoSenderCertificateCertificate.builder(sender: senderRecipientId, - senderDevice: senderDeviceId, - expires: expirationTimestamp, - identityKey: try! key.ecPublicKey().serialized, - signer: try! serverCertificate.toProto()) - let unsignedSenderCertificateData = try! unsignedCertificateBuilder.build().serializedData() + // byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes); + let certificateSignature = try! Ed25519.sign(certificateData, with: serverKey) - // byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes); - let senderCertificateSignature = try! Ed25519.sign(unsignedSenderCertificateData, with: serverKey) + // SenderCertificate senderCertificate = new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(certificateBytes)) + // .setSignature(ByteString.copyFrom(certificateSignature)) + // .build() + // .toByteArray()); + let senderCertificateData = try! SMKProtoSenderCertificate.builder(certificate: certificateData, + signature: certificateSignature) + .buildSerializedData() + let senderCertificate = try! SMKSenderCertificate(serializedData: senderCertificateData) - // SenderCertificate senderCertificate = new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() - // .setCertificate(ByteString.copyFrom(certificateBytes)) - // .setSignature(ByteString.copyFrom(certificateSignature)) - // .build() - // .toByteArray()); - let signedSenderCertificate = SMKSenderCertificate(signer: serverCertificate, - key: try! key.ecPublicKey(), - senderDeviceId: senderDeviceId, - senderRecipientId: senderRecipientId, - expirationTimestamp: expirationTimestamp, - signatureData: senderCertificateSignature) - - // try { - // new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31338); - // throw new AssertionError(); - // } catch (InvalidCertificateException e) { - // // good - // } + // try { + // new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31338); + // throw new AssertionError(); + // } catch (InvalidCertificateException e) { + // // good + // } let certificateValidator = try! SMKCertificateDefaultValidator(trustRoot: trustRoot.ecPublicKey()) - XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(senderCertificate: signedSenderCertificate, validationTime: 31338)) + XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(senderCertificate: senderCertificate, validationTime: 31338)) } // public void testBadSignature() throws InvalidCertificateException, InvalidKeyException { @@ -129,92 +113,82 @@ class SMKSenderCertificateTest: XCTestCase { // ECKeyPair serverKey = Curve.generateKeyPair(); // ECKeyPair key = Curve.generateKeyPair(); let serverKey = Curve25519.generateKeyPair() - let key = Curve25519.generateKeyPair() + let key = Curve25519.generateKeyPair() - // byte[] certificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() - // .setSender("+14152222222") - // .setSenderDevice(1) - // .setExpires(31337) - // .setIdentityKey(ByteString.copyFrom(key.getPublicKey().serialize())) - // .setSigner(getServerCertificate(serverKey)) - // .build() - // .toByteArray(); - let senderRecipientId = "+14152222222" - let senderDeviceId: UInt32 = 1 - let expirationTimestamp: UInt64 = 31337 + // byte[] certificateBytes = SignalProtos.SenderCertificate.Certificate.newBuilder() + // .setSender("+14152222222") + // .setSenderDevice(1) + // .setExpires(31337) + // .setIdentityKey(ByteString.copyFrom(key.getPublicKey().serialize())) + // .setSigner(getServerCertificate(serverKey)) + // .build() + // .toByteArray(); + let signer = try! getServerCertificate(serverKey: serverKey) + let certificateData = try! SMKProtoSenderCertificateCertificate.builder(sender: "+14152222222", + senderDevice: 1, + expires: 31337, + identityKey: key.ecPublicKey().serialized, + signer: signer).buildSerializedData() - let serverCertificate = getServerCertificate(serverKey: serverKey, trustRoot: trustRoot) - let unsignedCertificateBuilder = SMKProtoSenderCertificateCertificate.builder(sender: senderRecipientId, - senderDevice: senderDeviceId, - expires: expirationTimestamp, - identityKey: try! key.ecPublicKey().serialized, - signer: try! serverCertificate.toProto()) - let unsignedSenderCertificateData = try! unsignedCertificateBuilder.build().serializedData() + // byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes); + let certificateSignature = try! Ed25519.sign(certificateData, with: serverKey) - // byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes); - let senderCertificateSignature = try! Ed25519.sign(unsignedSenderCertificateData, with: serverKey) - - // for (int i=0;i) in bytes[i] = (UInt8)(bytes[i] ^ 1 << b) } - // SenderCertificate senderCertificate = new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() - // .setCertificate(ByteString.copyFrom(certificateBytes)) - // .setSignature(ByteString.copyFrom(badSignature)) - // .build() - // .toByteArray()); - let signedSenderCertificate = SMKSenderCertificate(signer: serverCertificate, - key: try! key.ecPublicKey(), - senderDeviceId: senderDeviceId, - senderRecipientId: senderRecipientId, - expirationTimestamp: expirationTimestamp, - signatureData: badSignature) + // SenderCertificate senderCertificate = new SenderCertificate(SignalProtos.SenderCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(certificateBytes)) + // .setSignature(ByteString.copyFrom(badSignature)) + // .build() + // .toByteArray()); + let serializedData = try! SMKProtoSenderCertificate.builder(certificate: certificateData, + signature: badSignature).buildSerializedData() + let senderCertificate = try! SMKSenderCertificate(serializedData: serializedData) - // try { - // new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31336); - // throw new AssertionError(); - // } catch (InvalidCertificateException e) { - // // good - // } + // try { + // new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31336); + // throw new AssertionError(); + // } catch (InvalidCertificateException e) { + // // good + // } let certificateValidator = try! SMKCertificateDefaultValidator(trustRoot: trustRoot.ecPublicKey()) - XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(senderCertificate: signedSenderCertificate, validationTime: 31336)) + XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(senderCertificate: senderCertificate, + validationTime: 31336)) } } } // MARK: - Utils - // private SignalProtos.ServerCertificate getServerCertificate(ECKeyPair serverKey) throws InvalidKeyException, InvalidCertificateException { - private func getServerCertificate(serverKey: ECKeyPair, trustRoot: ECKeyPair) -> SMKServerCertificate { - // byte[] certificateBytes = SignalProtos.ServerCertificate.Certificate.newBuilder() - // .setId(1) - // .setKey(ByteString.copyFrom(serverKey.getPublicKey().serialize())) - // .build() - // .toByteArray(); - let keyId: UInt32 = 1 - let unsignedServerCertificateBuilder = SMKProtoServerCertificateCertificate.builder(id: keyId, - key: try! serverKey.ecPublicKey().serialized) - let unsignedServerCertificateData = try! unsignedServerCertificateBuilder.build().serializedData() + // private SignalProtos.ServerCertificate getServerCertificate(ECKeyPair serverKey) throws InvalidKeyException, InvalidCertificateException { + private func getServerCertificate(serverKey: ECKeyPair) throws -> SMKProtoServerCertificate { + // byte[] certificateBytes = SignalProtos.ServerCertificate.Certificate.newBuilder() + // .setId(1) + // .setKey(ByteString.copyFrom(serverKey.getPublicKey().serialize())) + // .build() + // .toByteArray(); + let certificateData = try! SMKProtoServerCertificateCertificate.builder(id: 1, + key: serverKey.ecPublicKey().serialized) + .buildSerializedData() - // byte[] certificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), certificateBytes); - let serverCertificateSignature = try! Ed25519.sign(unsignedServerCertificateData, with: trustRoot) + // byte[] certificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), certificateBytes); + let certificateSignature = try! Ed25519.sign(certificateData, with: trustRoot) - // return SignalProtos.ServerCertificate.newBuilder() - // .setCertificate(ByteString.copyFrom(certificateBytes)) - // .setSignature(ByteString.copyFrom(certificateSignature)) - // .build(); - let signedServerCertificate = SMKServerCertificate(keyId: keyId, - key: try! serverKey.ecPublicKey(), - signatureData: serverCertificateSignature) - return signedServerCertificate + // return SignalProtos.ServerCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(certificateBytes)) + // .setSignature(ByteString.copyFrom(certificateSignature)) + // .build(); + return try! SMKProtoServerCertificate.builder(certificate: certificateData, + signature: certificateSignature).build() } } diff --git a/SignalMetadataKitTests/src/SMKServerCertificateTest.swift b/SignalMetadataKitTests/src/SMKServerCertificateTest.swift index 511915c..16a6ca6 100644 --- a/SignalMetadataKitTests/src/SMKServerCertificateTest.swift +++ b/SignalMetadataKitTests/src/SMKServerCertificateTest.swift @@ -60,33 +60,31 @@ class SMKServerCertificateTest: XCTestCase { let trustRoot = Curve25519.generateKeyPair() let keyPair = Curve25519.generateKeyPair() -// SignalProtos.ServerCertificate.Certificate certificate = SignalProtos.ServerCertificate.Certificate.newBuilder() -// .setId(1) -// .setKey(ByteString.copyFrom(keyPair.getPublicKey().serialize())) -// .build(); - let keyId: UInt32 = 1 - let unsignedServerCertificateBuilder = SMKProtoServerCertificateCertificate.builder(id: keyId, - key: try! keyPair.ecPublicKey().serialized) + // SignalProtos.ServerCertificate.Certificate certificate = SignalProtos.ServerCertificate.Certificate.newBuilder() + // .setId(1) + // .setKey(ByteString.copyFrom(keyPair.getPublicKey().serialize())) + // .build(); + let certificateBuilder = SMKProtoServerCertificateCertificate.builder(id: 1, + key: try! keyPair.ecPublicKey().serialized) + // byte[] certificateBytes = certificate.toByteArray(); + let certificateData = try! certificateBuilder.build().serializedData() - // byte[] certificateBytes = certificate.toByteArray(); - let unsignedServerCertificateData = try! unsignedServerCertificateBuilder.build().serializedData() + // byte[] certificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), certificateBytes); + let certificateSignature = try! Ed25519.sign(certificateData, with: trustRoot) -// byte[] certificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), certificateBytes); - let serverCertificateSignature = try! Ed25519.sign(unsignedServerCertificateData, with: trustRoot) + // byte[] serialized = SignalProtos.ServerCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(certificateBytes)) + // .setSignature(ByteString.copyFrom(certificateSignature)) + // .build().toByteArray(); + // + let serializedData = try! SMKProtoServerCertificate.builder(certificate: certificateData, + signature: certificateSignature) + .buildSerializedData() -// byte[] serialized = SignalProtos.ServerCertificate.newBuilder() -// .setCertificate(ByteString.copyFrom(certificateBytes)) -// .setSignature(ByteString.copyFrom(certificateSignature)) -// .build().toByteArray(); - let signedServerCertificate = SMKServerCertificate(keyId: keyId, - key: try! keyPair.ecPublicKey(), - signatureData: serverCertificateSignature) - let serializedData = try! signedServerCertificate.serialized() - let parsed = try! SMKServerCertificate.parse(data: serializedData) - -// new CertificateValidator(trustRoot.getPublicKey()).validate(new ServerCertificate(serialized)); + // new CertificateValidator(trustRoot.getPublicKey()).validate(new ServerCertificate(serialized)); + let serverCertificate = try! SMKServerCertificate(serializedData: serializedData) let certificateValidator = SMKCertificateDefaultValidator(trustRoot: try! trustRoot.ecPublicKey()) - try! certificateValidator.throwswrapped_validate(serverCertificate: parsed) + try! certificateValidator.throwswrapped_validate(serverCertificate: serverCertificate) } // public void testBadSignature() throws Exception { @@ -96,77 +94,83 @@ class SMKServerCertificateTest: XCTestCase { let trustRoot = Curve25519.generateKeyPair() let keyPair = Curve25519.generateKeyPair() -// SignalProtos.ServerCertificate.Certificate certificate = SignalProtos.ServerCertificate.Certificate.newBuilder() -// .setId(1) -// .setKey(ByteString.copyFrom(keyPair.getPublicKey().serialize())) -// .build(); - let keyId: UInt32 = 1 - let unsignedServerCertificateBuilder = SMKProtoServerCertificateCertificate.builder(id: keyId, - key: try! keyPair.ecPublicKey().serialized) + // SignalProtos.ServerCertificate.Certificate certificate = SignalProtos.ServerCertificate.Certificate.newBuilder() + // .setId(1) + // .setKey(ByteString.copyFrom(keyPair.getPublicKey().serialize())) + // .build(); + let certificate = try! SMKProtoServerCertificateCertificate.builder(id: 1, + key: try! keyPair.ecPublicKey().serialized) + .build() -// byte[] certificateBytes = certificate.toByteArray(); - let unsignedServerCertificateData = try! unsignedServerCertificateBuilder.build().serializedData() + // byte[] certificateBytes = certificate.toByteArray(); + let certificateData = try! certificate.serializedData() -// byte[] certificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), certificateBytes); - let serverCertificateSignature = try! Ed25519.sign(unsignedServerCertificateData, with: trustRoot) + // byte[] certificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), certificateBytes); + let certificateSignature = try! Ed25519.sign(certificateData, with: trustRoot) -// for (int i=0;i) in - bytes[i] = (UInt8)(bytes[i] ^ 1 << b) + // byte[] badSignature = new byte[certificateSignature.length]; + // System.arraycopy(certificateSignature, 0, badSignature, 0, badSignature.length); + // + // badSignature[i] = (byte) (badSignature[i] ^ (1 << b)); + var badSignature = certificateSignature + badSignature.withUnsafeMutableBytes { (bytes: UnsafeMutableRawBufferPointer) in + bytes[i] = (bytes[i] ^ 1 << b) } -// byte[] serialized = SignalProtos.ServerCertificate.newBuilder() -// .setCertificate(ByteString.copyFrom(certificateBytes)) -// .setSignature(ByteString.copyFrom(badSignature)) -// .build().toByteArray(); - let signedServerCertificate = SMKServerCertificate(keyId: keyId, - key: try! keyPair.ecPublicKey(), - signatureData: badSignature) - let serializedData = try! signedServerCertificate.serialized() - let parsed = try! SMKServerCertificate.parse(data: serializedData) + // byte[] serialized = SignalProtos.ServerCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(certificateBytes)) + // .setSignature(ByteString.copyFrom(badSignature)) + // .build().toByteArray(); + let serializedData = try! SMKProtoServerCertificate.builder(certificate: certificateData, + signature: badSignature) + .buildSerializedData() -// try { -// new CertificateValidator(trustRoot.getPublicKey()).validate(new ServerCertificate(serialized)); -// throw new AssertionError(); -// } catch (InvalidCertificateException e) { -// // good -// } + // try { + // new CertificateValidator(trustRoot.getPublicKey()).validate(new ServerCertificate(serialized)); + // throw new AssertionError(); + // } catch (InvalidCertificateException e) { + // // good + // } + let serverCertificate = try! SMKServerCertificate(serializedData: serializedData) let certificateValidator = SMKCertificateDefaultValidator(trustRoot: try! trustRoot.ecPublicKey()) - XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(serverCertificate: parsed)) + XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(serverCertificate: serverCertificate)) } } -// for (int i=0;i) in - bytes[i] = (UInt8)(bytes[i] ^ 1 << b) + // byte[] badCertificate = new byte[certificateBytes.length]; + // System.arraycopy(certificateBytes, 0, badCertificate, 0, badCertificate.length); + // + // badCertificate[i] = (byte) (badCertificate[i] ^ (1 << b)); + var badCertificate = certificateData + badCertificate.withUnsafeMutableBytes { (bytes: UnsafeMutableRawBufferPointer) in + bytes[i] = (bytes[i] ^ 1 << b) } -// byte[] serialized = SignalProtos.ServerCertificate.newBuilder() -// .setCertificate(ByteString.copyFrom(badCertificate)) -// .setSignature(ByteString.copyFrom(certificateSignature)) -// .build().toByteArray(); - let builder = - SMKProtoServerCertificate.builder(certificate: badCertificate, signature: serverCertificateSignature) - let serializedData = try! builder.buildSerializedData() - let parsed: SMKServerCertificate + // byte[] serialized = SignalProtos.ServerCertificate.newBuilder() + // .setCertificate(ByteString.copyFrom(badCertificate)) + // .setSignature(ByteString.copyFrom(certificateSignature)) + // .build().toByteArray(); + let serializedData = try! SMKProtoServerCertificate.builder(certificate: badCertificate, + signature: certificateSignature) + .buildSerializedData() + + // try { + // new CertificateValidator(trustRoot.getPublicKey()).validate(new ServerCertificate(serialized)); + // throw new AssertionError(); + // } catch (InvalidCertificateException e) { + // // good + // } + let serverCertificate: SMKServerCertificate do { - parsed = try SMKServerCertificate.parse(data: serializedData) + serverCertificate = try SMKServerCertificate(serializedData: serializedData) } catch BinaryDecodingError.malformedProtobuf { // Some bad certificates will fail to parse. continue @@ -192,7 +196,7 @@ class SMKServerCertificateTest: XCTestCase { // } // } let certificateValidator = SMKCertificateDefaultValidator(trustRoot: try! trustRoot.ecPublicKey()) - XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(serverCertificate: parsed)) + XCTAssertThrowsError(try certificateValidator.throwswrapped_validate(serverCertificate: serverCertificate)) } } }