mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Closes #236
- Sublassing errors in case of expected behaviour - When receiving a new message that was using a previously unknown identity key, we search for any other messages that are encrypted with the new accepted key and decrypt those too. - Addressing some of the warnings we had before.
This commit is contained in:
parent
4cb3231bb1
commit
eff589af93
16 changed files with 189 additions and 107 deletions
4
Podfile
4
Podfile
|
@ -4,10 +4,10 @@ inhibit_all_warnings!
|
|||
|
||||
link_with ["Signal", "SignalTests"]
|
||||
|
||||
pod 'SocketRocket', :git => 'https://github.com/square/SocketRocket.git', :commit => 'd0585af165'
|
||||
pod 'SocketRocket', :git => 'https://github.com/square/SocketRocket.git', :commit => '954750c018'
|
||||
pod 'OpenSSL', '~> 1.0.110'
|
||||
pod 'libPhoneNumber-iOS', '~> 0.7'
|
||||
pod 'AxolotlKit', '~> 0.3'
|
||||
pod 'AxolotlKit', '~> 0.5'
|
||||
pod 'PastelogKit', '~> 1.2'
|
||||
pod 'TwistedOakCollapsingFutures','~> 1.0'
|
||||
pod 'YapDatabase/SQLCipher'
|
||||
|
|
12
Podfile.lock
12
Podfile.lock
|
@ -21,7 +21,7 @@ PODS:
|
|||
- AFNetworking/UIKit (2.5.0):
|
||||
- AFNetworking/NSURLConnection
|
||||
- AFNetworking/NSURLSession
|
||||
- AxolotlKit (0.3):
|
||||
- AxolotlKit (0.5):
|
||||
- 25519 (~> 1.8)
|
||||
- HKDFKit (~> 0.0.3)
|
||||
- ProtocolBuffers (~> 1.9.2)
|
||||
|
@ -59,14 +59,14 @@ PODS:
|
|||
|
||||
DEPENDENCIES:
|
||||
- AFNetworking (~> 2.5)
|
||||
- AxolotlKit (~> 0.3)
|
||||
- AxolotlKit (~> 0.5)
|
||||
- DJWActionSheet
|
||||
- JSQMessagesViewController (from `https://github.com/dtsbourg/JSQMessagesViewController`, branch `JSignalQ`)
|
||||
- libPhoneNumber-iOS (~> 0.7)
|
||||
- Mantle (~> 1.5)
|
||||
- OpenSSL (~> 1.0.110)
|
||||
- PastelogKit (~> 1.2)
|
||||
- SocketRocket (from `https://github.com/square/SocketRocket.git`, commit `d0585af165`)
|
||||
- SocketRocket (from `https://github.com/square/SocketRocket.git`, commit `954750c018`)
|
||||
- SSKeychain
|
||||
- TwistedOakCollapsingFutures (~> 1.0)
|
||||
- YapDatabase/SQLCipher
|
||||
|
@ -76,7 +76,7 @@ EXTERNAL SOURCES:
|
|||
:branch: JSignalQ
|
||||
:git: https://github.com/dtsbourg/JSQMessagesViewController
|
||||
SocketRocket:
|
||||
:commit: d0585af165
|
||||
:commit: 954750c018
|
||||
:git: https://github.com/square/SocketRocket.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
|
@ -84,13 +84,13 @@ CHECKOUT OPTIONS:
|
|||
:commit: ed9858bd6df609bba83b21a029701cbf13682981
|
||||
:git: https://github.com/dtsbourg/JSQMessagesViewController
|
||||
SocketRocket:
|
||||
:commit: d0585af165
|
||||
:commit: 954750c018
|
||||
:git: https://github.com/square/SocketRocket.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
25519: 601ffb5d258aa33d642062d6fa4096db210e02e7
|
||||
AFNetworking: 0f54cb5d16ce38c1b76948faffb8d5fb705021c7
|
||||
AxolotlKit: 19a7a6482e3deb6621e0f81a1733f60301802d40
|
||||
AxolotlKit: eec4d036d5b021258dc8b6b0212f3c04edeaf15b
|
||||
CocoaLumberjack: 205769c032b5fef85b92472046bcc8b7e7c8a817
|
||||
DJWActionSheet: d88b302d7c29523e1e9fb9b62cfac46f59bb90d9
|
||||
HKDFKit: 5998cf1bbb611e7ecc6bd3eaaef8c7a7da7be949
|
||||
|
|
2
Pods
2
Pods
|
@ -1 +1 @@
|
|||
Subproject commit 94599a4564daeec5315e99bfae427f798925b0b2
|
||||
Subproject commit 53c2e1ee892acb702b48f16ec8e63a0ea4d0fff4
|
|
@ -353,6 +353,7 @@
|
|||
B68112ED1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112EC1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m */; };
|
||||
B684A46D19C3446200B11029 /* PushManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B684A46C19C3446200B11029 /* PushManagerTest.m */; };
|
||||
B6850E5A1995A4710068E715 /* whisperFake.cer in Resources */ = {isa = PBXBuildFile; fileRef = B6850E591995A4710068E715 /* whisperFake.cer */; };
|
||||
B68B0E8A1A54284100DE8A02 /* TSInvalidIdentityKeyErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68B0E891A54284100DE8A02 /* TSInvalidIdentityKeyErrorMessage.m */; };
|
||||
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
|
||||
B6A3EB4B1A423B3800B2236B /* TSAttachmentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A3EB4A1A423B3800B2236B /* TSAttachmentAdapter.m */; };
|
||||
B6AE33BD1A1EB121003DF39D /* GroupModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B6AE33BC1A1EB121003DF39D /* GroupModel.m */; };
|
||||
|
@ -519,7 +520,7 @@
|
|||
FCAC963C19FEF9280046DFC5 /* SignalsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC963B19FEF9280046DFC5 /* SignalsViewController.m */; };
|
||||
FCAC964019FEF99A0046DFC5 /* InboxTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC963E19FEF99A0046DFC5 /* InboxTableViewCell.m */; };
|
||||
FCAC964119FEF99A0046DFC5 /* InboxTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FCAC963F19FEF99A0046DFC5 /* InboxTableViewCell.xib */; };
|
||||
FCAC965119FF0A6E0046DFC5 /* MessagesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC965019FF0A6E0046DFC5 /* MessagesViewController.m */; };
|
||||
FCAC965119FF0A6E0046DFC5 /* MessagesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC965019FF0A6E0046DFC5 /* MessagesViewController.m */; settings = {COMPILER_FLAGS = "-Wno-receiver-is-weak"; }; };
|
||||
FCAFC33F1A0F948F00AE5136 /* ActionContactDetailCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAFC33E1A0F948F00AE5136 /* ActionContactDetailCell.m */; };
|
||||
FCB11D8A1A1284BB002F93FB /* SettingsTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCB11D891A1284BB002F93FB /* SettingsTableViewCell.m */; };
|
||||
FCB11D8C1A129A76002F93FB /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCB11D8B1A129A76002F93FB /* CoreMedia.framework */; };
|
||||
|
@ -986,6 +987,9 @@
|
|||
B68112EC1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "JSQMessagesCollectionViewCell+menuBarItems.m"; path = "views/JSQMessagesCollectionViewCell+menuBarItems.m"; sourceTree = "<group>"; };
|
||||
B684A46C19C3446200B11029 /* PushManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PushManagerTest.m; path = Signal/test/push/PushManagerTest.m; sourceTree = SOURCE_ROOT; };
|
||||
B6850E591995A4710068E715 /* whisperFake.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = whisperFake.cer; sourceTree = "<group>"; };
|
||||
B68B0E881A54284100DE8A02 /* TSInvalidIdentityKeyErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInvalidIdentityKeyErrorMessage.h; sourceTree = "<group>"; };
|
||||
B68B0E891A54284100DE8A02 /* TSInvalidIdentityKeyErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInvalidIdentityKeyErrorMessage.m; sourceTree = "<group>"; };
|
||||
B68B0E8D1A542AD700DE8A02 /* TSErrorMessage_privateConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSErrorMessage_privateConstructor.h; sourceTree = "<group>"; };
|
||||
B69CD25019773E79005CE69A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
|
||||
B6A3EB491A423B3800B2236B /* TSAttachmentAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachmentAdapter.h; sourceTree = "<group>"; };
|
||||
B6A3EB4A1A423B3800B2236B /* TSAttachmentAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentAdapter.m; sourceTree = "<group>"; };
|
||||
|
@ -2375,7 +2379,10 @@
|
|||
B6B096051A1D25ED008BFAA6 /* TSCall.h */,
|
||||
B6B096061A1D25ED008BFAA6 /* TSCall.m */,
|
||||
B6B096071A1D25ED008BFAA6 /* TSErrorMessage.h */,
|
||||
B68B0E8D1A542AD700DE8A02 /* TSErrorMessage_privateConstructor.h */,
|
||||
B6B096081A1D25ED008BFAA6 /* TSErrorMessage.m */,
|
||||
B68B0E881A54284100DE8A02 /* TSInvalidIdentityKeyErrorMessage.h */,
|
||||
B68B0E891A54284100DE8A02 /* TSInvalidIdentityKeyErrorMessage.m */,
|
||||
B6B0960B1A1D25ED008BFAA6 /* TSIncomingMessage.h */,
|
||||
B6B0960C1A1D25ED008BFAA6 /* TSIncomingMessage.m */,
|
||||
B6B0960D1A1D25ED008BFAA6 /* TSInfoMessage.h */,
|
||||
|
@ -3144,6 +3151,7 @@
|
|||
76EB05EC18170B33006006FC /* CallState.m in Sources */,
|
||||
76EB05D218170B33006006FC /* ZrtpInitiator.m in Sources */,
|
||||
76EB05E018170B33006006FC /* NetworkStream.m in Sources */,
|
||||
B68B0E8A1A54284100DE8A02 /* TSInvalidIdentityKeyErrorMessage.m in Sources */,
|
||||
B6B0968A1A1D25ED008BFAA6 /* TSStorageManager+SessionStore.m in Sources */,
|
||||
FCFA64B71A24F6730007FB87 /* UIFont+OWS.m in Sources */,
|
||||
B6B096891A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.m in Sources */,
|
||||
|
|
|
@ -156,15 +156,20 @@
|
|||
-(BOOL) application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation {
|
||||
if ([url.scheme isEqualToString:@"sgnl"]) {
|
||||
if ([url.host hasPrefix:@"verify"] && ![TSAccountManager isRegistered]) {
|
||||
UIViewController *controller = [[Environment getCurrent].signUpFlowNavigationController.childViewControllers lastObject];
|
||||
if ([controller isKindOfClass:[CodeVerificationViewController class]]) {
|
||||
CodeVerificationViewController *cvvc = (CodeVerificationViewController*)controller;
|
||||
NSString *verificationCode = [url.path substringFromIndex:1];
|
||||
id signupController = [Environment getCurrent].signUpFlowNavigationController;
|
||||
if ([signupController isKindOfClass:[UINavigationController class]]) {
|
||||
UINavigationController *navController = (UINavigationController*)signupController;
|
||||
UIViewController *controller = [navController.childViewControllers lastObject];
|
||||
if ([controller isKindOfClass:[CodeVerificationViewController class]]) {
|
||||
CodeVerificationViewController *cvvc = (CodeVerificationViewController*)controller;
|
||||
NSString *verificationCode = [url.path substringFromIndex:1];
|
||||
|
||||
cvvc.challengeTextField.text = verificationCode;
|
||||
[cvvc verifyChallengeAction:nil];
|
||||
} else{
|
||||
DDLogWarn(@"Not the verification view controller we expected. Got %@ instead", NSStringFromClass(controller.class));
|
||||
}
|
||||
|
||||
cvvc.challengeTextField.text = verificationCode;
|
||||
[cvvc verifyChallengeAction:nil];
|
||||
} else{
|
||||
DDLogWarn(@"Not the verification view controller we expected. Got %@ instead", NSStringFromClass(controller.class));
|
||||
}
|
||||
} else{
|
||||
DDLogWarn(@"Application opened with an unknown URL action: %@", url.host);
|
||||
|
@ -200,7 +205,7 @@
|
|||
}
|
||||
|
||||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
|
||||
|
||||
|
||||
if ([self isRedPhonePush:userInfo]) {
|
||||
[self application:application didReceiveRemoteNotification:userInfo];
|
||||
} else {
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
*/
|
||||
@interface ResponderSessionDescriptor : NSObject
|
||||
|
||||
@property (nonatomic,readonly) int32_t interopVersion;
|
||||
@property (nonatomic,readonly) NSUInteger interopVersion;
|
||||
@property (nonatomic,readonly) in_port_t relayUdpPort;
|
||||
@property (nonatomic,readonly) int64_t sessionId;
|
||||
@property (nonatomic,readonly) NSString* relayServerName;
|
||||
@property (nonatomic,readonly) PhoneNumber* initiatorNumber;
|
||||
|
||||
+(ResponderSessionDescriptor*)responderSessionDescriptorWithInteropVersion:(int32_t)interopVersion
|
||||
+(ResponderSessionDescriptor*)responderSessionDescriptorWithInteropVersion:(NSUInteger)interopVersion
|
||||
andRelayUdpPort:(in_port_t)relayUdpPort
|
||||
andSessionId:(int64_t)sessionId
|
||||
andRelayServerName:(NSString*)relayServerName
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
@synthesize initiatorNumber;
|
||||
@synthesize interopVersion;
|
||||
|
||||
+(ResponderSessionDescriptor*)responderSessionDescriptorWithInteropVersion:(int32_t)interopVersion
|
||||
+(ResponderSessionDescriptor*)responderSessionDescriptorWithInteropVersion:(NSUInteger)interopVersion
|
||||
andRelayUdpPort:(in_port_t)relayUdpPort
|
||||
andSessionId:(int64_t)sessionId
|
||||
andRelayServerName:(NSString*)relayServerName
|
||||
|
@ -72,8 +72,8 @@
|
|||
checkOperation(parsedPayload.initiator != nil);
|
||||
checkOperation(parsedPayload.serverName != nil);
|
||||
|
||||
unsigned int interopVersion = parsedPayload.version;
|
||||
unsigned long long sessionId = parsedPayload.sessionId;
|
||||
NSUInteger interopVersion = parsedPayload.version;
|
||||
int64_t sessionId = (int64_t)parsedPayload.sessionId;
|
||||
in_port_t relayUdpPort = (in_port_t)parsedPayload.port;
|
||||
NSString* relayServerName = parsedPayload.serverName;
|
||||
PhoneNumber* phoneNumber = [PhoneNumber phoneNumberFromE164:parsedPayload.initiator];
|
||||
|
@ -106,11 +106,11 @@
|
|||
}
|
||||
|
||||
-(NSString*) description {
|
||||
return [NSString stringWithFormat:@"relay name: %@, relay port: %d, session id: %llud, interop version: %d",
|
||||
return [NSString stringWithFormat:@"relay name: %@, relay port: %d, session id: %llud, interop version: %lu",
|
||||
relayServerName,
|
||||
relayUdpPort,
|
||||
sessionId,
|
||||
interopVersion];
|
||||
(unsigned long)interopVersion];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
//
|
||||
|
||||
#import "TSMessage.h"
|
||||
|
||||
#import "IncomingPushMessageSignal.pb.h"
|
||||
|
||||
@interface TSErrorMessage : TSMessage
|
||||
|
@ -28,15 +27,6 @@ typedef NS_ENUM(int32_t, TSErrorMessageType){
|
|||
+ (instancetype)invalidKeyExceptionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
|
||||
+ (instancetype)missingSessionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
|
||||
|
||||
/**
|
||||
* Methods on TSErrorMessageWrongTrustedIdentityKey error types
|
||||
*/
|
||||
|
||||
+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
|
||||
|
||||
- (void)acceptNewIdentityKey;
|
||||
- (NSString*)newIdentityKey;
|
||||
|
||||
@property (nonatomic, readonly) TSErrorMessageType errorType;
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,29 +8,12 @@
|
|||
|
||||
#import "TSErrorMessage.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "TSStorageManager+IdentityKeyStore.h"
|
||||
#import <AxolotlKit/PreKeyWhisperMessage.h>
|
||||
#import <AxolotlKit/NSData+keyVersionByte.h>
|
||||
#import "TSMessagesManager.h"
|
||||
#import "TSFingerprintGenerator.h"
|
||||
|
||||
@interface TSErrorMessage()
|
||||
@property NSData *pushSignal;
|
||||
@end
|
||||
#import "TSErrorMessage_privateConstructor.h"
|
||||
|
||||
@implementation TSErrorMessage
|
||||
|
||||
- (instancetype)initForUnknownIdentityKeyWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread incomingPushSignal:(NSData*)signal{
|
||||
self = [self initWithTimestamp:timestamp inThread:thread failedMessageType:TSErrorMessageWrongTrustedIdentityKey];
|
||||
|
||||
if (self) {
|
||||
_pushSignal = signal;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread failedMessageType:(TSErrorMessageType)errorMessageType{
|
||||
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread failedMessageType:(TSErrorMessageType)errorMessageType {
|
||||
self = [super initWithTimestamp:timestamp inThread:thread messageBody:nil attachments:nil];
|
||||
|
||||
if (self) {
|
||||
|
@ -83,42 +66,8 @@
|
|||
return [[self alloc] initWithSignal:signal transaction:transaction failedMessageType:TSErrorMessageInvalidKeyException];
|
||||
}
|
||||
|
||||
+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:preKeyMessage.source transaction:transaction];
|
||||
TSErrorMessage *errorMessage = [[self alloc] initForUnknownIdentityKeyWithTimestamp:preKeyMessage.timestamp inThread:contactThread incomingPushSignal:preKeyMessage.data];
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
+ (instancetype)missingSessionWithSignal:(IncomingPushMessageSignal*)signal withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
|
||||
return [[self alloc] initWithSignal:signal transaction:transaction failedMessageType:TSErrorMessageNoSession];
|
||||
}
|
||||
|
||||
- (void)acceptNewIdentityKey{
|
||||
if (_errorType != TSErrorMessageWrongTrustedIdentityKey || !_pushSignal) {
|
||||
return;
|
||||
}
|
||||
|
||||
TSStorageManager *storage = [TSStorageManager sharedManager];
|
||||
IncomingPushMessageSignal *signal = [IncomingPushMessageSignal parseFromData:_pushSignal];
|
||||
PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:signal.message];
|
||||
NSData *newKey = [message.identityKey removeKeyType];
|
||||
|
||||
[storage saveRemoteIdentity:newKey recipientId:signal.source];
|
||||
|
||||
[[TSMessagesManager sharedManager] handleMessageSignal:signal];
|
||||
//TODO: Decrypt any other messages encrypted with that new identity key automatically.
|
||||
}
|
||||
|
||||
- (NSString *)newIdentityKey{
|
||||
if (_errorType != TSErrorMessageWrongTrustedIdentityKey || !_pushSignal) {
|
||||
return @"";
|
||||
}
|
||||
|
||||
IncomingPushMessageSignal *signal = [IncomingPushMessageSignal parseFromData:_pushSignal];
|
||||
PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:signal.message];
|
||||
NSData *identityKey = [message.identityKey removeKeyType];
|
||||
|
||||
return [TSFingerprintGenerator getFingerprintForDisplay:identityKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// TSErrorMessage_privateConstructor.h
|
||||
// Signal
|
||||
//
|
||||
// Created by Frederic Jacobs on 31/12/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSErrorMessage.h"
|
||||
|
||||
@interface TSErrorMessage ()
|
||||
|
||||
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread failedMessageType:(TSErrorMessageType)errorMessageType NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property NSData *pushSignal;
|
||||
|
||||
@end
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// TSInvalidIdentityKeyErrorMessage.h
|
||||
// Signal
|
||||
//
|
||||
// Created by Frederic Jacobs on 31/12/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSErrorMessage.h"
|
||||
|
||||
@interface TSInvalidIdentityKeyErrorMessage : TSErrorMessage
|
||||
|
||||
+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction;
|
||||
|
||||
- (void)acceptNewIdentityKey;
|
||||
- (NSString*)newIdentityKey;
|
||||
|
||||
@end
|
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// TSInvalidIdentityKeyErrorMessage.m
|
||||
// Signal
|
||||
//
|
||||
// Created by Frederic Jacobs on 31/12/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
#import <YapDatabase/YapDatabaseView.h>
|
||||
|
||||
#import "TSInvalidIdentityKeyErrorMessage.h"
|
||||
#import "TSErrorMessage_privateConstructor.h"
|
||||
#import "TSDatabaseView.h"
|
||||
#import "TSStorageManager.h"
|
||||
#import "TSStorageManager+IdentityKeyStore.h"
|
||||
#import <AxolotlKit/PreKeyWhisperMessage.h>
|
||||
#import <AxolotlKit/NSData+keyVersionByte.h>
|
||||
#import "TSMessagesManager.h"
|
||||
#import "TSFingerprintGenerator.h"
|
||||
|
||||
@implementation TSInvalidIdentityKeyErrorMessage
|
||||
|
||||
- (instancetype)initForUnknownIdentityKeyWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread incomingPushSignal:(NSData*)signal{
|
||||
self = [self initWithTimestamp:timestamp inThread:thread failedMessageType:TSErrorMessageWrongTrustedIdentityKey];
|
||||
|
||||
if (self) {
|
||||
self.pushSignal = signal;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:preKeyMessage.source transaction:transaction];
|
||||
TSInvalidIdentityKeyErrorMessage *errorMessage = [[self alloc] initForUnknownIdentityKeyWithTimestamp:preKeyMessage.timestamp inThread:contactThread incomingPushSignal:preKeyMessage.data];
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
- (void)acceptNewIdentityKey{
|
||||
if (self.errorType != TSErrorMessageWrongTrustedIdentityKey || !self.pushSignal) {
|
||||
return;
|
||||
}
|
||||
|
||||
TSStorageManager *storage = [TSStorageManager sharedManager];
|
||||
IncomingPushMessageSignal *signal = [IncomingPushMessageSignal parseFromData:self.pushSignal];
|
||||
PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:signal.message];
|
||||
NSData *newKey = [message.identityKey removeKeyType];
|
||||
|
||||
[storage saveRemoteIdentity:newKey recipientId:signal.source];
|
||||
|
||||
[[TSMessagesManager sharedManager] handleMessageSignal:signal];
|
||||
|
||||
__block NSMutableSet *messagesToDecrypt = [NSMutableSet set];
|
||||
|
||||
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[transaction ext:TSMessageDatabaseViewExtensionName]enumerateKeysAndObjectsInGroup:self.uniqueThreadId withOptions:NSEnumerationReverse usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) {
|
||||
TSInteraction *interaction = (TSInteraction*)object;
|
||||
|
||||
DDLogVerbose(@"Interaction type: %@", interaction.description);
|
||||
|
||||
if ([interaction isKindOfClass:[TSInvalidIdentityKeyErrorMessage class]]) {
|
||||
TSInvalidIdentityKeyErrorMessage *invalidKeyMessage = (TSInvalidIdentityKeyErrorMessage*)interaction;
|
||||
IncomingPushMessageSignal *invalidMessageSignal = [IncomingPushMessageSignal parseFromData:invalidKeyMessage.pushSignal];
|
||||
PreKeyWhisperMessage *pkwm = [[PreKeyWhisperMessage alloc] initWithData:invalidMessageSignal.message];
|
||||
NSData *newKeyCandidate = [pkwm.identityKey removeKeyType];
|
||||
|
||||
if ([newKeyCandidate isEqualToData:newKey]) {
|
||||
[messagesToDecrypt addObject:invalidMessageSignal];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}];
|
||||
|
||||
for (IncomingPushMessageSignal *aSignal in messagesToDecrypt) {
|
||||
[[TSMessagesManager sharedManager] handleMessageSignal:aSignal];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)newIdentityKey{
|
||||
if (self.errorType != TSErrorMessageWrongTrustedIdentityKey || !self.pushSignal) {
|
||||
return @"";
|
||||
}
|
||||
|
||||
IncomingPushMessageSignal *signal = [IncomingPushMessageSignal parseFromData:self.pushSignal];
|
||||
PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:signal.message];
|
||||
NSData *identityKey = [message.identityKey removeKeyType];
|
||||
|
||||
return [TSFingerprintGenerator getFingerprintForDisplay:identityKey];
|
||||
}
|
||||
|
||||
@end
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#import "TSIncomingMessage.h"
|
||||
#import "TSErrorMessage.h"
|
||||
#import "TSInvalidIdentityKeyErrorMessage.h"
|
||||
#import "TSInfoMessage.h"
|
||||
|
||||
#import "TSStorageManager+keyingMaterial.h"
|
||||
|
@ -305,7 +306,7 @@
|
|||
} else if ([exception.name isEqualToString:InvalidVersionException]){
|
||||
errorMessage = [TSErrorMessage invalidVersionWithSignal:signal withTransaction:transaction];
|
||||
} else if ([exception.name isEqualToString:UntrustedIdentityKeyException]){
|
||||
errorMessage = [TSErrorMessage untrustedKeyWithSignal:signal withTransaction:transaction];
|
||||
errorMessage = [TSInvalidIdentityKeyErrorMessage untrustedKeyWithSignal:signal withTransaction:transaction];
|
||||
} else {
|
||||
errorMessage = [TSErrorMessage corruptedMessageWithSignal:signal withTransaction:transaction];
|
||||
}
|
||||
|
|
|
@ -17,17 +17,17 @@ typedef NS_ENUM(NSInteger, TSMACType) {
|
|||
TSHMACSHA256AttachementType = 3
|
||||
};
|
||||
|
||||
+(NSMutableData*) generateRandomBytes:(int)numberBytes;
|
||||
+(NSMutableData*) generateRandomBytes:(NSUInteger)numberBytes;
|
||||
|
||||
#pragma mark SHA and HMAC methods
|
||||
|
||||
+(NSData*) computeSHA256:(NSData *)data truncatedToBytes:(int)truncatedBytes;
|
||||
+(NSData*) computeSHA256:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes;
|
||||
+(NSString*)truncatedSHA1Base64EncodedWithoutPadding:(NSString*)string;
|
||||
+(NSString*)computeSHA1DigestForString:(NSString*)input;
|
||||
|
||||
+(NSData*) computeSHA256HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey;
|
||||
+(NSData*) computeSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey;
|
||||
+(NSData*) truncatedSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(int)bytes;
|
||||
+(NSData*) truncatedSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(NSUInteger)bytes;
|
||||
|
||||
+(NSData*) decryptAppleMessagePayload:(NSData*)payload withSignalingKey:(NSString*)signalingKeyString;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
|
||||
#pragma mark random bytes methods
|
||||
+(NSMutableData*) generateRandomBytes:(int)numberBytes {
|
||||
+(NSMutableData*) generateRandomBytes:(NSUInteger)numberBytes {
|
||||
/* used to generate db master key, and to generate signaling key, both at install */
|
||||
NSMutableData* randomBytes = [NSMutableData dataWithLength:numberBytes];
|
||||
int err = 0;
|
||||
|
@ -72,7 +72,7 @@
|
|||
}
|
||||
|
||||
#pragma mark SHA256
|
||||
+(NSData*) computeSHA256:(NSData *)data truncatedToBytes:(int)truncatedBytes {
|
||||
+(NSData*) computeSHA256:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes {
|
||||
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
|
||||
CC_SHA256(data.bytes, (unsigned int)data.length, digest);
|
||||
return [[NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH] subdataWithRange:NSMakeRange(0, truncatedBytes)];
|
||||
|
@ -103,11 +103,11 @@
|
|||
}
|
||||
|
||||
|
||||
+(NSData*) truncatedSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(int)bytes{
|
||||
+(NSData*) truncatedSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(NSUInteger)bytes{
|
||||
return [[Cryptography computeSHA1HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)];
|
||||
}
|
||||
|
||||
+(NSData*) truncatedSHA256HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(int)bytes{
|
||||
+(NSData*) truncatedSHA256HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(NSUInteger)bytes{
|
||||
return [[Cryptography computeSHA256HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)];
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#import "TSMessageAdapter.h"
|
||||
#import "TSErrorMessage.h"
|
||||
#import "TSInvalidIdentityKeyErrorMessage.h"
|
||||
#import "TSIncomingMessage.h"
|
||||
#import "TSInteraction.h"
|
||||
#import "TSAttachmentAdapter.h"
|
||||
|
@ -543,14 +544,15 @@ typedef enum : NSUInteger {
|
|||
DDLogWarn(@"Currently unsupported");
|
||||
}
|
||||
}
|
||||
|
||||
break;}
|
||||
}
|
||||
break;
|
||||
case TSErrorMessageAdapter:
|
||||
[self handleErrorMessageTap:(TSErrorMessage*)interaction];
|
||||
break;
|
||||
case TSInfoMessageAdapter:
|
||||
break;
|
||||
|
||||
case TSCallAdapter:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -581,8 +583,9 @@ typedef enum : NSUInteger {
|
|||
}
|
||||
|
||||
- (void)handleErrorMessageTap:(TSErrorMessage*)message{
|
||||
if (message.errorType == TSErrorMessageWrongTrustedIdentityKey) {
|
||||
NSString *newKeyFingerprint = [message newIdentityKey];
|
||||
if ([message isKindOfClass:[TSInvalidIdentityKeyErrorMessage class]]) {
|
||||
TSInvalidIdentityKeyErrorMessage *errorMessage = (TSInvalidIdentityKeyErrorMessage*)message;
|
||||
NSString *newKeyFingerprint = [errorMessage newIdentityKey];
|
||||
NSString *messageString = [NSString stringWithFormat:@"Do you want to accept %@'s new identity key: %@", _thread.name, newKeyFingerprint];
|
||||
NSArray *actions = @[@"Accept new identity key", @"Copy new identity key to pasteboard"];
|
||||
|
||||
|
@ -598,9 +601,8 @@ typedef enum : NSUInteger {
|
|||
} else {
|
||||
switch (tappedButtonIndex) {
|
||||
case 0:
|
||||
[message acceptNewIdentityKey];
|
||||
[errorMessage acceptNewIdentityKey];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
[[UIPasteboard generalPasteboard] setString:newKeyFingerprint];
|
||||
break;
|
||||
|
@ -862,7 +864,7 @@ typedef enum : NSUInteger {
|
|||
#pragma mark - UICollectionView DataSource
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
|
||||
{
|
||||
NSInteger numberOfMessages = [self.messageMappings numberOfItemsInSection:section];
|
||||
NSInteger numberOfMessages = (NSInteger)[self.messageMappings numberOfItemsInSection:(NSUInteger)section];
|
||||
return numberOfMessages;
|
||||
}
|
||||
|
||||
|
@ -873,8 +875,8 @@ typedef enum : NSUInteger {
|
|||
NSParameterAssert(viewTransaction != nil);
|
||||
NSParameterAssert(self.messageMappings != nil);
|
||||
NSParameterAssert(indexPath != nil);
|
||||
NSUInteger row = indexPath.row;
|
||||
NSUInteger section = indexPath.section;
|
||||
NSUInteger row = (NSUInteger)indexPath.row;
|
||||
NSUInteger section = (NSUInteger)indexPath.section;
|
||||
NSUInteger numberOfItemsInSection = [self.messageMappings numberOfItemsInSection:section];
|
||||
|
||||
NSAssert(row < numberOfItemsInSection, @"Cannot fetch message because row %d is >= numberOfItemsInSection %d", (int)row, (int)numberOfItemsInSection);
|
||||
|
|
Loading…
Reference in a new issue