Merge branch 'dev' of https://github.com/loki-project/loki-messenger-ios into sync-closed-group
This commit is contained in:
commit
be20236a78
2
Pods
2
Pods
|
@ -1 +1 @@
|
|||
Subproject commit 6fae72d48c06c35c8219ebfc58116450c473b8f1
|
||||
Subproject commit c171262c7dec75b47e89cde64b6ab2908b200c6b
|
|
@ -142,13 +142,13 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
|
|||
* ================
|
||||
*/
|
||||
|
||||
if (self.contactThread.sessionResetState != .requestReceived) {
|
||||
if (self.contactThread.sessionResetStatus != .requestReceived) {
|
||||
let message = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: self.contactThread, messageType: .typeLokiSessionResetInProgress)
|
||||
message.save(with: transaction)
|
||||
|
||||
// Loki: We have initiated a session reset
|
||||
print("[Loki] Session reset initiated.")
|
||||
self.contactThread.sessionResetState = .initiated
|
||||
self.contactThread.sessionResetStatus = .initiated
|
||||
self.contactThread.save(with: transaction)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1227,7 +1227,7 @@ typedef enum : NSUInteger {
|
|||
}
|
||||
}
|
||||
[[[TSInfoMessage alloc] initWithTimestamp:NSDate.ows_millisecondTimeStamp inThread:thread messageType:TSInfoMessageTypeLokiSessionResetInProgress] save];
|
||||
thread.sessionResetState = TSContactThreadSessionResetStateRequestReceived;
|
||||
thread.sessionResetStatus = LKSessionResetStatusRequestReceived;
|
||||
[thread save];
|
||||
[thread removeAllSessionRestoreDevicesWithTransaction:nil];
|
||||
}
|
||||
|
|
|
@ -3,25 +3,16 @@
|
|||
//
|
||||
|
||||
#import "TSThread.h"
|
||||
#import <SignalMetadataKit/SignalMetadataKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Loki: Session reset state
|
||||
typedef NS_ENUM(NSInteger, TSContactThreadSessionResetState) {
|
||||
// No ongoing session reset
|
||||
TSContactThreadSessionResetStateNone,
|
||||
// We initiated a session reset
|
||||
TSContactThreadSessionResetStateInitiated,
|
||||
// We received a session reset
|
||||
TSContactThreadSessionResetStateRequestReceived,
|
||||
};
|
||||
|
||||
extern NSString *const TSContactThreadPrefix;
|
||||
|
||||
@interface TSContactThread : TSThread
|
||||
|
||||
// Loki: The current session reset state for this thread
|
||||
@property (atomic) TSContactThreadSessionResetState sessionResetState;
|
||||
@property (atomic) LKSessionResetStatus sessionResetStatus;
|
||||
@property (atomic, readonly) NSArray<NSString *> *sessionRestoreDevices;
|
||||
|
||||
@property (nonatomic) BOOL hasDismissedOffers;
|
||||
|
|
|
@ -26,7 +26,7 @@ NSString *const TSContactThreadPrefix = @"c";
|
|||
self = [super initWithUniqueId:uniqueIdentifier];
|
||||
|
||||
// No session reset ongoing
|
||||
_sessionResetState = TSContactThreadSessionResetStateNone;
|
||||
_sessionResetStatus = LKSessionResetStatusNone;
|
||||
_sessionRestoreDevices = @[];
|
||||
|
||||
return self;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import PromiseKit
|
||||
import SignalMetadataKit
|
||||
|
||||
/// Base class for `LokiFileServerAPI` and `LokiPublicChatAPI`.
|
||||
public class LokiDotNetAPI : NSObject {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import PromiseKit
|
||||
import SignalMetadataKit
|
||||
|
||||
internal class LokiFileServerProxy : LokiHTTPClient {
|
||||
private let server: String
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import PromiseKit
|
||||
import SignalMetadataKit
|
||||
|
||||
internal class LokiSnodeProxy : LokiHTTPClient {
|
||||
private let target: LokiAPITarget
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
import CryptoSwift
|
||||
import Curve25519Kit
|
||||
|
||||
@objc public final class DiffieHellman : NSObject {
|
||||
|
||||
@objc public class DiffieHellmanError : NSError { // Not called `Error` for Obj-C interoperablity
|
||||
|
||||
@objc public static let decryptionFailed = DiffieHellmanError(domain: "DiffieHellmanErrorDomain", code: 1, userInfo: [ NSLocalizedDescriptionKey : "Couldn't decrypt data." ])
|
||||
}
|
||||
|
||||
public static let ivLength: Int32 = 16;
|
||||
|
||||
private override init() { }
|
||||
|
||||
public static func encrypt(_ plainTextData: Data, using symmetricKey: Data) throws -> Data {
|
||||
let iv = Randomness.generateRandomBytes(ivLength)!
|
||||
let ivBytes = [UInt8](iv)
|
||||
let symmetricKeyBytes = [UInt8](symmetricKey)
|
||||
let messageBytes = [UInt8](plainTextData)
|
||||
let blockMode = CBC(iv: ivBytes)
|
||||
let aes = try AES(key: symmetricKeyBytes, blockMode: blockMode)
|
||||
let cipherText = try aes.encrypt(messageBytes)
|
||||
let ivAndCipher = ivBytes + cipherText
|
||||
return Data(bytes: ivAndCipher, count: ivAndCipher.count)
|
||||
}
|
||||
|
||||
public static func encrypt(_ plainTextData: Data, publicKey: Data, privateKey: Data) throws -> Data {
|
||||
let symmetricKey = try Curve25519.generateSharedSecret(fromPublicKey: publicKey, privateKey: privateKey)
|
||||
return try encrypt(plainTextData, using: symmetricKey)
|
||||
}
|
||||
|
||||
public static func decrypt(_ encryptedData: Data, using symmetricKey: Data) throws -> Data {
|
||||
let symmetricKeyBytes = [UInt8](symmetricKey)
|
||||
guard encryptedData.count >= ivLength else { throw DiffieHellmanError.decryptionFailed }
|
||||
let ivBytes = [UInt8](encryptedData[..<ivLength])
|
||||
let cipherBytes = [UInt8](encryptedData[ivLength...])
|
||||
let blockMode = CBC(iv: ivBytes)
|
||||
let aes = try AES(key: symmetricKeyBytes, blockMode: blockMode)
|
||||
let decrypted = try aes.decrypt(cipherBytes)
|
||||
return Data(bytes: decrypted, count: decrypted.count)
|
||||
}
|
||||
|
||||
public static func decrypt(_ encryptedData: Data, publicKey: Data, privateKey: Data) throws -> Data {
|
||||
let symmetricKey = try Curve25519.generateSharedSecret(fromPublicKey: publicKey, privateKey: privateKey)
|
||||
return try decrypt(encryptedData, using: symmetricKey)
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
import CryptoSwift
|
||||
import Curve25519Kit
|
||||
|
||||
private extension String {
|
||||
|
||||
// Convert hex string to Data
|
||||
fileprivate var hexData: Data {
|
||||
var hex = self
|
||||
var data = Data()
|
||||
while(hex.count > 0) {
|
||||
let subIndex = hex.index(hex.startIndex, offsetBy: 2)
|
||||
let c = String(hex[..<subIndex])
|
||||
hex = String(hex[subIndex...])
|
||||
var ch: UInt32 = 0
|
||||
Scanner(string: c).scanHexInt32(&ch)
|
||||
var char = UInt8(ch)
|
||||
data.append(&char, count: 1)
|
||||
}
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
/// A fallback session cipher which uses the the recipients public key to encrypt data
|
||||
@objc public final class FallBackSessionCipher : NSObject {
|
||||
// The pubkey hex string of the recipient
|
||||
private let recipientId: String
|
||||
// The identity manager
|
||||
private let identityKeyStore: OWSIdentityManager
|
||||
|
||||
// The length of the iv
|
||||
private let ivLength: Int32 = 16;
|
||||
|
||||
// The pubkey representation of the hex id
|
||||
private lazy var recipientPubKey: Data = {
|
||||
var recipientId = self.recipientId
|
||||
|
||||
// We need to check here if the id is prefix with '05'
|
||||
// We only need to do this if the length is 66
|
||||
if (recipientId.count == 66 && recipientId.hasPrefix("05")) {
|
||||
recipientId = recipientId.substring(from: 2)
|
||||
}
|
||||
|
||||
return recipientId.hexData
|
||||
}()
|
||||
|
||||
// Our identity key
|
||||
private lazy var userIdentityKeyPair: ECKeyPair? = identityKeyStore.identityKeyPair()
|
||||
|
||||
// A symmetric key used for encryption and decryption
|
||||
private lazy var symmetricKey: Data? = {
|
||||
guard let userIdentityKeyPair = userIdentityKeyPair else { return nil }
|
||||
|
||||
return try? Curve25519.generateSharedSecret(fromPublicKey: recipientPubKey, privateKey: userIdentityKeyPair.privateKey)
|
||||
}()
|
||||
|
||||
/// Create a FallBackSessionCipher.
|
||||
/// This is a very basic cipher and should only be used in special cases such as Friend Requests.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - recipientId: The pubkey string of the recipient
|
||||
/// - identityKeyStore: The identity manager
|
||||
@objc public init(recipientId: String, identityKeyStore: OWSIdentityManager) {
|
||||
self.recipientId = recipientId
|
||||
self.identityKeyStore = identityKeyStore
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Encrypt a message
|
||||
///
|
||||
/// - Parameter message: The message to encrypt
|
||||
/// - Returns: The encypted message or `nil` if it failed
|
||||
@objc public func encrypt(message: Data) -> Data? {
|
||||
guard let symmetricKey = symmetricKey else { return nil }
|
||||
do {
|
||||
return try DiffieHellman.encrypt(message, using: symmetricKey)
|
||||
} catch {
|
||||
Logger.warn("FallBackSessionCipher: Failed to encrypt message")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrypt a message
|
||||
///
|
||||
/// - Parameter message: The message to decrypt
|
||||
/// - Returns: The decrypted message or `nil` if it failed
|
||||
@objc public func decrypt(message: Data) -> Data? {
|
||||
guard let symmetricKey = symmetricKey else { return nil }
|
||||
do {
|
||||
return try DiffieHellman.decrypt(message, using: symmetricKey)
|
||||
} catch {
|
||||
Logger.warn("FallBackSessionCipher: Failed to decrypt message")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
// Loki: Refer to Docs/SessionReset.md for explanations
|
||||
|
||||
#import <AxolotlKit/SessionCipher.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern NSString *const kNSNotificationName_SessionAdopted;
|
||||
extern NSString *const kNSNotificationKey_ContactPubKey;
|
||||
|
||||
@interface SessionCipher (Loki)
|
||||
|
||||
/**
|
||||
Decrypt the given `CipherMessage`.
|
||||
This function is a wrapper around `throws_decrypt:protocolContext:` and adds on the custom Loki session handling.
|
||||
Refer to SignalServiceKit/Loki/Docs/SessionReset.md for an overview of how it works.
|
||||
|
||||
@param whisperMessage The cipher message.
|
||||
@param protocolContext The protocol context (a `YapDatabaseReadWriteTransaction`).
|
||||
@return The decrypted data.
|
||||
*/
|
||||
- (NSData *)throws_lokiDecrypt:(id<CipherMessage>)whisperMessage protocolContext:(nullable id)protocolContext NS_SWIFT_UNAVAILABLE("throws Obj-C exceptions");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,63 @@
|
|||
import Foundation
|
||||
import SignalMetadataKit
|
||||
|
||||
@objc(LKSessionResetImplementation)
|
||||
public class LokiSessionResetImplementation : NSObject, SessionResetProtocol {
|
||||
private let storage: OWSPrimaryStorage
|
||||
|
||||
@objc public init(storage: OWSPrimaryStorage) {
|
||||
self.storage = storage
|
||||
}
|
||||
|
||||
enum Errors : Error {
|
||||
case invalidPreKey
|
||||
case preKeyIDsDontMatch
|
||||
}
|
||||
|
||||
public func validatePreKeyForFriendRequestAcceptance(for recipientID: String, whisperMessage: CipherMessage, protocolContext: Any?) throws {
|
||||
guard let transaction = protocolContext as? YapDatabaseReadWriteTransaction else {
|
||||
print("[Loki] Could not verify friend request acceptance pre key because an invalid transaction was provided.")
|
||||
return
|
||||
}
|
||||
guard let preKeyMessage = whisperMessage as? PreKeyWhisperMessage else { return }
|
||||
guard let storedPreKey = storage.getPreKey(forContact: recipientID, transaction: transaction) else {
|
||||
print("[Loki] Received a friend request from a public key for which no pre key bundle was created.")
|
||||
throw Errors.invalidPreKey
|
||||
}
|
||||
guard storedPreKey.id == preKeyMessage.prekeyID else {
|
||||
print("[Loki] Received a `PreKeyWhisperMessage` (friend request acceptance) from an unknown source.")
|
||||
throw Errors.preKeyIDsDontMatch
|
||||
}
|
||||
}
|
||||
|
||||
public func getSessionResetStatus(for recipientID: String, protocolContext: Any?) -> SessionResetStatus {
|
||||
guard let transaction = protocolContext as? YapDatabaseReadWriteTransaction else {
|
||||
print("[Loki] Could not get session reset status for \(recipientID) because an invalid transaction was provided.")
|
||||
return .none
|
||||
}
|
||||
guard let thread = TSContactThread.getWithContactId(recipientID, transaction: transaction) else { return .none }
|
||||
return thread.sessionResetStatus
|
||||
}
|
||||
|
||||
public func onNewSessionAdopted(for recipientID: String, protocolContext: Any?) {
|
||||
guard let transaction = protocolContext as? YapDatabaseReadWriteTransaction else {
|
||||
Logger.warn("[Loki] Cannot handle new session adoption because an invalid transaction was provided.")
|
||||
return
|
||||
}
|
||||
guard !recipientID.isEmpty else { return }
|
||||
guard let thread = TSContactThread.getWithContactId(recipientID, transaction: transaction) else {
|
||||
Logger.debug("[Loki] A new session was adopted but the thread couldn't be found for: \(recipientID).")
|
||||
return
|
||||
}
|
||||
// If the current user initiated the reset then send back an empty message to acknowledge the completion of the session reset
|
||||
if thread.sessionResetStatus == .initiated {
|
||||
let emptyMessage = EphemeralMessage(in: thread)
|
||||
SSKEnvironment.shared.messageSender.sendPromise(message: emptyMessage).retainUntilComplete()
|
||||
}
|
||||
// Show session reset done message
|
||||
TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: thread, messageType: .typeLokiSessionResetDone).save(with: transaction)
|
||||
// Clear the session reset status
|
||||
thread.sessionResetStatus = .none
|
||||
thread.save(with: transaction)
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
#import "OWSPrimaryStorage+SessionStore.h"
|
||||
#import "OWSPrimaryStorage+SignedPreKeyStore.h"
|
||||
#import "OWSPrimaryStorage.h"
|
||||
#import "SessionCipher+Loki.h"
|
||||
#import "SSKEnvironment.h"
|
||||
#import "SignalRecipient.h"
|
||||
#import "TSAccountManager.h"
|
||||
|
@ -84,6 +83,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
|
|||
@interface OWSMessageDecrypter ()
|
||||
|
||||
@property (nonatomic, readonly) OWSPrimaryStorage *primaryStorage;
|
||||
@property (nonatomic, readonly) LKSessionResetImplementation *sessionResetImplementation;
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||
|
||||
@end
|
||||
|
@ -101,7 +101,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
|
|||
}
|
||||
|
||||
_primaryStorage = primaryStorage;
|
||||
|
||||
_sessionResetImplementation = [[LKSessionResetImplementation alloc] initWithStorage:primaryStorage];
|
||||
_dbConnection = primaryStorage.newDatabaseConnection;
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
@ -336,7 +336,8 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
|
|||
}
|
||||
|
||||
NSString *recipientId = envelope.source;
|
||||
FallBackSessionCipher *cipher = [[FallBackSessionCipher alloc] initWithRecipientId:recipientId identityKeyStore:self.identityManager];
|
||||
ECKeyPair *identityKeyPair = self.identityManager.identityKeyPair;
|
||||
FallBackSessionCipher *cipher = [[FallBackSessionCipher alloc] initWithRecipientId:recipientId privateKey:identityKeyPair.privateKey];
|
||||
|
||||
NSData *_Nullable plaintextData = [[cipher decryptWithMessage:encryptedData] removePadding];
|
||||
if (!plaintextData) {
|
||||
|
@ -425,16 +426,22 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
|
|||
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
@try {
|
||||
id<CipherMessage> cipherMessage = cipherMessageBlock(encryptedData);
|
||||
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:self.primaryStorage
|
||||
preKeyStore:self.primaryStorage
|
||||
signedPreKeyStore:self.primaryStorage
|
||||
identityKeyStore:self.identityManager
|
||||
recipientId:recipientId
|
||||
deviceId:deviceId];
|
||||
LKSessionCipher *cipher = [[LKSessionCipher alloc]
|
||||
initWithSessionResetImplementation:self.sessionResetImplementation
|
||||
sessionStore:self.primaryStorage
|
||||
preKeyStore:self.primaryStorage
|
||||
signedPreKeyStore:self.primaryStorage
|
||||
identityKeyStore:self.primaryStorage
|
||||
recipientID:recipientId
|
||||
deviceID:deviceId];
|
||||
|
||||
// plaintextData may be nil for some envelope types.
|
||||
NSData *_Nullable plaintextData = [[cipher throws_lokiDecrypt:cipherMessage protocolContext:transaction] removePadding];
|
||||
|
||||
NSError *error = nil;
|
||||
NSData *_Nullable decryptedData = [cipher decrypt:cipherMessage protocolContext:transaction error:&error];
|
||||
// Throw if we got an error
|
||||
SCKRaiseIfExceptionWrapperError(error);
|
||||
NSData *_Nullable plaintextData = decryptedData != nil ? [decryptedData removePadding] : nil;
|
||||
|
||||
OWSMessageDecryptResult *result = [OWSMessageDecryptResult resultWithEnvelopeData:envelopeData
|
||||
plaintextData:plaintextData
|
||||
source:envelope.source
|
||||
|
@ -482,11 +489,13 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
|
|||
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSError *cipherError;
|
||||
SMKSecretSessionCipher *_Nullable cipher =
|
||||
[[SMKSecretSessionCipher alloc] initWithSessionStore:self.primaryStorage
|
||||
[[SMKSecretSessionCipher alloc] initWithSessionResetImplementation:self.sessionResetImplementation
|
||||
sessionStore:self.primaryStorage
|
||||
preKeyStore:self.primaryStorage
|
||||
signedPreKeyStore:self.primaryStorage
|
||||
identityStore:self.identityManager
|
||||
error:&cipherError];
|
||||
|
||||
if (cipherError || !cipher) {
|
||||
OWSFailDebug(@"Could not create secret session cipher: %@.", cipherError);
|
||||
cipherError = EnsureDecryptError(cipherError, @"Could not create secret session cipher.");
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#import "OWSSyncGroupsMessage.h"
|
||||
#import "OWSSyncGroupsRequestMessage.h"
|
||||
#import "ProfileManagerProtocol.h"
|
||||
#import "SessionCipher+Loki.h"
|
||||
#import "SSKEnvironment.h"
|
||||
#import "TSAccountManager.h"
|
||||
#import "TSAttachment.h"
|
||||
|
@ -53,11 +52,11 @@
|
|||
#import "TSQuotedMessage.h"
|
||||
#import <SignalCoreKit/Cryptography.h>
|
||||
#import <SignalCoreKit/NSDate+OWS.h>
|
||||
#import <SignalMetadataKit/SignalMetadataKit-Swift.h>
|
||||
#import <SignalServiceKit/NSObject+Casting.h>
|
||||
#import <SignalServiceKit/SignalRecipient.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <YapDatabase/YapDatabase.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import "OWSDispatch.h"
|
||||
#import "OWSBatchMessageProcessor.h"
|
||||
#import "OWSQueues.h"
|
||||
|
@ -94,9 +93,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
_primaryStorage = primaryStorage;
|
||||
_dbConnection = primaryStorage.newDatabaseConnection;
|
||||
_incomingMessageFinder = [[OWSIncomingMessageFinder alloc] initWithPrimaryStorage:primaryStorage];
|
||||
|
||||
// Loki: Observe session changes
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleNewSessionAdopted:) name:kNSNotificationName_SessionAdopted object:nil];
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
|
@ -1184,7 +1180,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[self.primaryStorage archiveAllSessionsForContact:hexEncodedPublicKey protocolContext:transaction];
|
||||
|
||||
// Loki: Set our session reset state
|
||||
thread.sessionResetState = TSContactThreadSessionResetStateRequestReceived;
|
||||
thread.sessionResetStatus = LKSessionResetStatusRequestReceived;
|
||||
[thread saveWithTransaction:transaction];
|
||||
|
||||
// Loki: Send an empty message to trigger the session reset code for both parties
|
||||
|
@ -2050,36 +2046,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
}
|
||||
|
||||
# pragma mark - Loki Session Handling
|
||||
|
||||
- (void)handleNewSessionAdopted:(NSNotification *)notification {
|
||||
NSString *hexEncodedPublicKey = notification.userInfo[kNSNotificationKey_ContactPubKey];
|
||||
if (hexEncodedPublicKey.length == 0) { return; }
|
||||
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
TSContactThread *thread = [TSContactThread getThreadWithContactId:hexEncodedPublicKey transaction:transaction];
|
||||
if (thread == nil) {
|
||||
NSLog(@"[Loki] A new session was adopted but the thread couldn't be found for: %@.", hexEncodedPublicKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the current user initiated the reset then send back an empty message to acknowledge the completion of the session reset
|
||||
if (thread.sessionResetState == TSContactThreadSessionResetStateInitiated) {
|
||||
LKEphemeralMessage *emptyMessage = [[LKEphemeralMessage alloc] initInThread:thread];
|
||||
[self.messageSenderJobQueue addMessage:emptyMessage transaction:transaction];
|
||||
}
|
||||
|
||||
// Show session reset done message
|
||||
[[[TSInfoMessage alloc] initWithTimestamp:NSDate.ows_millisecondTimeStamp
|
||||
inThread:thread
|
||||
messageType:TSInfoMessageTypeLokiSessionResetDone] saveWithTransaction:transaction];
|
||||
|
||||
// Clear the session reset state
|
||||
thread.sessionResetState = TSContactThreadSessionResetStateNone;
|
||||
[thread saveWithTransaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1941,7 +1941,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
NSString *recipientId = recipient.recipientId;
|
||||
TSOutgoingMessage *message = messageSend.message;
|
||||
|
||||
FallBackSessionCipher *cipher = [[FallBackSessionCipher alloc] initWithRecipientId:recipientId identityKeyStore:self.identityManager];
|
||||
ECKeyPair *identityKeyPair = self.identityManager.identityKeyPair;
|
||||
FallBackSessionCipher *cipher = [[FallBackSessionCipher alloc] initWithRecipientId:recipientId privateKey:identityKeyPair.privateKey];
|
||||
|
||||
// This will return nil if encryption failed
|
||||
NSData *_Nullable serializedMessage = [cipher encryptWithMessage:[plainText paddedMessageBody]];
|
||||
|
|
Loading…
Reference in New Issue