diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 90dbb4f2f..58192ec10 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -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 = ""; }; B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachementsTest.m; sourceTree = ""; }; B6416F58199A0478003C5699 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Localizable.strings; sourceTree = ""; }; + B65031CE1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignedPreKeyDeletionTests.m; sourceTree = ""; }; B657DDC91911A40500F45B0C /* Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Signal.entitlements; sourceTree = ""; }; B65EDA1019E1BE6400AAA7CB /* RPAPICall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RPAPICall.h; sourceTree = ""; }; B65EDA1119E1BE6400AAA7CB /* RPAPICall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RPAPICall.m; sourceTree = ""; }; @@ -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 = ""; }; B6A3EB4A1A423B3800B2236B /* TSAttachmentAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentAdapter.m; sourceTree = ""; }; + B6A5D05A1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAvailablePreKeysCountRequest.h; sourceTree = ""; }; + B6A5D05B1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAvailablePreKeysCountRequest.m; sourceTree = ""; }; + B6A5D0611A7850180043D837 /* TSCurrentSignedPreKeyRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSCurrentSignedPreKeyRequest.h; sourceTree = ""; }; + B6A5D0621A7850180043D837 /* TSCurrentSignedPreKeyRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSCurrentSignedPreKeyRequest.m; sourceTree = ""; }; B6AE33BB1A1EB121003DF39D /* TSGroupModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSGroupModel.h; path = "../../view controllers/TSGroupModel.h"; sourceTree = ""; }; B6AE33BC1A1EB121003DF39D /* TSGroupModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSGroupModel.m; path = "../../view controllers/TSGroupModel.m"; sourceTree = ""; }; B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CryptographyTests.mm; sourceTree = ""; }; @@ -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 = ""; @@ -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 */, diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 9399af72e..dd5692ec1 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -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; } diff --git a/Signal/src/textsecure/Account/TSPreKeyManager.h b/Signal/src/textsecure/Account/TSPreKeyManager.h index 3f8420f10..f28e1f700 100644 --- a/Signal/src/textsecure/Account/TSPreKeyManager.h +++ b/Signal/src/textsecure/Account/TSPreKeyManager.h @@ -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 diff --git a/Signal/src/textsecure/Account/TSPreKeyManager.m b/Signal/src/textsecure/Account/TSPreKeyManager.m index d5f87d4dd..7d2308af8 100644 --- a/Signal/src/textsecure/Account/TSPreKeyManager.m +++ b/Signal/src/textsecure/Account/TSPreKeyManager.m @@ -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 diff --git a/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.h b/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.h new file mode 100644 index 000000000..64b2a2857 --- /dev/null +++ b/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.h @@ -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 diff --git a/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.m b/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.m new file mode 100644 index 000000000..e95ae18f6 --- /dev/null +++ b/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.m @@ -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 diff --git a/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.h b/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.h new file mode 100644 index 000000000..982f3443d --- /dev/null +++ b/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.h @@ -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 diff --git a/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.m b/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.m new file mode 100644 index 000000000..32e41b58e --- /dev/null +++ b/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.m @@ -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 diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.h b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.h index 9baa54513..43c7bb988 100644 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.h +++ b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.h @@ -9,6 +9,9 @@ #import "TSStorageManager.h" #import + +#define TSStorageManagerSignedPreKeyStoreCollection @"TSStorageManagerSignedPreKeyStoreCollection" + @interface TSStorageManager (SignedPreKeyStore) - (SignedPreKeyRecord*)generateRandomSignedRecord; diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.m b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.m index 6b765c204..3fcef2a7c 100644 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.m +++ b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.m @@ -12,7 +12,6 @@ #import #import "TSStorageManager+keyFromIntLong.h" -#define TSStorageManagerSignedPreKeyStoreCollection @"TSStorageManagerSignedPreKeyStoreCollection" @implementation TSStorageManager (SignedPreKeyStore) diff --git a/Signal/src/textsecure/TSConstants.h b/Signal/src/textsecure/TSConstants.h index 375bd45c2..bbafc50ab 100644 --- a/Signal/src/textsecure/TSConstants.h +++ b/Signal/src/textsecure/TSConstants.h @@ -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); diff --git a/Signal/test/textsecure/SignedPreKeyDeletionTests.m b/Signal/test/textsecure/SignedPreKeyDeletionTests.m new file mode 100644 index 000000000..cc8165f26 --- /dev/null +++ b/Signal/test/textsecure/SignedPreKeyDeletionTests.m @@ -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 + +#import +#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