This commit is contained in:
Frederic Jacobs 2015-01-27 15:13:13 -10:00
parent 529c1346fa
commit bcd98f90ee
12 changed files with 276 additions and 12 deletions

View File

@ -358,6 +358,7 @@
B63BAD6D1A74DA8F00269E74 /* TSStorageManager+messageIDs.m in Sources */ = {isa = PBXBuildFile; fileRef = B63BAD6C1A74DA8F00269E74 /* TSStorageManager+messageIDs.m */; };
B640C4771A477B0F005C7C8A /* TSAttachementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */; };
B6416FB8199A0478003C5699 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6416F57199A0478003C5699 /* Localizable.strings */; };
B65031CF1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B65031CE1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m */; };
B65EDA1219E1BE6400AAA7CB /* RPAPICall.m in Sources */ = {isa = PBXBuildFile; fileRef = B65EDA1119E1BE6400AAA7CB /* RPAPICall.m */; };
B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B66DBF4919D5BBC8006EA940 /* Images.xcassets */; };
B67ADDC41989FF8700E1A773 /* RPServerRequestsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B67ADDC31989FF8700E1A773 /* RPServerRequestsManager.m */; };
@ -370,6 +371,8 @@
B692BF071A76EF0F002786DA /* TSDatabaseSecondaryIndexes.m in Sources */ = {isa = PBXBuildFile; fileRef = B692BF061A76EF0F002786DA /* TSDatabaseSecondaryIndexes.m */; };
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
B6A3EB4B1A423B3800B2236B /* TSAttachmentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A3EB4A1A423B3800B2236B /* TSAttachmentAdapter.m */; };
B6A5D05C1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A5D05B1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m */; };
B6A5D0631A7850180043D837 /* TSCurrentSignedPreKeyRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A5D0621A7850180043D837 /* TSCurrentSignedPreKeyRequest.m */; };
B6AE33BD1A1EB121003DF39D /* TSGroupModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B6AE33BC1A1EB121003DF39D /* TSGroupModel.m */; };
B6B095E41A1D25C5008BFAA6 /* CryptographyTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */; };
B6B095E51A1D25C5008BFAA6 /* TextSecureKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095DF1A1D25C5008BFAA6 /* TextSecureKitTests.m */; };
@ -991,6 +994,7 @@
B63BAD6C1A74DA8F00269E74 /* TSStorageManager+messageIDs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+messageIDs.m"; sourceTree = "<group>"; };
B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachementsTest.m; sourceTree = "<group>"; };
B6416F58199A0478003C5699 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Localizable.strings; sourceTree = "<group>"; };
B65031CE1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignedPreKeyDeletionTests.m; sourceTree = "<group>"; };
B657DDC91911A40500F45B0C /* Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Signal.entitlements; sourceTree = "<group>"; };
B65EDA1019E1BE6400AAA7CB /* RPAPICall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RPAPICall.h; sourceTree = "<group>"; };
B65EDA1119E1BE6400AAA7CB /* RPAPICall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RPAPICall.m; sourceTree = "<group>"; };
@ -1013,6 +1017,10 @@
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>"; };
B6A5D05A1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAvailablePreKeysCountRequest.h; sourceTree = "<group>"; };
B6A5D05B1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAvailablePreKeysCountRequest.m; sourceTree = "<group>"; };
B6A5D0611A7850180043D837 /* TSCurrentSignedPreKeyRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSCurrentSignedPreKeyRequest.h; sourceTree = "<group>"; };
B6A5D0621A7850180043D837 /* TSCurrentSignedPreKeyRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSCurrentSignedPreKeyRequest.m; sourceTree = "<group>"; };
B6AE33BB1A1EB121003DF39D /* TSGroupModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSGroupModel.h; path = "../../view controllers/TSGroupModel.h"; sourceTree = "<group>"; };
B6AE33BC1A1EB121003DF39D /* TSGroupModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSGroupModel.m; path = "../../view controllers/TSGroupModel.m"; sourceTree = "<group>"; };
B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CryptographyTests.mm; sourceTree = "<group>"; };
@ -2254,10 +2262,12 @@
children = (
B60FB9A51A46F099006A5A66 /* TSAllocAttachmentRequest.h */,
B60FB9A61A46F099006A5A66 /* TSAllocAttachmentRequest.m */,
B6A5D05A1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.h */,
B6A5D05B1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m */,
B63AF5AC1A1F757900D01AAD /* TSContactsIntersectionRequest.h */,
B63AF5AD1A1F757900D01AAD /* TSContactsIntersectionRequest.m */,
B63AF5AE1A1F757900D01AAD /* TSUnregisterAccountRequest.h */,
B63AF5AF1A1F757900D01AAD /* TSUnregisterAccountRequest.m */,
B6A5D0611A7850180043D837 /* TSCurrentSignedPreKeyRequest.h */,
B6A5D0621A7850180043D837 /* TSCurrentSignedPreKeyRequest.m */,
B63AF5B01A1F757900D01AAD /* TSRecipientPrekeyRequest.h */,
B63AF5B11A1F757900D01AAD /* TSRecipientPrekeyRequest.m */,
B63AF5B21A1F757900D01AAD /* TSRegisterForPushRequest.h */,
@ -2272,6 +2282,8 @@
B63AF5BB1A1F757900D01AAD /* TSAttachmentRequest.m */,
B63AF5BE1A1F757900D01AAD /* TSSubmitMessageRequest.h */,
B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.m */,
B63AF5AE1A1F757900D01AAD /* TSUnregisterAccountRequest.h */,
B63AF5AF1A1F757900D01AAD /* TSUnregisterAccountRequest.m */,
);
path = Requests;
sourceTree = "<group>";
@ -2308,6 +2320,7 @@
B6B095DD1A1D25C5008BFAA6 /* textsecure */ = {
isa = PBXGroup;
children = (
B65031CE1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m */,
A5578C711A646E5300704A25 /* VersionMigrationsTests.m */,
B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */,
B6B095DF1A1D25C5008BFAA6 /* TextSecureKitTests.m */,
@ -3139,6 +3152,7 @@
B6B0968B1A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.m in Sources */,
76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */,
B6CBF53F1A254BD1000D4184 /* ContactDetailCell.m in Sources */,
B6A5D05C1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m in Sources */,
FCB11D931A12A4AA002F93FB /* FullImageViewController.m in Sources */,
B6B096871A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.m in Sources */,
B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */,
@ -3243,6 +3257,7 @@
B6B096651A1D25ED008BFAA6 /* TSGroupThread.m in Sources */,
FCAC965119FF0A6E0046DFC5 /* MessagesViewController.m in Sources */,
B63AF5D01A1F757900D01AAD /* TSSubmitMessageRequest.m in Sources */,
B6A5D0631A7850180043D837 /* TSCurrentSignedPreKeyRequest.m in Sources */,
B6B0966B1A1D25ED008BFAA6 /* TSAttachment.m in Sources */,
76EB057618170B33006006FC /* Contact.m in Sources */,
B6B0968F1A1D25ED008BFAA6 /* TSYapDatabaseObject.m in Sources */,
@ -3452,6 +3467,7 @@
76EB062918170B33006006FC /* BadArgument.m in Sources */,
A157076A17F0CD6D007C2BD6 /* ZrtpTest.m in Sources */,
A157076B17F0CD6D007C2BD6 /* LowLatencyConnectorTest.m in Sources */,
B65031CF1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m in Sources */,
76EB061718170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */,
76EB05F118170B33006006FC /* PhoneManager.m in Sources */,
76EB05F718170B33006006FC /* CallConnectUtil.m in Sources */,

View File

@ -13,6 +13,7 @@
#import "Release.h"
#import "SignalsViewController.h"
#import "TSAccountManager.h"
#import "TSPreKeyManager.h"
#import "TSSocketManager.h"
#import "TSStorageManager.h"
#import "Util.h"
@ -123,9 +124,11 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue";
[vc performSegueWithIdentifier:kCallSegue sender:self];
} onThread:NSThread.mainThread untilCancelled:nil];
[TSSocketManager becomeActive];
[self refreshContacts];
if ([TSAccountManager isRegistered]) {
[TSSocketManager becomeActive];
[self refreshContacts];
[TSPreKeyManager refreshPreKeys];
}
return YES;
}

View File

@ -10,8 +10,13 @@
#import "TSConstants.h"
#import "TSAccountManager.h"
// Time before deletion of signed PreKeys (measured in seconds)
#define SignedPreKeysDeletionTime 14*24*60*60
@interface TSPreKeyManager : NSObject
+ (void)registerPreKeysWithSuccess:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock;
+ (void)refreshPreKeys;
@end

View File

@ -7,6 +7,9 @@
//
#import "TSPreKeyManager.h"
#import "TSAvailablePreKeysCountRequest.h"
#import "TSCurrentSignedPreKeyRequest.h"
#import "TSStorageManager.h"
#import "TSStorageManager+PreKeyStore.h"
#import "TSStorageManager+SignedPreKeyStore.h"
@ -14,6 +17,8 @@
#import "TSNetworkManager.h"
#import "TSRegisterPrekeysRequest.h"
#define EPHEMERAL_PREKEYS_MINIMUM 15
@implementation TSPreKeyManager
+ (void)registerPreKeysWithSuccess:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock{
@ -47,4 +52,75 @@
}
+ (void)refreshPreKeys {
TSAvailablePreKeysCountRequest *preKeyCountRequest = [[TSAvailablePreKeysCountRequest alloc] init];
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:preKeyCountRequest success:^(NSURLSessionDataTask *task, NSDictionary* responseObject){
NSString *preKeyCountKey = @"count";
NSNumber *count = [responseObject objectForKey:preKeyCountKey];
if (count.integerValue > EPHEMERAL_PREKEYS_MINIMUM) {
DDLogVerbose(@"Available prekeys sufficient: %@", count.stringValue);
return;
} else {
[self registerPreKeysWithSuccess:^{
DDLogInfo(@"New PreKeys registered with server.");
[self clearSignedPreKeyRecords];
} failure:^(NSError *error) {
DDLogWarn(@"Failed to update prekeys with the server");
}];
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"Failed to retreive the number of available prekeys.");
}];
}
+ (void)clearSignedPreKeyRecords {
TSRequest *currentSignedPreKey = [[TSCurrentSignedPreKeyRequest alloc] init];
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:currentSignedPreKey success:^(NSURLSessionDataTask *task, NSDictionary* responseObject) {
NSString *keyIdDictKey = @"keyId";
NSNumber *keyId = [responseObject objectForKey:keyIdDictKey];
[self clearSignedPreKeyRecordsWithKeyId:keyId];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogWarn(@"Failed to retreive current prekey.");
}];
}
+ (void)clearSignedPreKeyRecordsWithKeyId:(NSNumber*)keyId{
if (!keyId) {
DDLogError(@"The server returned an incomplete ");
return;
}
TSStorageManager *storageManager = [TSStorageManager sharedManager];
SignedPreKeyRecord *currentRecord = [storageManager loadSignedPrekey:keyId.intValue];
NSArray *allSignedPrekeys = [storageManager loadSignedPreKeys];
NSArray *oldSignedPrekeys = [self removeCurrentRecord:currentRecord fromRecords:allSignedPrekeys];
if ([oldSignedPrekeys count] > 3) {
for (SignedPreKeyRecord *deletionCandidate in oldSignedPrekeys) {
DDLogInfo(@"Old signed prekey record: %@", deletionCandidate.generatedAt);
if ([deletionCandidate.generatedAt timeIntervalSinceNow] > SignedPreKeysDeletionTime) {
[storageManager removeSignedPreKey:deletionCandidate.Id];
}
}
}
}
+ (NSArray*)removeCurrentRecord:(SignedPreKeyRecord*)currentRecord fromRecords:(NSArray*)allRecords {
NSMutableArray *oldRecords = [NSMutableArray array];
for (SignedPreKeyRecord *record in allRecords) {
if (currentRecord.Id != record.Id) {
[oldRecords addObject:record];
}
}
return oldRecords;
}
@end

View File

@ -0,0 +1,13 @@
//
// TSAvailablePreKeysCountRequest.h
// Signal
//
// Created by Frederic Jacobs on 27/01/15.
// Copyright (c) 2015 Open Whisper Systems. All rights reserved.
//
#import "TSRequest.h"
@interface TSAvailablePreKeysCountRequest : TSRequest
@end

View File

@ -0,0 +1,27 @@
//
// TSAvailablePreKeysCountRequest.m
// Signal
//
// Created by Frederic Jacobs on 27/01/15.
// Copyright (c) 2015 Open Whisper Systems. All rights reserved.
//
#import "TSAvailablePreKeysCountRequest.h"
#import "TSConstants.h"
@implementation TSAvailablePreKeysCountRequest
-(instancetype)init {
NSString *path = [NSString stringWithFormat:@"%@", textSecureKeysAPI];
self = [super initWithURL:[NSURL URLWithString:path]];
if (self) {
[self setHTTPMethod:@"GET"];
}
return self;
}
@end

View File

@ -0,0 +1,13 @@
//
// TSCurrentSignedPreKeyRequest.h
// Signal
//
// Created by Frederic Jacobs on 27/01/15.
// Copyright (c) 2015 Open Whisper Systems. All rights reserved.
//
#import "TSRequest.h"
@interface TSCurrentSignedPreKeyRequest : TSRequest
@end

View File

@ -0,0 +1,22 @@
//
// TSCurrentSignedPreKeyRequest.m
// Signal
//
// Created by Frederic Jacobs on 27/01/15.
// Copyright (c) 2015 Open Whisper Systems. All rights reserved.
//
#import "TSCurrentSignedPreKeyRequest.h"
#import "TSConstants.h"
@implementation TSCurrentSignedPreKeyRequest
- (instancetype)init {
self = [super initWithURL:[NSURL URLWithString:textSecureSignedKeysAPI]];
self.HTTPMethod = @"GET";
return self;
}
@end

View File

@ -9,6 +9,9 @@
#import "TSStorageManager.h"
#import <AxolotlKit/SignedPreKeyStore.h>
#define TSStorageManagerSignedPreKeyStoreCollection @"TSStorageManagerSignedPreKeyStoreCollection"
@interface TSStorageManager (SignedPreKeyStore) <SignedPreKeyStore>
- (SignedPreKeyRecord*)generateRandomSignedRecord;

View File

@ -12,7 +12,6 @@
#import <AxolotlKit/NSData+keyVersionByte.h>
#import "TSStorageManager+keyFromIntLong.h"
#define TSStorageManagerSignedPreKeyStoreCollection @"TSStorageManagerSignedPreKeyStoreCollection"
@implementation TSStorageManager (SignedPreKeyStore)

View File

@ -35,12 +35,14 @@ typedef enum {
//#define textSecureWebSocketAPI @"wss://textsecure-service-staging.whispersystems.org/v1/websocket/"
//#define textSecureServerURL @"https://textsecure-service-staging.whispersystems.org/"
#define textSecureGeneralAPI @"v1"
#define textSecureAccountsAPI @"v1/accounts"
#define textSecureMessagesAPI @"v1/messages/"
#define textSecureKeysAPI @"v2/keys"
#define textSecureDirectoryAPI @"v1/directory"
#define textSecureAttachmentsAPI @"v1/attachments"
#define textSecureGeneralAPI @"v1"
#define textSecureAccountsAPI @"v1/accounts"
#define textSecureMessagesAPI @"v1/messages/"
#define textSecureKeysAPI @"v2/keys"
#define textSecureSignedKeysAPI @"v2/keys/signed"
#define textSecureDirectoryAPI @"v1/directory"
#define textSecureAttachmentsAPI @"v1/attachments"
typedef void(^successCompletionBlock)(void);
typedef void(^failedRegistrationRequestBlock)(void);

View File

@ -0,0 +1,85 @@
//
// SignedPreKeyDeletionTests.m
// Signal
//
// Created by Frederic Jacobs on 27/01/15.
// Copyright (c) 2015 Open Whisper Systems. All rights reserved.
//
#import <XCTest/XCTest.h>
#import <AxolotlKit/SignedPrekeyRecord.h>
#import <25519/Curve25519.h>
#import <25519/Ed25519.h>
#import "TSPreKeyManager.h"
#import "TSStorageManager+SignedPreKeyStore.h"
@interface TSPreKeyManager ()
+ (void)clearSignedPreKeyRecordsWithKeyId:(NSNumber*)keyId;
@end
@interface SignedPreKeyDeletionTests : XCTestCase
@property int lastpreKeyId;
@end
@implementation SignedPreKeyDeletionTests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
- (void)testSignedPreKeyDeletion {
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
_lastpreKeyId = 20;
for (int i = 0; i <= _lastpreKeyId; i++) { // 21 signed keys are generated, one per day from now until 20 days ago.
SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i keyPair:[Curve25519 generateKeyPair] signature:nil generatedAt:[NSDate dateWithTimeIntervalSinceNow:i*24*60*60]];
[[TSStorageManager sharedManager] storeSignedPreKey:i signedPreKeyRecord:record];
}
[TSPreKeyManager clearSignedPreKeyRecordsWithKeyId:[NSNumber numberWithInt:_lastpreKeyId]];
XCTAssert([[TSStorageManager sharedManager]loadSignedPrekey:_lastpreKeyId] != nil);
// We tolerate to keep keys around for 14 days. We have 20-15 = 5 keys to delete. Hence the result of 21-5 = 16
XCTAssert([[[TSStorageManager sharedManager] loadSignedPreKeys] count] == 16);
}
- (void)testOlderRecordsNotDeletedIfNoReplacement {
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
_lastpreKeyId = 3;
for (int i = 1; i <= _lastpreKeyId; i++) { // 21 signed keys are generated, one per day from now until 20 days ago.
SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i keyPair:[Curve25519 generateKeyPair] signature:nil generatedAt:[NSDate dateWithTimeIntervalSinceNow:i*100*24*60*60]];
[[TSStorageManager sharedManager] storeSignedPreKey:i signedPreKeyRecord:record];
}
[TSPreKeyManager clearSignedPreKeyRecordsWithKeyId:[NSNumber numberWithInt:_lastpreKeyId]];
XCTAssert([[TSStorageManager sharedManager]loadSignedPrekey:_lastpreKeyId] != nil);
// All three records should still be stored.
XCTAssert([[[TSStorageManager sharedManager] loadSignedPreKeys] count] == 3);
}
@end