New fingerprint format

In coordination with Desktop and Android, iOS will be using all-numeric
fingerprints, aka "Safety Numbers".

Furthermore, the concept of verifying one identity and then the other
has been removed. Instead we ask users to exchange a single number, or
scan a single QR code. These credentials are built by combining the
users identities.

// FREEBIE
pull/1/head
Michael Kirk 9 years ago
parent ce1aa04b61
commit c1ade86a8b

@ -24,6 +24,7 @@
45C6A09A1D2F029B007D8AC0 /* TSMessageTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C6A0991D2F029B007D8AC0 /* TSMessageTest.m */; };
45D7243F1D67899F00E0CA54 /* OWSDeviceProvisionerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 45D7243E1D67899F00E0CA54 /* OWSDeviceProvisionerTest.m */; };
51520592F83F2440F2DE4D67 /* libPods-TSKitiOSTestApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B8362AB8E280E0F64352F08A /* libPods-TSKitiOSTestApp.a */; };
6323E1F7730289398452E5C5 /* OWSFingerprintTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6323E02A33682A8838FE3F27 /* OWSFingerprintTest.m */; };
6323E339D5B8F4CB77EB3ED4 /* SignalRecipientTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6323E3E540CF763D71DACB59 /* SignalRecipientTest.m */; };
B6273DD61C13A2E500738558 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B6273DD51C13A2E500738558 /* main.m */; };
B6273DD91C13A2E500738558 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B6273DD81C13A2E500738558 /* AppDelegate.m */; };
@ -63,6 +64,7 @@
45A856AB1D220BFF0056CD4D /* TSAttributesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttributesTest.m; sourceTree = "<group>"; };
45C6A0991D2F029B007D8AC0 /* TSMessageTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSMessageTest.m; path = ../../../tests/Messages/Interactions/TSMessageTest.m; sourceTree = "<group>"; };
45D7243E1D67899F00E0CA54 /* OWSDeviceProvisionerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSDeviceProvisionerTest.m; path = ../../../tests/Devices/OWSDeviceProvisionerTest.m; sourceTree = "<group>"; };
6323E02A33682A8838FE3F27 /* OWSFingerprintTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSFingerprintTest.m; path = ../../../tests/Security/OWSFingerprintTest.m; sourceTree = "<group>"; };
6323E3E540CF763D71DACB59 /* SignalRecipientTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SignalRecipientTest.m; path = ../../tests/Contacts/SignalRecipientTest.m; sourceTree = "<group>"; };
B6273DD11C13A2E500738558 /* TSKitiOSTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TSKitiOSTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
B6273DD51C13A2E500738558 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@ -143,6 +145,14 @@
path = ../../../tests/Util;
sourceTree = "<group>";
};
454AB2261D89CC6E006325C9 /* Security */ = {
isa = PBXGroup;
children = (
6323E02A33682A8838FE3F27 /* OWSFingerprintTest.m */,
);
name = Security;
sourceTree = "<group>";
};
459850BF1D22C6C4006FFEDB /* Contacts */ = {
isa = PBXGroup;
children = (
@ -251,6 +261,7 @@
459850BF1D22C6C4006FFEDB /* Contacts */,
45D7243D1D67894100E0CA54 /* Devices */,
45C6A0971D2F0254007D8AC0 /* Messages */,
454AB2261D89CC6E006325C9 /* Security */,
45458B6D1CC342B600A02153 /* Storage */,
45458B721CC342B600A02153 /* Util */,
B6273DF01C13A2E500738558 /* Info.plist */,
@ -313,6 +324,7 @@
TargetAttributes = {
B6273DD01C13A2E500738558 = {
CreatedOnToolsVersion = 7.1.1;
DevelopmentTeam = U68MSDN6DR;
};
B6273DE91C13A2E500738558 = {
CreatedOnToolsVersion = 7.1.1;
@ -483,6 +495,7 @@
45458B7C1CC342B600A02153 /* MessagePaddingTests.m in Sources */,
45A856AC1D220BFF0056CD4D /* TSAttributesTest.m in Sources */,
6323E339D5B8F4CB77EB3ED4 /* SignalRecipientTest.m in Sources */,
6323E1F7730289398452E5C5 /* OWSFingerprintTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -603,6 +616,7 @@
baseConfigurationReference = 31DFDA8F9523F5B15EA2376B /* Pods-TSKitiOSTestApp.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = U68MSDN6DR;
INFOPLIST_FILE = TSKitiOSTestApp/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.TSKitiOSTestApp;
@ -615,6 +629,7 @@
baseConfigurationReference = 1A50A62A8930EE2BC9B8AC11 /* Pods-TSKitiOSTestApp.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = U68MSDN6DR;
INFOPLIST_FILE = TSKitiOSTestApp/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.TSKitiOSTestApp;

@ -1,23 +1,23 @@
# Assumes you've installed protobug-objc
# see: https://github.com/alexeyxo/protobuf-objc
all: signal_service_proto provisioning_protos
signal_service_proto:
protoc \
PROTOC=protoc \
--plugin=/usr/local/bin/proto-gen-objc \
--proto_path="${HOME}/src/WhisperSystems/protobuf-objc/src/compiler/" \
--proto_path="${HOME}/src/WhisperSystems/protobuf-objc/src/compiler/google/protobuf/" \
--proto_path='./' \
--objc_out=../src/Messages/ \
--proto_path='./'
all: signal_service_proto provisioning_protos fingerprint_protos
signal_service_proto: OWSSignalServiceProtos.proto
$(PROTOC) --objc_out=../src/Messages/ \
OWSSignalServiceProtos.proto
provisioning_protos:
protoc \
--plugin=/usr/local/bin/proto-gen-objc \
--proto_path="${HOME}/src/WhisperSystems/protobuf-objc/src/compiler/" \
--proto_path="${HOME}/src/WhisperSystems/protobuf-objc/src/compiler/google/protobuf/" \
--proto_path='./' \
--objc_out=../src/Devices/ \
provisioning_protos: OWSProvisioningProtos.proto
$(PROTOC) --objc_out=../src/Devices/ \
OWSProvisioningProtos.proto
fingerprint_protos: OWSFingerprintProtos.proto
$(PROTOC) --objc_out=../src/Security/ \
OWSFingerprintProtos.proto

@ -0,0 +1,18 @@
package textsecure;
option java_package = "org.whispersystems.libaxolotl.fingerprint";
option java_outer_classname = "FingerprintProtos";
import "objectivec-descriptor.proto";
option (google.protobuf.objectivec_file_options).class_prefix = "OWSFingerprintProtos";
message FingerprintData {
optional bytes publicKey = 1;
optional bytes identifier = 2;
}
message CombinedFingerprint {
optional uint32 version = 1;
optional FingerprintData localFingerprint = 2;
optional FingerprintData remoteFingerprint = 3;
}

@ -76,13 +76,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSString *)name {
NSString *contactId = [self contactIdentifier];
NSString *name = [[TextSecureKitEnv sharedEnv].contactsManager nameStringForPhoneIdentifier:contactId];
if (!name) {
name = contactId;
}
return name;
return [[TextSecureKitEnv sharedEnv].contactsManager nameStringForPhoneIdentifier:contactId];
}
#if TARGET_OS_IPHONE

@ -8,9 +8,16 @@
#import "TSErrorMessage.h"
NS_ASSUME_NONNULL_BEGIN
@class OWSFingerprint;
@interface TSInvalidIdentityKeyErrorMessage : TSErrorMessage
- (void)acceptNewIdentityKey;
- (NSString *)newIdentityFingerprint;
- (NSData *)newIdentityKey;
- (NSString *)theirSignalId;
@end
NS_ASSUME_NONNULL_END

@ -8,15 +8,27 @@
#import "TSInvalidIdentityKeyErrorMessage.h"
NS_ASSUME_NONNULL_BEGIN
@implementation TSInvalidIdentityKeyErrorMessage
- (void)acceptNewIdentityKey {
- (void)acceptNewIdentityKey
{
NSAssert(NO, @"Method needs to be implemented in subclasses of TSInvalidIdentityKeyErrorMessage.");
}
- (NSString *)newIdentityFingerprint
- (NSString *)newIdentityKey
{
NSAssert(NO, @"Method needs to be implemented in subclasses of TSInvalidIdentityKeyErrorMessage.");
return nil;
}
- (NSString *)theirSignalId
{
NSAssert(NO, @"Method needs to be implemented in subclasses of TSInvalidIdentityKeyErrorMessage.");
return nil;
}
@end
NS_ASSUME_NONNULL_END

@ -8,10 +8,13 @@
#import "TSInvalidIdentityKeyErrorMessage.h"
NS_ASSUME_NONNULL_BEGIN
@interface TSInvalidIdentityKeyReceivingErrorMessage : TSInvalidIdentityKeyErrorMessage
+ (instancetype)untrustedKeyWithEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
withTransaction:(YapDatabaseReadWriteTransaction *)transaction;
- (NSData *)newIdentityKey;
@end
NS_ASSUME_NONNULL_END

@ -2,10 +2,10 @@
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
#import "TSInvalidIdentityKeyReceivingErrorMessage.h"
#import "OWSFingerprint.h"
#import "TSContactThread.h"
#import "TSDatabaseView.h"
#import "TSErrorMessage_privateConstructor.h"
#import "TSFingerprintGenerator.h"
#import "TSMessagesManager.h"
#import "TSStorageManager+IdentityKeyStore.h"
#import "TSStorageManager.h"
@ -14,6 +14,14 @@
#import <YapDatabase/YapDatabaseTransaction.h>
#import <YapDatabase/YapDatabaseView.h>
NS_ASSUME_NONNULL_BEGIN
@interface TSInvalidIdentityKeyReceivingErrorMessage ()
@property (nonatomic, readonly, copy) NSString *authorId;
@end
@implementation TSInvalidIdentityKeyReceivingErrorMessage {
// Not using a property declaration in order to exclude from DB serialization
OWSSignalServiceProtosEnvelope *_envelope;
@ -29,20 +37,21 @@
TSInvalidIdentityKeyReceivingErrorMessage *errorMessage =
[[self alloc] initForUnknownIdentityKeyWithTimestamp:envelope.timestamp
inThread:contactThread
incomingEnvelopeData:envelope.data];
incomingEnvelope:envelope];
return errorMessage;
}
- (instancetype)initForUnknownIdentityKeyWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
incomingEnvelopeData:(NSData *)envelopeData
incomingEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
{
self = [self initWithTimestamp:timestamp inThread:thread failedMessageType:TSErrorMessageWrongTrustedIdentityKey];
if (!self) {
return self;
}
_envelopeData = envelopeData;
_envelopeData = envelope.data;
_authorId = envelope.source;
return self;
}
@ -108,9 +117,16 @@
return [message.identityKey removeKeyType];
}
- (NSString *)newIdentityFingerprint
- (NSString *)theirSignalId
{
return [TSFingerprintGenerator getFingerprintForDisplay:[self newIdentityKey]];
if (self.authorId) {
return self.authorId;
} else {
// for existing messages before we were storing author id.
return self.envelope.source;
}
}
@end
NS_ASSUME_NONNULL_END

@ -7,9 +7,12 @@
//
#import "TSInvalidIdentityKeyErrorMessage.h"
#import "TSOutgoingMessage.h"
NS_ASSUME_NONNULL_BEGIN
@class PreKeyBundle;
@class TSOutgoingMessage;
@class TSThread;
@interface TSInvalidIdentityKeySendingErrorMessage : TSInvalidIdentityKeyErrorMessage
@ -22,6 +25,8 @@
preKeyBundle:(PreKeyBundle *)preKeyBundle
withTransaction:(YapDatabaseReadWriteTransaction *)transaction;
- (NSString *)recipientId;
@property (nonatomic, readonly) NSString *recipientId;
@end
NS_ASSUME_NONNULL_END

@ -2,20 +2,21 @@
// Copyright (c) 2015 Open Whisper Systems. All rights reserved.
#import "TSInvalidIdentityKeySendingErrorMessage.h"
#import "OWSFingerprint.h"
#import "PreKeyBundle+jsonDict.h"
#import "SignalRecipient.h"
#import "TSContactThread.h"
#import "TSErrorMessage_privateConstructor.h"
#import "TSFingerprintGenerator.h"
#import "TSMessagesManager+sendMessages.h"
#import "TSOutgoingMessage.h"
#import "TSStorageManager+IdentityKeyStore.h"
#import <AxolotlKit/NSData+keyVersionByte.h>
NS_ASSUME_NONNULL_BEGIN
@interface TSInvalidIdentityKeySendingErrorMessage ()
@property (nonatomic, readonly) PreKeyBundle *preKeyBundle;
@property (nonatomic, readonly) NSString *recipientId;
@property (nonatomic, readonly) NSString *messageId;
@end
@ -55,9 +56,9 @@
- (void)acceptNewIdentityKey
{
[[TSStorageManager sharedManager] saveRemoteIdentity:[self newKey] recipientId:self.recipientId];
[[TSStorageManager sharedManager] saveRemoteIdentity:self.newIdentityKey recipientId:self.recipientId];
__block TSOutgoingMessage *message;
__block TSOutgoingMessage *_Nullable message;
__block TSThread *thread;
__block SignalRecipient *recipient;
@ -89,15 +90,16 @@
}
}
- (NSString *)newIdentityFingerprint
- (NSData *)newIdentityKey
{
NSData *identityKey = [self newKey];
return [TSFingerprintGenerator getFingerprintForDisplay:identityKey];
return [self.preKeyBundle.identityKey removeKeyType];
}
- (NSData *)newKey {
return [self.preKeyBundle.identityKey removeKeyType];
- (NSString *)theirSignalId
{
return self.recipientId;
}
@end
NS_ASSUME_NONNULL_END

@ -11,11 +11,13 @@
@class OWSSignalServiceProtosEnvelope;
@class OWSSignalServiceProtosDataMessage;
@class ContactsUpdater;
@protocol ContactsManagerProtocol;
@interface TSMessagesManager : NSObject
- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
dbConnection:(YapDatabaseConnection *)dbConnection
contactsManager:(id<ContactsManagerProtocol>)contactsManager
contactsUpdater:(ContactsUpdater *)contactsUpdater NS_DESIGNATED_INITIALIZER;
+ (instancetype)sharedManager;

@ -26,6 +26,12 @@
#import <AxolotlKit/AxolotlExceptions.h>
#import <AxolotlKit/SessionCipher.h>
@interface TSMessagesManager ()
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
@end
@implementation TSMessagesManager
+ (instancetype)sharedManager {
@ -41,11 +47,14 @@
{
return [self initWithNetworkManager:[TSNetworkManager sharedManager]
dbConnection:[TSStorageManager sharedManager].newDatabaseConnection
contactsManager:[TextSecureKitEnv sharedEnv].contactsManager
contactsUpdater:[ContactsUpdater sharedUpdater]];
}
- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
dbConnection:(YapDatabaseConnection *)dbConnection
contactsManager:(id<ContactsManagerProtocol>)contactsManager
contactsUpdater:(ContactsUpdater *)contactsUpdater
{
self = [super init];
@ -56,6 +65,7 @@
_networkManager = networkManager;
_dbConnection = dbConnection;
_contactsManager = contactsManager;
_contactsUpdater = contactsUpdater;
return self;
@ -257,7 +267,7 @@
DDLogInfo(@"Received request `Contacts` syncMessage.");
OWSSyncContactsMessage *syncContactsMessage =
[[OWSSyncContactsMessage alloc] initWithContactsManager:[TextSecureKitEnv sharedEnv].contactsManager];
[[OWSSyncContactsMessage alloc] initWithContactsManager:self.contactsManager];
[self sendTemporaryAttachment:[syncContactsMessage buildPlainTextAttachmentData]
contentType:OWSMimeTypeApplicationOctetStream
@ -378,12 +388,7 @@
messageType:TSInfoMessageTypeGroupUpdate
customMessage:updateGroupInfo] saveWithTransaction:transaction];
} else if (dataMessage.group.type == OWSSignalServiceProtosGroupContextTypeQuit) {
NSString *nameString =
[[TextSecureKitEnv sharedEnv].contactsManager nameStringForPhoneIdentifier:envelope.source];
if (!nameString) {
nameString = envelope.source;
}
NSString *nameString = [self.contactsManager nameStringForPhoneIdentifier:envelope.source];
NSString *updateGroupInfo =
[NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_LEFT", @""), nameString];

@ -0,0 +1,41 @@
// Created by Michael Kirk on 9/14/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
NS_ASSUME_NONNULL_BEGIN
@class UIImage;
@interface OWSFingerprint : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithMyStableId:(NSString *)myStableId
myIdentityKey:(NSData *)myIdentityKeyWithoutKeyType
theirStableId:(NSString *)theirStableId
theirIdentityKey:(NSData *)theirIdentityKeyWithoutKeyType
hashIterations:(uint32_t)hashIterations NS_DESIGNATED_INITIALIZER;
+ (instancetype)fingerprintWithMyStableId:(NSString *)myStableId
myIdentityKey:(NSData *)myIdentityKeyWithoutKeyType
theirStableId:(NSString *)theirStableId
theirIdentityKey:(NSData *)theirIdentityKeyWithoutKeyType
hashIterations:(uint32_t)hashIterations;
+ (instancetype)fingerprintWithMyStableId:(NSString *)myStableId
myIdentityKey:(NSData *)myIdentityKeyWithoutKeyType
theirStableId:(NSString *)theirStableId
theirIdentityKey:(NSData *)theirIdentityKeyWithoutKeyType;
- (BOOL)matchesCombinedFingerprintData:(NSData *)combinedFingerprintData error:(NSError **)error;
@property (nonatomic, readonly) NSData *myStableIdData;
@property (nonatomic, readonly) NSData *myIdentityKey;
@property (nonatomic, readonly) NSString *theirStableId;
@property (nonatomic, readonly) NSData *theirStableIdData;
@property (nonatomic, readonly) NSData *theirIdentityKey;
@property (nonatomic, readonly) NSString *displayableText;
@property (nonatomic, readonly) UIImage *image;
@end
NS_ASSUME_NONNULL_END

@ -0,0 +1,299 @@
// Created by Michael Kirk on 9/14/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSFingerprint.h"
#import "NSData+Base64.h"
#import "OWSError.h"
#import "OWSFingerprintProtos.pb.h"
#import <AxolotlKit/NSData+keyVersionByte.h>
#import <CommonCrypto/CommonDigest.h>
#import <UIKit/UIImage.h>
NS_ASSUME_NONNULL_BEGIN
static uint32_t const OWSFingerprintVersion = 0;
static uint32_t const OWSFingerprintDefaultHashIterations = 5200;
@interface OWSFingerprint ()
@property (nonatomic, readonly) NSUInteger hashIterations;
@property (nonatomic, readonly) NSString *text;
@end
@implementation OWSFingerprint
- (instancetype)initWithMyStableId:(NSString *)myStableId
myIdentityKey:(NSData *)myIdentityKeyWithoutKeyType
theirStableId:(NSString *)theirStableId
theirIdentityKey:(NSData *)theirIdentityKeyWithoutKeyType
hashIterations:(uint32_t)hashIterations
{
self = [super init];
if (!self) {
return self;
}
_myStableIdData = [myStableId dataUsingEncoding:NSUTF8StringEncoding];
_myIdentityKey = [myIdentityKeyWithoutKeyType prependKeyType];
_theirStableId = theirStableId;
_theirStableIdData = [theirStableId dataUsingEncoding:NSUTF8StringEncoding];
_theirIdentityKey = [theirIdentityKeyWithoutKeyType prependKeyType];
_hashIterations = hashIterations;
_text = [self generateText];
_image = [self generateImage];
return self;
}
+ (instancetype)fingerprintWithMyStableId:(NSString *)myStableId
myIdentityKey:(NSData *)myIdentityKeyWithoutKeyType
theirStableId:(NSString *)theirStableId
theirIdentityKey:(NSData *)theirIdentityKeyWithoutKeyType
hashIterations:(uint32_t)hashIterations
{
return [[self alloc] initWithMyStableId:myStableId
myIdentityKey:myIdentityKeyWithoutKeyType
theirStableId:theirStableId
theirIdentityKey:theirIdentityKeyWithoutKeyType
hashIterations:hashIterations];
}
+ (instancetype)fingerprintWithMyStableId:(NSString *)myStableId
myIdentityKey:(NSData *)myIdentityKeyWithoutKeyType
theirStableId:(NSString *)theirStableId
theirIdentityKey:(NSData *)theirIdentityKeyWithoutKeyType
{
return [[self alloc] initWithMyStableId:myStableId
myIdentityKey:myIdentityKeyWithoutKeyType
theirStableId:theirStableId
theirIdentityKey:theirIdentityKeyWithoutKeyType
hashIterations:OWSFingerprintDefaultHashIterations];
}
- (BOOL)matchesCombinedFingerprintData:(NSData *)data error:(NSError **)error
{
OWSFingerprintProtosCombinedFingerprint *combinedFingerprint;
@try {
combinedFingerprint = [OWSFingerprintProtosCombinedFingerprint parseFromData:data];
} @catch (NSException *exception) {
if ([exception.name isEqualToString:@"InvalidProtocolBuffer"]) {
NSString *description = NSLocalizedString(@"PRIVACY_VERIFICATION_FAILURE_INVALID_QRCODE", @"alert body");
*error = OWSErrorWithCodeDescription(OWSErrorCodePrivacyVerificationFailure, description);
return NO;
} else {
// Sync log in case we bail.
NSLog(@"%@ parsing QRCode data failed with error: %@", self.tag, exception);
@throw exception;
}
}
if (combinedFingerprint.version < OWSFingerprintVersion) {
DDLogWarn(@"%@ Verification failed. We're running an old version.", self.tag);
NSString *description
= NSLocalizedString(@"PRIVACY_VERIFICATION_FAILED_WITH_OLD_REMOTE_VERSION", @"alert body");
*error = OWSErrorWithCodeDescription(OWSErrorCodePrivacyVerificationFailure, description);
return NO;
}
if (combinedFingerprint.version > OWSFingerprintVersion) {
DDLogWarn(@"%@ Verification failed. They're running an old version.", self.tag);
NSString *description = NSLocalizedString(@"PRIVACY_VERIFICATION_FAILED_WITH_OLD_LOCAL_VERSION", @"alert body");
*error = OWSErrorWithCodeDescription(OWSErrorCodePrivacyVerificationFailure, description);
return NO;
}
// Their local is *our* remote.
OWSFingerprintProtosFingerprintData *localFingerprint = combinedFingerprint.remoteFingerprint;
OWSFingerprintProtosFingerprintData *remoteFingerprint = combinedFingerprint.localFingerprint;
if (![remoteFingerprint.identifier isEqual:self.theirStableIdData]) {
DDLogWarn(@"%@ Verification failed. We're expecting a different contact.", self.tag);
NSString *errorFormat = NSLocalizedString(@"PRIVACY_VERIFICATION_FAILED_WITH_MISMATCHED_REMOTE_IDENTIFIER",
@"Alert body {{expected phone number}}, {{actual phone number we found}}");
NSString *expected = [[NSString alloc] initWithData:self.theirStableIdData encoding:NSUTF8StringEncoding];
NSString *actual = [[NSString alloc] initWithData:remoteFingerprint.identifier encoding:NSUTF8StringEncoding];
NSString *description = [NSString stringWithFormat:errorFormat, expected, actual];
*error = OWSErrorWithCodeDescription(OWSErrorCodePrivacyVerificationFailure, description);
return NO;
}
if (![localFingerprint.identifier isEqual:self.myStableIdData]) {
DDLogWarn(@"%@ Verification failed. They presented the wrong fingerprint.", self.tag);
NSString *errorFormat = NSLocalizedString(@"PRIVACY_VERIFICATION_FAILED_WITH_MISMATCHED_LOCAL_IDENTIFIER",
@"Alert body {{expected phone number}}, {{actual phone number we found}}");
NSString *expected = [[NSString alloc] initWithData:self.myStableIdData encoding:NSUTF8StringEncoding];
NSString *actual = [[NSString alloc] initWithData:localFingerprint.identifier encoding:NSUTF8StringEncoding];
NSString *description = [NSString stringWithFormat:errorFormat, expected, actual];
*error = OWSErrorWithCodeDescription(OWSErrorCodePrivacyVerificationFailure, description);
return NO;
}
if (![localFingerprint.publicKey isEqual:self.myIdentityKey]) {
DDLogWarn(@"%@ Verification failed. They have the wrong key for us", self.tag);
NSString *description = NSLocalizedString(@"PRIVACY_VERIFICATION_FAILED_WITH_MISMATCHED_KEYS", @"Alert body");
*error = OWSErrorWithCodeDescription(OWSErrorCodePrivacyVerificationFailure, description);
return NO;
}
if (![remoteFingerprint.publicKey isEqual:self.theirIdentityKey]) {
DDLogWarn(@"%@ Verification failed. We have the wrong key for them", self.tag);
NSString *description = NSLocalizedString(@"PRIVACY_VERIFICATION_FAILED_WITH_MISMATCHED_KEYS", @"Alert body");
*error = OWSErrorWithCodeDescription(OWSErrorCodePrivacyVerificationFailure, description);
return NO;
}
DDLogWarn(@"%@ Verification Succeeded.", self.tag);
return YES;
}
- (NSString *)generateText
{
NSString *myDisplayString = [self stringForStableId:self.myStableIdData publicKey:self.myIdentityKey];
NSString *theirDisplayString = [self stringForStableId:self.theirStableIdData publicKey:self.theirIdentityKey];
if ([theirDisplayString compare:myDisplayString] == NSOrderedAscending) {
return [NSString stringWithFormat:@"%@%@", theirDisplayString, myDisplayString];
} else {
return [NSString stringWithFormat:@"%@%@", myDisplayString, theirDisplayString];
}
}
- (NSString *)displayableText
{
NSString *input = self.text;
NSMutableArray<NSString *> *chunks = [NSMutableArray new];
for (uint i = 0; i < input.length / 5; i++) {
NSString *nextChunk = [input substringWithRange:NSMakeRange(i * 5, 5)];
[chunks addObject:nextChunk];
}
return [chunks componentsJoinedByString:@" "];
}
- (NSData *)dataFromShort:(uint32_t)aShort
{
uint8_t bytes[] = {
((uint8_t)(aShort & 0xFF00) >> 8),
(uint8_t)(aShort & 0x00FF)
};
return [NSData dataWithBytes:bytes length:2];
}
/**
* An identifier for a mutable public key, belonging to an immutable identifier (stableId).
*
* This method is intended to be somewhat expensive to produce in order to be brute force adverse.
*
* @param stableId
* Immutable global identifier e.g. Signal Identifier, an e164 formatted phone number encoded as UTF-8 data
* @param publicKey
* The current public key for <stableId>
* @return
* All-number textual representation
*/
- (NSString *)stringForStableId:(NSData *)stableIdData publicKey:(NSData *)publicKey
{
NSData *versionData = [self dataFromShort:OWSFingerprintVersion];
NSMutableData *hash = [NSMutableData dataWithData:versionData];
[hash appendData:publicKey];
[hash appendData:stableIdData];
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
for (int i = 0; i < self.hashIterations; i++) {
[hash appendData:publicKey];
CC_SHA512(hash.bytes, (unsigned int)hash.length, digest);
// TODO get rid of this loop-allocation
hash = [NSMutableData dataWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];
}
return [NSString stringWithFormat:@"%@%@%@%@%@%@",
[self encodedChunkFromData:hash offset:0],
[self encodedChunkFromData:hash offset:5],
[self encodedChunkFromData:hash offset:10],
[self encodedChunkFromData:hash offset:15],
[self encodedChunkFromData:hash offset:20],
[self encodedChunkFromData:hash offset:25]];
}
- (NSString *)encodedChunkFromData:(NSData *)data offset:(uint)offset
{
uint8_t fiveBytes[5];
[data getBytes:fiveBytes range:NSMakeRange(offset, 5)];
int chunk = [self uint64From5Bytes:fiveBytes] % 100000;
return [NSString stringWithFormat:@"%05d", chunk];
}
- (int64_t)uint64From5Bytes:(uint8_t[])bytes
{
int64_t result = ((bytes[0] & 0xffLL) << 32) |
((bytes[1] & 0xffLL) << 24) |
((bytes[2] & 0xffLL) << 16) |
((bytes[3] & 0xffLL) << 8) |
((bytes[4] & 0xffLL));
return result;
}
- (nullable UIImage *)generateImage
{
OWSFingerprintProtosCombinedFingerprintBuilder *combinedFingerprintBuilder =
[OWSFingerprintProtosCombinedFingerprintBuilder new];
[combinedFingerprintBuilder setVersion:OWSFingerprintVersion];
OWSFingerprintProtosFingerprintDataBuilder *remoteFingerprintDataBuilder =
[OWSFingerprintProtosFingerprintDataBuilder new];
[remoteFingerprintDataBuilder setPublicKey:self.theirIdentityKey];
[remoteFingerprintDataBuilder setIdentifier:self.theirStableIdData];
[combinedFingerprintBuilder setRemoteFingerprintBuilder:remoteFingerprintDataBuilder];
OWSFingerprintProtosFingerprintDataBuilder *localFingerprintDataBuilder =
[OWSFingerprintProtosFingerprintDataBuilder new];
[localFingerprintDataBuilder setPublicKey:self.myIdentityKey];
[localFingerprintDataBuilder setIdentifier:self.myStableIdData];
[combinedFingerprintBuilder setLocalFingerprintBuilder:localFingerprintDataBuilder];
// Build ByteMode QR (Latin-1 encodable data)
NSData *fingerprintData = [combinedFingerprintBuilder build].data;
DDLogDebug(@"%@ Building fingerprint with data: %@", self.tag, fingerprintData);
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[filter setDefaults];
[filter setValue:fingerprintData forKey:@"inputMessage"];
CIImage *ciImage = [filter outputImage];
if (!ciImage) {
DDLogError(@"%@ Failed to create QR image from fingerprint text: %@", self.tag, self.text);
return nil;
}
// UIImages backed by a CIImage won't render without antialiasing, so we convert the backign image to a CGImage,
// which can be scaled crisply.
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgImage = [context createCGImage:ciImage fromRect:ciImage.extent];
UIImage *qrImage = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
return qrImage;
}
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end
NS_ASSUME_NONNULL_END

@ -0,0 +1,199 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
#import <ProtocolBuffers/ProtocolBuffers.h>
// @@protoc_insertion_point(imports)
@class OWSFingerprintProtosCombinedFingerprint;
@class OWSFingerprintProtosCombinedFingerprintBuilder;
@class OWSFingerprintProtosFingerprintData;
@class OWSFingerprintProtosFingerprintDataBuilder;
@class ObjectiveCFileOptions;
@class ObjectiveCFileOptionsBuilder;
@class PBDescriptorProto;
@class PBDescriptorProtoBuilder;
@class PBDescriptorProtoExtensionRange;
@class PBDescriptorProtoExtensionRangeBuilder;
@class PBEnumDescriptorProto;
@class PBEnumDescriptorProtoBuilder;
@class PBEnumOptions;
@class PBEnumOptionsBuilder;
@class PBEnumValueDescriptorProto;
@class PBEnumValueDescriptorProtoBuilder;
@class PBEnumValueOptions;
@class PBEnumValueOptionsBuilder;
@class PBFieldDescriptorProto;
@class PBFieldDescriptorProtoBuilder;
@class PBFieldOptions;
@class PBFieldOptionsBuilder;
@class PBFileDescriptorProto;
@class PBFileDescriptorProtoBuilder;
@class PBFileDescriptorSet;
@class PBFileDescriptorSetBuilder;
@class PBFileOptions;
@class PBFileOptionsBuilder;
@class PBMessageOptions;
@class PBMessageOptionsBuilder;
@class PBMethodDescriptorProto;
@class PBMethodDescriptorProtoBuilder;
@class PBMethodOptions;
@class PBMethodOptionsBuilder;
@class PBOneofDescriptorProto;
@class PBOneofDescriptorProtoBuilder;
@class PBServiceDescriptorProto;
@class PBServiceDescriptorProtoBuilder;
@class PBServiceOptions;
@class PBServiceOptionsBuilder;
@class PBSourceCodeInfo;
@class PBSourceCodeInfoBuilder;
@class PBSourceCodeInfoLocation;
@class PBSourceCodeInfoLocationBuilder;
@class PBUninterpretedOption;
@class PBUninterpretedOptionBuilder;
@class PBUninterpretedOptionNamePart;
@class PBUninterpretedOptionNamePartBuilder;
@interface OWSFingerprintProtosOwsfingerprintProtosRoot : NSObject {
}
+ (PBExtensionRegistry*) extensionRegistry;
+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry;
@end
#define FingerprintData_publicKey @"publicKey"
#define FingerprintData_identifier @"identifier"
@interface OWSFingerprintProtosFingerprintData : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasPublicKey_:1;
BOOL hasIdentifier_:1;
NSData* publicKey;
NSData* identifier;
}
- (BOOL) hasPublicKey;
- (BOOL) hasIdentifier;
@property (readonly, strong) NSData* publicKey;
@property (readonly, strong) NSData* identifier;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (OWSFingerprintProtosFingerprintDataBuilder*) builder;
+ (OWSFingerprintProtosFingerprintDataBuilder*) builder;
+ (OWSFingerprintProtosFingerprintDataBuilder*) builderWithPrototype:(OWSFingerprintProtosFingerprintData*) prototype;
- (OWSFingerprintProtosFingerprintDataBuilder*) toBuilder;
+ (OWSFingerprintProtosFingerprintData*) parseFromData:(NSData*) data;
+ (OWSFingerprintProtosFingerprintData*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSFingerprintProtosFingerprintData*) parseFromInputStream:(NSInputStream*) input;
+ (OWSFingerprintProtosFingerprintData*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSFingerprintProtosFingerprintData*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (OWSFingerprintProtosFingerprintData*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface OWSFingerprintProtosFingerprintDataBuilder : PBGeneratedMessageBuilder {
@private
OWSFingerprintProtosFingerprintData* resultFingerprintData;
}
- (OWSFingerprintProtosFingerprintData*) defaultInstance;
- (OWSFingerprintProtosFingerprintDataBuilder*) clear;
- (OWSFingerprintProtosFingerprintDataBuilder*) clone;
- (OWSFingerprintProtosFingerprintData*) build;
- (OWSFingerprintProtosFingerprintData*) buildPartial;
- (OWSFingerprintProtosFingerprintDataBuilder*) mergeFrom:(OWSFingerprintProtosFingerprintData*) other;
- (OWSFingerprintProtosFingerprintDataBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (OWSFingerprintProtosFingerprintDataBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasPublicKey;
- (NSData*) publicKey;
- (OWSFingerprintProtosFingerprintDataBuilder*) setPublicKey:(NSData*) value;
- (OWSFingerprintProtosFingerprintDataBuilder*) clearPublicKey;
- (BOOL) hasIdentifier;
- (NSData*) identifier;
- (OWSFingerprintProtosFingerprintDataBuilder*) setIdentifier:(NSData*) value;
- (OWSFingerprintProtosFingerprintDataBuilder*) clearIdentifier;
@end
#define CombinedFingerprint_version @"version"
#define CombinedFingerprint_localFingerprint @"localFingerprint"
#define CombinedFingerprint_remoteFingerprint @"remoteFingerprint"
@interface OWSFingerprintProtosCombinedFingerprint : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasLocalFingerprint_:1;
BOOL hasRemoteFingerprint_:1;
BOOL hasVersion_:1;
OWSFingerprintProtosFingerprintData* localFingerprint;
OWSFingerprintProtosFingerprintData* remoteFingerprint;
UInt32 version;
}
- (BOOL) hasVersion;
- (BOOL) hasLocalFingerprint;
- (BOOL) hasRemoteFingerprint;
@property (readonly) UInt32 version;
@property (readonly, strong) OWSFingerprintProtosFingerprintData* localFingerprint;
@property (readonly, strong) OWSFingerprintProtosFingerprintData* remoteFingerprint;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) builder;
+ (OWSFingerprintProtosCombinedFingerprintBuilder*) builder;
+ (OWSFingerprintProtosCombinedFingerprintBuilder*) builderWithPrototype:(OWSFingerprintProtosCombinedFingerprint*) prototype;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) toBuilder;
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromData:(NSData*) data;
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromInputStream:(NSInputStream*) input;
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface OWSFingerprintProtosCombinedFingerprintBuilder : PBGeneratedMessageBuilder {
@private
OWSFingerprintProtosCombinedFingerprint* resultCombinedFingerprint;
}
- (OWSFingerprintProtosCombinedFingerprint*) defaultInstance;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clear;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clone;
- (OWSFingerprintProtosCombinedFingerprint*) build;
- (OWSFingerprintProtosCombinedFingerprint*) buildPartial;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeFrom:(OWSFingerprintProtosCombinedFingerprint*) other;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasVersion;
- (UInt32) version;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setVersion:(UInt32) value;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clearVersion;
- (BOOL) hasLocalFingerprint;
- (OWSFingerprintProtosFingerprintData*) localFingerprint;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setLocalFingerprint:(OWSFingerprintProtosFingerprintData*) value;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setLocalFingerprintBuilder:(OWSFingerprintProtosFingerprintDataBuilder*) builderForValue;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeLocalFingerprint:(OWSFingerprintProtosFingerprintData*) value;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clearLocalFingerprint;
- (BOOL) hasRemoteFingerprint;
- (OWSFingerprintProtosFingerprintData*) remoteFingerprint;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setRemoteFingerprint:(OWSFingerprintProtosFingerprintData*) value;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setRemoteFingerprintBuilder:(OWSFingerprintProtosFingerprintDataBuilder*) builderForValue;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeRemoteFingerprint:(OWSFingerprintProtosFingerprintData*) value;
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clearRemoteFingerprint;
@end
// @@protoc_insertion_point(global_scope)

@ -0,0 +1,632 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
#import "OWSFingerprintProtos.pb.h"
// @@protoc_insertion_point(imports)
@implementation OWSFingerprintProtosOwsfingerprintProtosRoot
static PBExtensionRegistry* extensionRegistry = nil;
+ (PBExtensionRegistry*) extensionRegistry {
return extensionRegistry;
}
+ (void) initialize {
if (self == [OWSFingerprintProtosOwsfingerprintProtosRoot class]) {
PBMutableExtensionRegistry* registry = [PBMutableExtensionRegistry registry];
[self registerAllExtensions:registry];
[ObjectivecDescriptorRoot registerAllExtensions:registry];
extensionRegistry = registry;
}
}
+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry {
}
@end
@interface OWSFingerprintProtosFingerprintData ()
@property (strong) NSData* publicKey;
@property (strong) NSData* identifier;
@end
@implementation OWSFingerprintProtosFingerprintData
- (BOOL) hasPublicKey {
return !!hasPublicKey_;
}
- (void) setHasPublicKey:(BOOL) _value_ {
hasPublicKey_ = !!_value_;
}
@synthesize publicKey;
- (BOOL) hasIdentifier {
return !!hasIdentifier_;
}
- (void) setHasIdentifier:(BOOL) _value_ {
hasIdentifier_ = !!_value_;
}
@synthesize identifier;
- (instancetype) init {
if ((self = [super init])) {
self.publicKey = [NSData data];
self.identifier = [NSData data];
}
return self;
}
static OWSFingerprintProtosFingerprintData* defaultOWSFingerprintProtosFingerprintDataInstance = nil;
+ (void) initialize {
if (self == [OWSFingerprintProtosFingerprintData class]) {
defaultOWSFingerprintProtosFingerprintDataInstance = [[OWSFingerprintProtosFingerprintData alloc] init];
}
}
+ (instancetype) defaultInstance {
return defaultOWSFingerprintProtosFingerprintDataInstance;
}
- (instancetype) defaultInstance {
return defaultOWSFingerprintProtosFingerprintDataInstance;
}
- (BOOL) isInitialized {
return YES;
}
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output {
if (self.hasPublicKey) {
[output writeData:1 value:self.publicKey];
}
if (self.hasIdentifier) {
[output writeData:2 value:self.identifier];
}
[self.unknownFields writeToCodedOutputStream:output];
}
- (SInt32) serializedSize {
__block SInt32 size_ = memoizedSerializedSize;
if (size_ != -1) {
return size_;
}
size_ = 0;
if (self.hasPublicKey) {
size_ += computeDataSize(1, self.publicKey);
}
if (self.hasIdentifier) {
size_ += computeDataSize(2, self.identifier);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
return size_;
}
+ (OWSFingerprintProtosFingerprintData*) parseFromData:(NSData*) data {
return (OWSFingerprintProtosFingerprintData*)[[[OWSFingerprintProtosFingerprintData builder] mergeFromData:data] build];
}
+ (OWSFingerprintProtosFingerprintData*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSFingerprintProtosFingerprintData*)[[[OWSFingerprintProtosFingerprintData builder] mergeFromData:data extensionRegistry:extensionRegistry] build];
}
+ (OWSFingerprintProtosFingerprintData*) parseFromInputStream:(NSInputStream*) input {
return (OWSFingerprintProtosFingerprintData*)[[[OWSFingerprintProtosFingerprintData builder] mergeFromInputStream:input] build];
}
+ (OWSFingerprintProtosFingerprintData*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSFingerprintProtosFingerprintData*)[[[OWSFingerprintProtosFingerprintData builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build];
}
+ (OWSFingerprintProtosFingerprintData*) parseFromCodedInputStream:(PBCodedInputStream*) input {
return (OWSFingerprintProtosFingerprintData*)[[[OWSFingerprintProtosFingerprintData builder] mergeFromCodedInputStream:input] build];
}
+ (OWSFingerprintProtosFingerprintData*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSFingerprintProtosFingerprintData*)[[[OWSFingerprintProtosFingerprintData builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build];
}
+ (OWSFingerprintProtosFingerprintDataBuilder*) builder {
return [[OWSFingerprintProtosFingerprintDataBuilder alloc] init];
}
+ (OWSFingerprintProtosFingerprintDataBuilder*) builderWithPrototype:(OWSFingerprintProtosFingerprintData*) prototype {
return [[OWSFingerprintProtosFingerprintData builder] mergeFrom:prototype];
}
- (OWSFingerprintProtosFingerprintDataBuilder*) builder {
return [OWSFingerprintProtosFingerprintData builder];
}
- (OWSFingerprintProtosFingerprintDataBuilder*) toBuilder {
return [OWSFingerprintProtosFingerprintData builderWithPrototype:self];
}
- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent {
if (self.hasPublicKey) {
[output appendFormat:@"%@%@: %@\n", indent, @"publicKey", self.publicKey];
}
if (self.hasIdentifier) {
[output appendFormat:@"%@%@: %@\n", indent, @"identifier", self.identifier];
}
[self.unknownFields writeDescriptionTo:output withIndent:indent];
}
- (void) storeInDictionary:(NSMutableDictionary *)dictionary {
if (self.hasPublicKey) {
[dictionary setObject: self.publicKey forKey: @"publicKey"];
}
if (self.hasIdentifier) {
[dictionary setObject: self.identifier forKey: @"identifier"];
}
[self.unknownFields storeInDictionary:dictionary];
}
- (BOOL) isEqual:(id)other {
if (other == self) {
return YES;
}
if (![other isKindOfClass:[OWSFingerprintProtosFingerprintData class]]) {
return NO;
}
OWSFingerprintProtosFingerprintData *otherMessage = other;
return
self.hasPublicKey == otherMessage.hasPublicKey &&
(!self.hasPublicKey || [self.publicKey isEqual:otherMessage.publicKey]) &&
self.hasIdentifier == otherMessage.hasIdentifier &&
(!self.hasIdentifier || [self.identifier isEqual:otherMessage.identifier]) &&
(self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
}
- (NSUInteger) hash {
__block NSUInteger hashCode = 7;
if (self.hasPublicKey) {
hashCode = hashCode * 31 + [self.publicKey hash];
}
if (self.hasIdentifier) {
hashCode = hashCode * 31 + [self.identifier hash];
}
hashCode = hashCode * 31 + [self.unknownFields hash];
return hashCode;
}
@end
@interface OWSFingerprintProtosFingerprintDataBuilder()
@property (strong) OWSFingerprintProtosFingerprintData* resultFingerprintData;
@end
@implementation OWSFingerprintProtosFingerprintDataBuilder
@synthesize resultFingerprintData;
- (instancetype) init {
if ((self = [super init])) {
self.resultFingerprintData = [[OWSFingerprintProtosFingerprintData alloc] init];
}
return self;
}
- (PBGeneratedMessage*) internalGetResult {
return resultFingerprintData;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) clear {
self.resultFingerprintData = [[OWSFingerprintProtosFingerprintData alloc] init];
return self;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) clone {
return [OWSFingerprintProtosFingerprintData builderWithPrototype:resultFingerprintData];
}
- (OWSFingerprintProtosFingerprintData*) defaultInstance {
return [OWSFingerprintProtosFingerprintData defaultInstance];
}
- (OWSFingerprintProtosFingerprintData*) build {
[self checkInitialized];
return [self buildPartial];
}
- (OWSFingerprintProtosFingerprintData*) buildPartial {
OWSFingerprintProtosFingerprintData* returnMe = resultFingerprintData;
self.resultFingerprintData = nil;
return returnMe;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) mergeFrom:(OWSFingerprintProtosFingerprintData*) other {
if (other == [OWSFingerprintProtosFingerprintData defaultInstance]) {
return self;
}
if (other.hasPublicKey) {
[self setPublicKey:other.publicKey];
}
if (other.hasIdentifier) {
[self setIdentifier:other.identifier];
}
[self mergeUnknownFields:other.unknownFields];
return self;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input {
return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]];
}
- (OWSFingerprintProtosFingerprintDataBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields];
while (YES) {
SInt32 tag = [input readTag];
switch (tag) {
case 0:
[self setUnknownFields:[unknownFields build]];
return self;
default: {
if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) {
[self setUnknownFields:[unknownFields build]];
return self;
}
break;
}
case 10: {
[self setPublicKey:[input readData]];
break;
}
case 18: {
[self setIdentifier:[input readData]];
break;
}
}
}
}
- (BOOL) hasPublicKey {
return resultFingerprintData.hasPublicKey;
}
- (NSData*) publicKey {
return resultFingerprintData.publicKey;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) setPublicKey:(NSData*) value {
resultFingerprintData.hasPublicKey = YES;
resultFingerprintData.publicKey = value;
return self;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) clearPublicKey {
resultFingerprintData.hasPublicKey = NO;
resultFingerprintData.publicKey = [NSData data];
return self;
}
- (BOOL) hasIdentifier {
return resultFingerprintData.hasIdentifier;
}
- (NSData*) identifier {
return resultFingerprintData.identifier;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) setIdentifier:(NSData*) value {
resultFingerprintData.hasIdentifier = YES;
resultFingerprintData.identifier = value;
return self;
}
- (OWSFingerprintProtosFingerprintDataBuilder*) clearIdentifier {
resultFingerprintData.hasIdentifier = NO;
resultFingerprintData.identifier = [NSData data];
return self;
}
@end
@interface OWSFingerprintProtosCombinedFingerprint ()
@property UInt32 version;
@property (strong) OWSFingerprintProtosFingerprintData* localFingerprint;
@property (strong) OWSFingerprintProtosFingerprintData* remoteFingerprint;
@end
@implementation OWSFingerprintProtosCombinedFingerprint
- (BOOL) hasVersion {
return !!hasVersion_;
}
- (void) setHasVersion:(BOOL) _value_ {
hasVersion_ = !!_value_;
}
@synthesize version;
- (BOOL) hasLocalFingerprint {
return !!hasLocalFingerprint_;
}
- (void) setHasLocalFingerprint:(BOOL) _value_ {
hasLocalFingerprint_ = !!_value_;
}
@synthesize localFingerprint;
- (BOOL) hasRemoteFingerprint {
return !!hasRemoteFingerprint_;
}
- (void) setHasRemoteFingerprint:(BOOL) _value_ {
hasRemoteFingerprint_ = !!_value_;
}
@synthesize remoteFingerprint;
- (instancetype) init {
if ((self = [super init])) {
self.version = 0;
self.localFingerprint = [OWSFingerprintProtosFingerprintData defaultInstance];
self.remoteFingerprint = [OWSFingerprintProtosFingerprintData defaultInstance];
}
return self;
}
static OWSFingerprintProtosCombinedFingerprint* defaultOWSFingerprintProtosCombinedFingerprintInstance = nil;
+ (void) initialize {
if (self == [OWSFingerprintProtosCombinedFingerprint class]) {
defaultOWSFingerprintProtosCombinedFingerprintInstance = [[OWSFingerprintProtosCombinedFingerprint alloc] init];
}
}
+ (instancetype) defaultInstance {
return defaultOWSFingerprintProtosCombinedFingerprintInstance;
}
- (instancetype) defaultInstance {
return defaultOWSFingerprintProtosCombinedFingerprintInstance;
}
- (BOOL) isInitialized {
return YES;
}
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output {
if (self.hasVersion) {
[output writeUInt32:1 value:self.version];
}
if (self.hasLocalFingerprint) {
[output writeMessage:2 value:self.localFingerprint];
}
if (self.hasRemoteFingerprint) {
[output writeMessage:3 value:self.remoteFingerprint];
}
[self.unknownFields writeToCodedOutputStream:output];
}
- (SInt32) serializedSize {
__block SInt32 size_ = memoizedSerializedSize;
if (size_ != -1) {
return size_;
}
size_ = 0;
if (self.hasVersion) {
size_ += computeUInt32Size(1, self.version);
}
if (self.hasLocalFingerprint) {
size_ += computeMessageSize(2, self.localFingerprint);
}
if (self.hasRemoteFingerprint) {
size_ += computeMessageSize(3, self.remoteFingerprint);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
return size_;
}
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromData:(NSData*) data {
return (OWSFingerprintProtosCombinedFingerprint*)[[[OWSFingerprintProtosCombinedFingerprint builder] mergeFromData:data] build];
}
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSFingerprintProtosCombinedFingerprint*)[[[OWSFingerprintProtosCombinedFingerprint builder] mergeFromData:data extensionRegistry:extensionRegistry] build];
}
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromInputStream:(NSInputStream*) input {
return (OWSFingerprintProtosCombinedFingerprint*)[[[OWSFingerprintProtosCombinedFingerprint builder] mergeFromInputStream:input] build];
}
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSFingerprintProtosCombinedFingerprint*)[[[OWSFingerprintProtosCombinedFingerprint builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build];
}
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromCodedInputStream:(PBCodedInputStream*) input {
return (OWSFingerprintProtosCombinedFingerprint*)[[[OWSFingerprintProtosCombinedFingerprint builder] mergeFromCodedInputStream:input] build];
}
+ (OWSFingerprintProtosCombinedFingerprint*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
return (OWSFingerprintProtosCombinedFingerprint*)[[[OWSFingerprintProtosCombinedFingerprint builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build];
}
+ (OWSFingerprintProtosCombinedFingerprintBuilder*) builder {
return [[OWSFingerprintProtosCombinedFingerprintBuilder alloc] init];
}
+ (OWSFingerprintProtosCombinedFingerprintBuilder*) builderWithPrototype:(OWSFingerprintProtosCombinedFingerprint*) prototype {
return [[OWSFingerprintProtosCombinedFingerprint builder] mergeFrom:prototype];
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) builder {
return [OWSFingerprintProtosCombinedFingerprint builder];
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) toBuilder {
return [OWSFingerprintProtosCombinedFingerprint builderWithPrototype:self];
}
- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent {
if (self.hasVersion) {
[output appendFormat:@"%@%@: %@\n", indent, @"version", [NSNumber numberWithInteger:self.version]];
}
if (self.hasLocalFingerprint) {
[output appendFormat:@"%@%@ {\n", indent, @"localFingerprint"];
[self.localFingerprint writeDescriptionTo:output
withIndent:[NSString stringWithFormat:@"%@ ", indent]];
[output appendFormat:@"%@}\n", indent];
}
if (self.hasRemoteFingerprint) {
[output appendFormat:@"%@%@ {\n", indent, @"remoteFingerprint"];
[self.remoteFingerprint writeDescriptionTo:output
withIndent:[NSString stringWithFormat:@"%@ ", indent]];
[output appendFormat:@"%@}\n", indent];
}
[self.unknownFields writeDescriptionTo:output withIndent:indent];
}
- (void) storeInDictionary:(NSMutableDictionary *)dictionary {
if (self.hasVersion) {
[dictionary setObject: [NSNumber numberWithInteger:self.version] forKey: @"version"];
}
if (self.hasLocalFingerprint) {
NSMutableDictionary *messageDictionary = [NSMutableDictionary dictionary];
[self.localFingerprint storeInDictionary:messageDictionary];
[dictionary setObject:[NSDictionary dictionaryWithDictionary:messageDictionary] forKey:@"localFingerprint"];
}
if (self.hasRemoteFingerprint) {
NSMutableDictionary *messageDictionary = [NSMutableDictionary dictionary];
[self.remoteFingerprint storeInDictionary:messageDictionary];
[dictionary setObject:[NSDictionary dictionaryWithDictionary:messageDictionary] forKey:@"remoteFingerprint"];
}
[self.unknownFields storeInDictionary:dictionary];
}
- (BOOL) isEqual:(id)other {
if (other == self) {
return YES;
}
if (![other isKindOfClass:[OWSFingerprintProtosCombinedFingerprint class]]) {
return NO;
}
OWSFingerprintProtosCombinedFingerprint *otherMessage = other;
return
self.hasVersion == otherMessage.hasVersion &&
(!self.hasVersion || self.version == otherMessage.version) &&
self.hasLocalFingerprint == otherMessage.hasLocalFingerprint &&
(!self.hasLocalFingerprint || [self.localFingerprint isEqual:otherMessage.localFingerprint]) &&
self.hasRemoteFingerprint == otherMessage.hasRemoteFingerprint &&
(!self.hasRemoteFingerprint || [self.remoteFingerprint isEqual:otherMessage.remoteFingerprint]) &&
(self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
}
- (NSUInteger) hash {
__block NSUInteger hashCode = 7;
if (self.hasVersion) {
hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.version] hash];
}
if (self.hasLocalFingerprint) {
hashCode = hashCode * 31 + [self.localFingerprint hash];
}
if (self.hasRemoteFingerprint) {
hashCode = hashCode * 31 + [self.remoteFingerprint hash];
}
hashCode = hashCode * 31 + [self.unknownFields hash];
return hashCode;
}
@end
@interface OWSFingerprintProtosCombinedFingerprintBuilder()
@property (strong) OWSFingerprintProtosCombinedFingerprint* resultCombinedFingerprint;
@end
@implementation OWSFingerprintProtosCombinedFingerprintBuilder
@synthesize resultCombinedFingerprint;
- (instancetype) init {
if ((self = [super init])) {
self.resultCombinedFingerprint = [[OWSFingerprintProtosCombinedFingerprint alloc] init];
}
return self;
}
- (PBGeneratedMessage*) internalGetResult {
return resultCombinedFingerprint;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clear {
self.resultCombinedFingerprint = [[OWSFingerprintProtosCombinedFingerprint alloc] init];
return self;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clone {
return [OWSFingerprintProtosCombinedFingerprint builderWithPrototype:resultCombinedFingerprint];
}
- (OWSFingerprintProtosCombinedFingerprint*) defaultInstance {
return [OWSFingerprintProtosCombinedFingerprint defaultInstance];
}
- (OWSFingerprintProtosCombinedFingerprint*) build {
[self checkInitialized];
return [self buildPartial];
}
- (OWSFingerprintProtosCombinedFingerprint*) buildPartial {
OWSFingerprintProtosCombinedFingerprint* returnMe = resultCombinedFingerprint;
self.resultCombinedFingerprint = nil;
return returnMe;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeFrom:(OWSFingerprintProtosCombinedFingerprint*) other {
if (other == [OWSFingerprintProtosCombinedFingerprint defaultInstance]) {
return self;
}
if (other.hasVersion) {
[self setVersion:other.version];
}
if (other.hasLocalFingerprint) {
[self mergeLocalFingerprint:other.localFingerprint];
}
if (other.hasRemoteFingerprint) {
[self mergeRemoteFingerprint:other.remoteFingerprint];
}
[self mergeUnknownFields:other.unknownFields];
return self;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input {
return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]];
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry {
PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields];
while (YES) {
SInt32 tag = [input readTag];
switch (tag) {
case 0:
[self setUnknownFields:[unknownFields build]];
return self;
default: {
if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) {
[self setUnknownFields:[unknownFields build]];
return self;
}
break;
}
case 8: {
[self setVersion:[input readUInt32]];
break;
}
case 18: {
OWSFingerprintProtosFingerprintDataBuilder* subBuilder = [OWSFingerprintProtosFingerprintData builder];
if (self.hasLocalFingerprint) {
[subBuilder mergeFrom:self.localFingerprint];
}
[input readMessage:subBuilder extensionRegistry:extensionRegistry];
[self setLocalFingerprint:[subBuilder buildPartial]];
break;
}
case 26: {
OWSFingerprintProtosFingerprintDataBuilder* subBuilder = [OWSFingerprintProtosFingerprintData builder];
if (self.hasRemoteFingerprint) {
[subBuilder mergeFrom:self.remoteFingerprint];
}
[input readMessage:subBuilder extensionRegistry:extensionRegistry];
[self setRemoteFingerprint:[subBuilder buildPartial]];
break;
}
}
}
}
- (BOOL) hasVersion {
return resultCombinedFingerprint.hasVersion;
}
- (UInt32) version {
return resultCombinedFingerprint.version;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setVersion:(UInt32) value {
resultCombinedFingerprint.hasVersion = YES;
resultCombinedFingerprint.version = value;
return self;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clearVersion {
resultCombinedFingerprint.hasVersion = NO;
resultCombinedFingerprint.version = 0;
return self;
}
- (BOOL) hasLocalFingerprint {
return resultCombinedFingerprint.hasLocalFingerprint;
}
- (OWSFingerprintProtosFingerprintData*) localFingerprint {
return resultCombinedFingerprint.localFingerprint;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setLocalFingerprint:(OWSFingerprintProtosFingerprintData*) value {
resultCombinedFingerprint.hasLocalFingerprint = YES;
resultCombinedFingerprint.localFingerprint = value;
return self;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setLocalFingerprintBuilder:(OWSFingerprintProtosFingerprintDataBuilder*) builderForValue {
return [self setLocalFingerprint:[builderForValue build]];
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeLocalFingerprint:(OWSFingerprintProtosFingerprintData*) value {
if (resultCombinedFingerprint.hasLocalFingerprint &&
resultCombinedFingerprint.localFingerprint != [OWSFingerprintProtosFingerprintData defaultInstance]) {
resultCombinedFingerprint.localFingerprint =
[[[OWSFingerprintProtosFingerprintData builderWithPrototype:resultCombinedFingerprint.localFingerprint] mergeFrom:value] buildPartial];
} else {
resultCombinedFingerprint.localFingerprint = value;
}
resultCombinedFingerprint.hasLocalFingerprint = YES;
return self;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clearLocalFingerprint {
resultCombinedFingerprint.hasLocalFingerprint = NO;
resultCombinedFingerprint.localFingerprint = [OWSFingerprintProtosFingerprintData defaultInstance];
return self;
}
- (BOOL) hasRemoteFingerprint {
return resultCombinedFingerprint.hasRemoteFingerprint;
}
- (OWSFingerprintProtosFingerprintData*) remoteFingerprint {
return resultCombinedFingerprint.remoteFingerprint;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setRemoteFingerprint:(OWSFingerprintProtosFingerprintData*) value {
resultCombinedFingerprint.hasRemoteFingerprint = YES;
resultCombinedFingerprint.remoteFingerprint = value;
return self;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) setRemoteFingerprintBuilder:(OWSFingerprintProtosFingerprintDataBuilder*) builderForValue {
return [self setRemoteFingerprint:[builderForValue build]];
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) mergeRemoteFingerprint:(OWSFingerprintProtosFingerprintData*) value {
if (resultCombinedFingerprint.hasRemoteFingerprint &&
resultCombinedFingerprint.remoteFingerprint != [OWSFingerprintProtosFingerprintData defaultInstance]) {
resultCombinedFingerprint.remoteFingerprint =
[[[OWSFingerprintProtosFingerprintData builderWithPrototype:resultCombinedFingerprint.remoteFingerprint] mergeFrom:value] buildPartial];
} else {
resultCombinedFingerprint.remoteFingerprint = value;
}
resultCombinedFingerprint.hasRemoteFingerprint = YES;
return self;
}
- (OWSFingerprintProtosCombinedFingerprintBuilder*) clearRemoteFingerprint {
resultCombinedFingerprint.hasRemoteFingerprint = NO;
resultCombinedFingerprint.remoteFingerprint = [OWSFingerprintProtosFingerprintData defaultInstance];
return self;
}
@end
// @@protoc_insertion_point(global_scope)

@ -1,15 +0,0 @@
//
// TSFingerprintGenerator.h
// Signal
//
// Created by Frederic Jacobs on 10/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface TSFingerprintGenerator : NSObject
+ (NSString *)getFingerprintForDisplay:(NSData *)identityKey;
@end

@ -1,37 +0,0 @@
//
// TSFingerprintGenerator.m
// Signal
//
// Created by Frederic Jacobs on 10/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <AxolotlKit/NSData+keyVersionByte.h>
#import "NSData+hexString.h"
#import "TSFingerprintGenerator.h"
@implementation TSFingerprintGenerator
+ (NSString *)getFingerprintForDisplay:(NSData *)identityKey {
// idea here is to insert a space every two characters. there is probably a cleverer/more native way to do this.
identityKey = [identityKey prependKeyType];
NSString *fingerprint = [identityKey hexadecimalString];
__block NSString *formattedFingerprint = @"";
[fingerprint
enumerateSubstringsInRange:NSMakeRange(0, [fingerprint length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
if (substringRange.location % 2 != 0 && substringRange.location != [fingerprint length] - 1) {
substring = [substring stringByAppendingString:@" "];
}
formattedFingerprint = [formattedFingerprint stringByAppendingString:substring];
}];
return formattedFingerprint;
}
@end

@ -33,6 +33,7 @@
*
* @return E164 string of the registered phone number
*/
- (NSString *)localNumber;
+ (NSString *)localNumber;
- (void)runIfHasLocalNumber:(void (^)())block;

@ -10,8 +10,14 @@
@implementation TSStorageManager (keyingMaterial)
+ (NSString *)localNumber {
return [[self sharedManager] stringForKey:TSStorageRegisteredNumberKey inCollection:TSStorageUserAccountCollection];
+ (NSString *)localNumber
{
return [[self sharedManager] localNumber];
}
- (NSString *)localNumber
{
return [self stringForKey:TSStorageRegisteredNumberKey inCollection:TSStorageUserAccountCollection];
}
- (void)runIfHasLocalNumber:(void (^)())block

@ -8,7 +8,10 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
OWSErrorCodeInvalidMethodParameters = 11,
OWSErrorCodeUnableToProcessServerResponse = 12,
OWSErrorCodeFailedToDecodeJson = 13,
OWSErrorCodeFailedToEncodeJson = 14
OWSErrorCodeFailedToEncodeJson = 14,
OWSErrorCodeFailedToDecodeQR = 15,
OWSErrorCodePrivacyVerificationFailure = 20
};
extern NSError *OWSErrorWithCodeDescription(OWSErrorCode code, NSString *description);

@ -8,6 +8,7 @@
#import "TSMessagesManager.h"
#import "TSNetworkManager.h"
#import "TSStorageManager.h"
#import "ContactsManagerProtocol.h"
#import "objc/runtime.h"
@interface TSMessagesManagerTest : XCTestCase
@ -139,6 +140,38 @@
@end
@interface OWSFakeContactsManager : NSObject <ContactsManagerProtocol>
@end
/**
* I don't know that this test relys on any of the specific behavior in this implementation.
* We're just trying to avoid setting up/accessing the TSEnv global. ~mjk
*/
@implementation OWSFakeContactsManager
- (NSString *)nameStringForPhoneIdentifier:(NSString *)phoneNumber
{
return @"Fake name";
}
- (NSArray<Contact *> *)signalContacts
{
return @[];
}
+ (BOOL)name:(NSString *)nameString matchesQuery:(NSString *)queryString
{
return YES;
}
- (UIImage *)imageForPhoneIdentifier:(NSString *)phoneNumber
{
return nil;
}
@end
@implementation TSMessagesManagerTest
- (void)testIncomingSyncContactMessage
@ -147,9 +180,11 @@
XCTestExpectation *messageWasSubmitted = [self expectationWithDescription:@"message was submitted"];
OWSTSMessagesManagerTestNetworkManager *fakeNetworkManager =
[[OWSTSMessagesManagerTestNetworkManager alloc] initWithExpectation:messageWasSubmitted];
OWSFakeContactsManager *fakeContactsManager = [OWSFakeContactsManager new];
TSMessagesManager *messagesManager =
[[TSMessagesManager alloc] initWithNetworkManager:fakeNetworkManager
dbConnection:[TSStorageManager sharedManager].newDatabaseConnection
contactsManager:fakeContactsManager
contactsUpdater:fakeContactsUpdater];
OWSSignalServiceProtosEnvelopeBuilder *envelopeBuilder = [OWSSignalServiceProtosEnvelopeBuilder new];

@ -0,0 +1,74 @@
// Created by Michael Kirk on 9/14/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSFingerprint.h"
#import <25519/Curve25519.h>
#import <XCTest/XCTest.h>
@interface OWSFingerprintTest : XCTestCase
@end
@implementation OWSFingerprintTest
- (void)testDisplayableTextInsertsSpaces
{
NSString *aliceStableId = @"+13231111111";
NSData *aliceIdentityKey = [Curve25519 generateKeyPair].publicKey;
NSString *bobStableId = @"+14152222222";
NSData *bobIdentityKey = [Curve25519 generateKeyPair].publicKey;
OWSFingerprint *aliceFingerprint = [OWSFingerprint fingerprintWithMyStableId:aliceStableId
myIdentityKey:aliceIdentityKey
theirStableId:bobStableId
theirIdentityKey:bobIdentityKey
hashIterations:2];
NSString *displayableText = aliceFingerprint.displayableText;
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(0, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(1, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(2, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(3, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(4, 1)]);
XCTAssertEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(5, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(6, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(7, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(8, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(9, 1)]);
XCTAssertNotEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(10, 1)]);
XCTAssertEqualObjects(@" ", [displayableText substringWithRange:NSMakeRange(11, 1)]);
}
- (void)testTextMatchesReciprocally
{
NSString *aliceStableId = @"+13231111111";
NSData *aliceIdentityKey = [Curve25519 generateKeyPair].publicKey;
NSString *bobStableId = @"+14152222222";
NSData *bobIdentityKey = [Curve25519 generateKeyPair].publicKey;
NSString *charlieStableId = @"+14153333333";
NSData *charlieIdentityKey = [Curve25519 generateKeyPair].publicKey;
OWSFingerprint *aliceFingerprint = [OWSFingerprint fingerprintWithMyStableId:aliceStableId
myIdentityKey:aliceIdentityKey
theirStableId:bobStableId
theirIdentityKey:bobIdentityKey
hashIterations:2];
OWSFingerprint *bobFingerprint = [OWSFingerprint fingerprintWithMyStableId:bobStableId
myIdentityKey:bobIdentityKey
theirStableId:aliceStableId
theirIdentityKey:aliceIdentityKey
hashIterations:2];
OWSFingerprint *charlieFingerprint = [OWSFingerprint fingerprintWithMyStableId:charlieStableId
myIdentityKey:charlieIdentityKey
theirStableId:aliceStableId
theirIdentityKey:aliceIdentityKey
hashIterations:2];
XCTAssertEqualObjects(aliceFingerprint.displayableText, bobFingerprint.displayableText);
XCTAssertNotEqualObjects(aliceFingerprint.displayableText, charlieFingerprint.displayableText);
}
@end
Loading…
Cancel
Save