Partially implement messaging kit encryption & decryption

This commit is contained in:
nielsandriesse 2020-11-06 19:32:09 +11:00
parent 52ed49d61e
commit 21fe9558a4
17 changed files with 179 additions and 35 deletions

View File

@ -100,6 +100,7 @@ end
target 'SessionMessagingKit' do
pod 'CryptoSwift', :inhibit_warnings => true
pod 'Curve25519Kit', :inhibit_warnings => true
pod 'PromiseKit', :inhibit_warnings => true
pod 'SwiftProtobuf', '~> 1.5.0', :inhibit_warnings => true
end
@ -121,6 +122,8 @@ target 'SessionSnodeKit' do
end
target 'SessionUtilities' do
pod 'CryptoSwift', :inhibit_warnings => true
pod 'Curve25519Kit', :inhibit_warnings => true
pod 'PromiseKit', :inhibit_warnings => true
end

View File

@ -332,6 +332,6 @@ SPEC CHECKSUMS:
YYImage: 6db68da66f20d9f169ceb94dfb9947c3867b9665
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: 4d6ed1d0ef2a98ce221ebfffc9ae860d4703ec47
PODFILE CHECKSUM: 2efffb9efc5ed9feaf8b2df90d8dee2d4685e7c2
COCOAPODS: 1.10.0.rc.1

2
Pods

@ -1 +1 @@
Subproject commit 855baeb2e72e3f90eb0cdcbc682162175db2bec8
Subproject commit 38df69dfa06ce734db625bdf39534d654528a916

View File

@ -0,0 +1,41 @@
import CryptoSwift
import SessionProtocolKit
import SessionUtilities
public extension ReceivingPipeline {
static func decryptWithSharedSenderKeys(envelope: SNProtoEnvelope, using transaction: Any) throws -> (plaintext: Data, senderPublicKey: String) {
// 1. ) Check preconditions
guard let groupPublicKey = envelope.source, Configuration.shared.storage.isClosedGroup(groupPublicKey) else {
throw Error.invalidGroupPublicKey
}
guard let data = envelope.content else {
throw Error.noData
}
guard let hexEncodedGroupPrivateKey = Configuration.shared.storage.getClosedGroupPrivateKey(for: groupPublicKey) else {
throw Error.noGroupPrivateKey
}
let groupPrivateKey = Data(hex: hexEncodedGroupPrivateKey)
let groupKeyPair = ECKeyPair(publicKey: Data(hex: groupPublicKey), privateKey: groupPrivateKey)
// 2. ) Parse the wrapper
let wrapper = try SNProtoClosedGroupCiphertextMessageWrapper.parseData(data)
let ivAndCiphertext = wrapper.ciphertext
let ephemeralPublicKey = wrapper.ephemeralPublicKey
// 3. ) Decrypt the data inside
guard let ephemeralSharedSecret = Curve25519.generateSharedSecret(fromPublicKey: ephemeralPublicKey, andKeyPair: groupKeyPair) else {
throw Error.sharedSecretGenerationFailed
}
let salt = "LOKI"
let symmetricKey = try HMAC(key: salt.bytes, variant: .sha256).authenticate(ephemeralSharedSecret.bytes)
let closedGroupCiphertextMessageAsData = try AESGCM.decrypt(ivAndCiphertext, with: Data(symmetricKey))
// 4. ) Parse the closed group ciphertext message
let closedGroupCiphertextMessage = ClosedGroupCiphertextMessage(_throws_with: closedGroupCiphertextMessageAsData)
let senderPublicKey = closedGroupCiphertextMessage.senderPublicKey.toHexString()
guard senderPublicKey != Configuration.shared.storage.getUserPublicKey() else { throw Error.selfSend }
// 5. ) Use the info inside the closed group ciphertext message to decrypt the actual message content
let plaintext = try SharedSenderKeys.decrypt(closedGroupCiphertextMessage.ivAndCiphertext, for: groupPublicKey,
senderPublicKey: senderPublicKey, keyIndex: UInt(closedGroupCiphertextMessage.keyIndex), using: transaction)
// 6. ) Return
return (plaintext, senderPublicKey)
}
}

View File

@ -4,10 +4,22 @@ public enum ReceivingPipeline {
public enum Error : LocalizedError {
case invalidMessage
// Shared sender keys
case invalidGroupPublicKey
case noData
case noGroupPrivateKey
case sharedSecretGenerationFailed
case selfSend
public var errorDescription: String? {
switch self {
case .invalidMessage: return "Invalid message."
// Shared sender keys
case .invalidGroupPublicKey: return "Invalid group public key."
case .noData: return "Received an empty envelope."
case .noGroupPrivateKey: return "Missing group private key."
case .sharedSecretGenerationFailed: return "Couldn't generate a shared secret."
case .selfSend: return "Message addressed at self."
}
}
}

View File

@ -0,0 +1,23 @@
import SessionProtocolKit
import SessionUtilities
public extension SendingPipeline {
static func encryptWithSignalProtocol(_ plaintext: Data, for publicKey: String, using transaction: Any) throws -> Data {
return Data()
}
static func encryptWithSharedSenderKeys(_ plaintext: Data, for groupPublicKey: String, using transaction: Any) throws -> Data {
// 1. ) Encrypt the data with the user's sender key
guard let userPublicKey = Configuration.shared.storage.getUserPublicKey() else {
SNLog("Couldn't find user key pair.")
throw Error.noUserPublicKey
}
let (ivAndCiphertext, keyIndex) = try SharedSenderKeys.encrypt(plaintext, for: groupPublicKey, senderPublicKey: userPublicKey, using: transaction)
let encryptedMessage = ClosedGroupCiphertextMessage(_throws_withIVAndCiphertext: ivAndCiphertext, senderPublicKey: Data(hex: userPublicKey), keyIndex: UInt32(keyIndex))
// 2. ) Encrypt the result for the group's public key to hide the sender public key and key index
let intermediate = try AESGCM.encrypt(encryptedMessage.serialized, for: groupPublicKey.removing05PrefixIfNeeded())
// 3. ) Wrap the result
return try SNProtoClosedGroupCiphertextMessageWrapper.builder(ciphertext: intermediate.ciphertext, ephemeralPublicKey: intermediate.ephemeralPublicKey).build().serializedData()
}
}

View File

@ -7,27 +7,27 @@ public enum SendingPipeline {
public enum Destination {
case contact(publicKey: String)
case closedGroup(publicKey: String)
case closedGroup(groupPublicKey: String)
case openGroup(channel: UInt64, server: String)
}
public enum Error : LocalizedError {
case invalidMessage
case protoConversionFailed
case protoSerializationFailed
case proofOfWorkCalculationFailed
case noUserPublicKey
public var errorDescription: String? {
switch self {
case .invalidMessage: return "Invalid message."
case .protoConversionFailed: return "Couldn't convert message to proto."
case .protoSerializationFailed: return "Couldn't serialize proto."
case .proofOfWorkCalculationFailed: return "Proof of work calculation failed."
case .noUserPublicKey: return "Couldn't find user key pair."
}
}
}
public static func send(_ message: Message, to destination: Destination) -> Promise<Void> {
public static func send(_ message: Message, to destination: Destination, using transaction: Any) -> Promise<Void> {
guard message.isValid else { return Promise(error: Error.invalidMessage) }
guard let proto = message.toProto() else { return Promise(error: Error.protoConversionFailed) }
let plaintext: Data
@ -35,9 +35,19 @@ public enum SendingPipeline {
plaintext = try proto.serializedData()
} catch {
SNLog("Couldn't serialize proto due to error: \(error).")
return Promise(error: Error.protoSerializationFailed)
return Promise(error: error)
}
let ciphertext: Data
do {
switch destination {
case .contact(let publicKey): ciphertext = try encryptWithSignalProtocol(plaintext, for: publicKey, using: transaction)
case .closedGroup(let groupPublicKey): ciphertext = try encryptWithSharedSenderKeys(plaintext, for: groupPublicKey, using: transaction)
case .openGroup(_, _): fatalError("Not implemented.")
}
} catch {
SNLog("Couldn't encrypt message for destination: \(destination) due to error: \(error).")
return Promise(error: error)
}
let ciphertext = plaintext // TODO: Encryption
let recipient = message.recipient!
let base64EncodedData = ciphertext.base64EncodedString()
guard let (timestamp, nonce) = ProofOfWork.calculate(ttl: ttl, publicKey: recipient, data: base64EncodedData) else {

View File

@ -4,5 +4,8 @@ public protocol SessionMessagingKitStorageProtocol {
func with(_ work: (Any) -> Void)
func getUserPublicKey() -> String?
func getOrGenerateRegistrationID(using transaction: Any) -> UInt32
func isClosedGroup(_ publicKey: String) -> Bool
func getClosedGroupPrivateKey(for publicKey: String) -> String?
}

View File

@ -0,0 +1,6 @@
import Foundation
internal enum Threading {
internal static let workQueue = DispatchQueue(label: "SessionMessagingKit.workQueue", qos: .userInitiated) // It's important that this is a serial queue
}

View File

@ -4,6 +4,7 @@ FOUNDATION_EXPORT double SessionProtocolKitVersionNumber;
FOUNDATION_EXPORT const unsigned char SessionProtocolKitVersionString[];
#import <SessionProtocolKit/AxolotlStore.h>
#import <SessionProtocolKit/ClosedGroupCiphertextMessage.h>
#import <SessionProtocolKit/NSData+OWS.h>
#import <SessionProtocolKit/NSObject+OWS.h>
#import <SessionProtocolKit/NSString+OWS.h>

View File

@ -27,14 +27,14 @@ public enum SharedSenderKeys {
}
// MARK: Private/Internal API
internal func generateRatchet(for groupPublicKey: String, senderPublicKey: String, using transaction: Any) -> ClosedGroupRatchet {
internal static func generateRatchet(for groupPublicKey: String, senderPublicKey: String, using transaction: Any) -> ClosedGroupRatchet {
let rootChainKey = Data.getSecureRandomData(ofSize: 32)!.toHexString()
let ratchet = ClosedGroupRatchet(chainKey: rootChainKey, keyIndex: 0, messageKeys: [])
Configuration.shared.storage.setClosedGroupRatchet(for: groupPublicKey, senderPublicKey: senderPublicKey, ratchet: ratchet, in: .current, using: transaction)
return ratchet
}
private func step(_ ratchet: ClosedGroupRatchet) throws -> ClosedGroupRatchet {
private static func step(_ ratchet: ClosedGroupRatchet) throws -> ClosedGroupRatchet {
let nextMessageKey = try HMAC(key: Data(hex: ratchet.chainKey).bytes, variant: .sha256).authenticate([ UInt8(1) ])
let nextChainKey = try HMAC(key: Data(hex: ratchet.chainKey).bytes, variant: .sha256).authenticate([ UInt8(2) ])
let nextKeyIndex = ratchet.keyIndex + 1
@ -43,7 +43,7 @@ public enum SharedSenderKeys {
}
/// - Note: Sync. Don't call from the main thread.
private func stepRatchetOnce(for groupPublicKey: String, senderPublicKey: String, using transaction: Any) throws -> ClosedGroupRatchet {
private static func stepRatchetOnce(for groupPublicKey: String, senderPublicKey: String, using transaction: Any) throws -> ClosedGroupRatchet {
#if DEBUG
assert(!Thread.isMainThread)
#endif
@ -63,7 +63,7 @@ public enum SharedSenderKeys {
}
/// - Note: Sync. Don't call from the main thread.
private func stepRatchet(for groupPublicKey: String, senderPublicKey: String, until targetKeyIndex: UInt, using transaction: Any, isRetry: Bool = false) throws -> ClosedGroupRatchet {
private static func stepRatchet(for groupPublicKey: String, senderPublicKey: String, until targetKeyIndex: UInt, using transaction: Any, isRetry: Bool = false) throws -> ClosedGroupRatchet {
#if DEBUG
assert(!Thread.isMainThread)
#endif
@ -100,7 +100,7 @@ public enum SharedSenderKeys {
}
// MARK: Public API
public func encrypt(_ plaintext: Data, for groupPublicKey: String, senderPublicKey: String, using transaction: Any) throws -> (ivAndCiphertext: Data, keyIndex: UInt) {
public static func encrypt(_ plaintext: Data, for groupPublicKey: String, senderPublicKey: String, using transaction: Any) throws -> (ivAndCiphertext: Data, keyIndex: UInt) {
let ratchet: ClosedGroupRatchet
do {
ratchet = try stepRatchetOnce(for: groupPublicKey, senderPublicKey: senderPublicKey, using: transaction)
@ -110,15 +110,15 @@ public enum SharedSenderKeys {
}
throw error
}
let iv = Data.getSecureRandomData(ofSize: SharedSenderKeys.ivSize)!
let gcm = GCM(iv: iv.bytes, tagLength: Int(SharedSenderKeys.gcmTagSize), mode: .combined)
let iv = Data.getSecureRandomData(ofSize: ivSize)!
let gcm = GCM(iv: iv.bytes, tagLength: Int(gcmTagSize), mode: .combined)
let messageKey = ratchet.messageKeys.last!
let aes = try AES(key: Data(hex: messageKey).bytes, blockMode: gcm, padding: .noPadding)
let ciphertext = try aes.encrypt(plaintext.bytes)
return (ivAndCiphertext: iv + Data(ciphertext), ratchet.keyIndex)
}
public func decrypt(_ ivAndCiphertext: Data, for groupPublicKey: String, senderPublicKey: String, keyIndex: UInt, using transaction: Any, isRetry: Bool = false) throws -> Data {
public static func decrypt(_ ivAndCiphertext: Data, for groupPublicKey: String, senderPublicKey: String, keyIndex: UInt, using transaction: Any, isRetry: Bool = false) throws -> Data {
let ratchet: ClosedGroupRatchet
do {
ratchet = try stepRatchet(for: groupPublicKey, senderPublicKey: senderPublicKey, until: keyIndex, using: transaction, isRetry: isRetry)
@ -132,9 +132,9 @@ public enum SharedSenderKeys {
throw error
}
}
let iv = ivAndCiphertext[0..<Int(SharedSenderKeys.ivSize)]
let ciphertext = ivAndCiphertext[Int(SharedSenderKeys.ivSize)...]
let gcm = GCM(iv: iv.bytes, tagLength: Int(SharedSenderKeys.gcmTagSize), mode: .combined)
let iv = ivAndCiphertext[0..<Int(ivSize)]
let ciphertext = ivAndCiphertext[Int(ivSize)...]
let gcm = GCM(iv: iv.bytes, tagLength: Int(gcmTagSize), mode: .combined)
let messageKeys = ratchet.messageKeys
let lastNMessageKeys: [String]
if messageKeys.count > 16 { // Pick an arbitrary number of message keys to try; this helps resolve issues caused by messages arriving out of order

View File

@ -1,14 +1,13 @@
import CryptoSwift
import Curve25519Kit
import SessionUtilities
internal enum AESGCM {
internal static let gcmTagSize: UInt = 16
internal static let ivSize: UInt = 12
public enum AESGCM {
public static let gcmTagSize: UInt = 16
public static let ivSize: UInt = 12
internal struct EncryptionResult { internal let ciphertext: Data, symmetricKey: Data, ephemeralPublicKey: Data }
public struct EncryptionResult { public let ciphertext: Data, symmetricKey: Data, ephemeralPublicKey: Data }
internal enum Error : LocalizedError {
public enum Error : LocalizedError {
case keyPairGenerationFailed
case sharedSecretGenerationFailed
@ -21,7 +20,7 @@ internal enum AESGCM {
}
/// - Note: Sync. Don't call from the main thread.
internal static func decrypt(_ ivAndCiphertext: Data, with symmetricKey: Data) throws -> Data {
public static func decrypt(_ ivAndCiphertext: Data, with symmetricKey: Data) throws -> Data {
if Thread.isMainThread {
#if DEBUG
preconditionFailure("It's illegal to call decrypt(_:usingAESGCMWithSymmetricKey:) from the main thread.")
@ -35,7 +34,7 @@ internal enum AESGCM {
}
/// - Note: Sync. Don't call from the main thread.
internal static func encrypt(_ plaintext: Data, with symmetricKey: Data) throws -> Data {
public static func encrypt(_ plaintext: Data, with symmetricKey: Data) throws -> Data {
if Thread.isMainThread {
#if DEBUG
preconditionFailure("It's illegal to call encrypt(_:usingAESGCMWithSymmetricKey:) from the main thread.")
@ -49,7 +48,7 @@ internal enum AESGCM {
}
/// - Note: Sync. Don't call from the main thread.
internal static func encrypt(_ plaintext: Data, for hexEncodedX25519PublicKey: String) throws -> EncryptionResult {
public static func encrypt(_ plaintext: Data, for hexEncodedX25519PublicKey: String) throws -> EncryptionResult {
if Thread.isMainThread {
#if DEBUG
preconditionFailure("It's illegal to call encrypt(_:forSnode:) from the main thread.")

View File

@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
#import <Curve25519Kit/Curve25519.h>
NS_ASSUME_NONNULL_BEGIN
@interface ECKeyPair (Utilities)
- (ECKeyPair *)initWithPublicKey:(NSData *)publicKey privateKey:(NSData *)privateKey;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,17 @@
#import "ECKeyPair+Utilities.h"
NS_ASSUME_NONNULL_BEGIN
@implementation ECKeyPair (Utilities)
- (ECKeyPair *)initWithPublicKey:(NSData *)snPublicKey privateKey:(NSData *)snPrivateKey
{
ECKeyPair *keyPair = [[ECKeyPair alloc] init];
[keyPair setValue:snPublicKey forKey:@"publicKey"];
[keyPair setValue:snPrivateKey forKey:@"privateKey"];
return keyPair;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -4,3 +4,4 @@ FOUNDATION_EXPORT double SessionUtilitiesVersionNumber;
FOUNDATION_EXPORT const unsigned char SessionUtilitiesVersionString[];
#import <SessionUtilities/NSDate+Timestamp.h>
#import <SessionUtilities/ECKeyPair+Utilities.h>

View File

@ -588,6 +588,12 @@
C31FFE57254A5FFE00F19441 /* KeyPairUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31FFE56254A5FFE00F19441 /* KeyPairUtilities.swift */; };
C329FEEC24F7277900B1C64C /* LightModeSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEEB24F7277900B1C64C /* LightModeSheet.swift */; };
C329FEEF24F7743F00B1C64C /* UIViewController+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */; };
C3471ECB2555356A00297E91 /* SendingPipeline+Encryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3471ECA2555356A00297E91 /* SendingPipeline+Encryption.swift */; };
C3471ED42555386B00297E91 /* AESGCM.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D72553860B00C340D1 /* AESGCM.swift */; };
C3471F4225553A4D00297E91 /* Threading.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3471F4125553A4D00297E91 /* Threading.swift */; };
C3471F4C25553AB000297E91 /* ReceivingPipeline+Decryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3471F4B25553AB000297E91 /* ReceivingPipeline+Decryption.swift */; };
C3471F5625553E1100297E91 /* ECKeyPair+Utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C3471F5525553DA000297E91 /* ECKeyPair+Utilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
C3471F6825553E7600297E91 /* ECKeyPair+Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C3471F6725553E7600297E91 /* ECKeyPair+Utilities.m */; };
C34C8F7423A7830B00D82669 /* SpaceMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */; };
C353F8F9244809150011121A /* PNOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C353F8F8244809150011121A /* PNOptionView.swift */; };
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0524456447009433A8 /* PNModeVC.swift */; };
@ -636,7 +642,6 @@
C3C2A5DE2553860B00C340D1 /* String+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D22553860900C340D1 /* String+Utilities.swift */; };
C3C2A5DF2553860B00C340D1 /* Promise+Delaying.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D32553860900C340D1 /* Promise+Delaying.swift */; };
C3C2A5E02553860B00C340D1 /* Threading.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D42553860A00C340D1 /* Threading.swift */; };
C3C2A5E32553860B00C340D1 /* AESGCM.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D72553860B00C340D1 /* AESGCM.swift */; };
C3C2A5E42553860B00C340D1 /* Data+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D82553860B00C340D1 /* Data+Utilities.swift */; };
C3C2A67D255388CC00C340D1 /* SessionUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C3C2A67B255388CC00C340D1 /* SessionUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
C3C2A680255388CC00C340D1 /* SessionUtilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A679255388CC00C340D1 /* SessionUtilities.framework */; };
@ -1582,6 +1587,11 @@
C31FFE56254A5FFE00F19441 /* KeyPairUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPairUtilities.swift; sourceTree = "<group>"; };
C329FEEB24F7277900B1C64C /* LightModeSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightModeSheet.swift; sourceTree = "<group>"; };
C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Utilities.swift"; sourceTree = "<group>"; };
C3471ECA2555356A00297E91 /* SendingPipeline+Encryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SendingPipeline+Encryption.swift"; sourceTree = "<group>"; };
C3471F4125553A4D00297E91 /* Threading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Threading.swift; sourceTree = "<group>"; };
C3471F4B25553AB000297E91 /* ReceivingPipeline+Decryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ReceivingPipeline+Decryption.swift"; sourceTree = "<group>"; };
C3471F5525553DA000297E91 /* ECKeyPair+Utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ECKeyPair+Utilities.h"; sourceTree = "<group>"; };
C3471F6725553E7600297E91 /* ECKeyPair+Utilities.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "ECKeyPair+Utilities.m"; sourceTree = "<group>"; };
C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = "<group>"; };
C353F8F8244809150011121A /* PNOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNOptionView.swift; sourceTree = "<group>"; };
C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = "<group>"; };
@ -3194,7 +3204,9 @@
isa = PBXGroup;
children = (
C300A5F12554B09800555489 /* SendingPipeline.swift */,
C3471ECA2555356A00297E91 /* SendingPipeline+Encryption.swift */,
C300A5FB2554B0A000555489 /* ReceivingPipeline.swift */,
C3471F4B25553AB000297E91 /* ReceivingPipeline+Decryption.swift */,
);
path = Pipelines;
sourceTree = "<group>";
@ -3252,6 +3264,7 @@
children = (
C3BBE0C62554F1570050F1E3 /* FixedWidthInteger+BigEndian.swift */,
C3BBE0B42554F0E10050F1E3 /* ProofOfWork.swift */,
C3471F4125553A4D00297E91 /* Threading.swift */,
);
path = Utilities;
sourceTree = "<group>";
@ -3285,7 +3298,6 @@
C3C2A5CD255385F300C340D1 /* Utilities */ = {
isa = PBXGroup;
children = (
C3C2A5D72553860B00C340D1 /* AESGCM.swift */,
C3C2A5D82553860B00C340D1 /* Data+Utilities.swift */,
C3C2A5D32553860900C340D1 /* Promise+Delaying.swift */,
C3C2A5CF2553860700C340D1 /* Promise+Hashing.swift */,
@ -3300,9 +3312,12 @@
isa = PBXGroup;
children = (
C3C2A68B255388D500C340D1 /* Meta */,
C3C2A5D72553860B00C340D1 /* AESGCM.swift */,
C3C2A5D12553860800C340D1 /* Array+Description.swift */,
C3C2ABD12553C6C900C340D1 /* Data+SecureRandom.swift */,
C3C2A5D52553860A00C340D1 /* Dictionary+Description.swift */,
C3471F5525553DA000297E91 /* ECKeyPair+Utilities.h */,
C3471F6725553E7600297E91 /* ECKeyPair+Utilities.m */,
C3C2A5BC255385EE00C340D1 /* HTTP.swift */,
C3C2A5D92553860B00C340D1 /* JSON.swift */,
C3C2A5CE2553860700C340D1 /* Logging.swift */,
@ -3763,6 +3778,7 @@
buildActionMask = 2147483647;
files = (
C300A63B2554B72200555489 /* NSDate+Timestamp.h in Headers */,
C3471F5625553E1100297E91 /* ECKeyPair+Utilities.h in Headers */,
C3C2A67D255388CC00C340D1 /* SessionUtilities.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -4857,7 +4873,6 @@
C3C2A5DF2553860B00C340D1 /* Promise+Delaying.swift in Sources */,
C3C2A5DC2553860B00C340D1 /* Promise+Threading.swift in Sources */,
C3C2A5C4255385EE00C340D1 /* OnionRequestAPI+Encryption.swift in Sources */,
C3C2A5E32553860B00C340D1 /* AESGCM.swift in Sources */,
C3C2A5DE2553860B00C340D1 /* String+Utilities.swift in Sources */,
C3C2A5DB2553860B00C340D1 /* Promise+Hashing.swift in Sources */,
C3C2A5E42553860B00C340D1 /* Data+Utilities.swift in Sources */,
@ -4874,8 +4889,10 @@
C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */,
C3BBE0A82554D4DE0050F1E3 /* JSON.swift in Sources */,
C3C2ABD22553C6C900C340D1 /* Data+SecureRandom.swift in Sources */,
C3471F6825553E7600297E91 /* ECKeyPair+Utilities.m in Sources */,
C3BBE0AA2554D4DE0050F1E3 /* Dictionary+Description.swift in Sources */,
C3C2AC2E2553CBEB00C340D1 /* String+Trimming.swift in Sources */,
C3471ED42555386B00297E91 /* AESGCM.swift in Sources */,
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */,
C3BBE0A92554D4DE0050F1E3 /* HTTP.swift in Sources */,
C300A60D2554B31900555489 /* Logging.swift in Sources */,
@ -4887,7 +4904,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C3471F4C25553AB000297E91 /* ReceivingPipeline+Decryption.swift in Sources */,
C300A5D32554B05A00555489 /* TypingIndicator.swift in Sources */,
C3471ECB2555356A00297E91 /* SendingPipeline+Encryption.swift in Sources */,
C300A5F22554B09800555489 /* SendingPipeline.swift in Sources */,
C3C2A74D2553A39700C340D1 /* VisibleMessage.swift in Sources */,
C3C2A7562553A3AB00C340D1 /* VisibleMessage+Quote.swift in Sources */,
@ -4900,6 +4919,7 @@
C3C2A7712553A41E00C340D1 /* ControlMessage.swift in Sources */,
C300A5BD2554B00D00555489 /* ReadReceipt.swift in Sources */,
C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */,
C3471F4225553A4D00297E91 /* Threading.swift in Sources */,
C300A5DD2554B06600555489 /* ClosedGroupUpdate.swift in Sources */,
C300A5E72554B07300555489 /* ExpirationTimerUpdate.swift in Sources */,
C3C2A75F2553A3C500C340D1 /* VisibleMessage+LinkPreview.swift in Sources */,

View File

@ -6,14 +6,10 @@
<dict>
<key>CarthageVersion</key>
<string>0.36.0</string>
<key>DateTime</key>
<string>Fri Nov 6 03:20:05 UTC 2020</string>
<key>OSXVersion</key>
<string>10.15.6</string>
<key>WebRTCCommit</key>
<string>1445d719bf05280270e9f77576f80f973fd847f8 M73</string>
<key>XCodeVersion</key>
<string>1200.1210</string>
</dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>