diff --git a/Cartfile b/Cartfile index 1388922b..7cbcc8ce 100644 --- a/Cartfile +++ b/Cartfile @@ -1,3 +1,3 @@ github "sparkle-project/Sparkle" ~> 1.13.1 -github "mstarke/KeePassKit" "5c98755e9954549a74f421d90af8cd6b5c0e01cc" +github "mstarke/KeePassKit" "d12bcc5e2e16115db19e26b6aaa29b62d23ce04b" github "mstarke/HNHUi" ~> 1.1 diff --git a/Cartfile.resolved b/Cartfile.resolved index 01370473..f3c47535 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ github "mstarke/HNHUi" "1.1" -github "mstarke/KeePassKit" "5c98755e9954549a74f421d90af8cd6b5c0e01cc" +github "mstarke/KeePassKit" "d12bcc5e2e16115db19e26b6aaa29b62d23ce04b" github "sparkle-project/Sparkle" "1.14.0" diff --git a/MacPass/KPKFormat+MPUTIDetection.m b/MacPass/KPKFormat+MPUTIDetection.m index 3f4b605f..835d0003 100644 --- a/MacPass/KPKFormat+MPUTIDetection.m +++ b/MacPass/KPKFormat+MPUTIDetection.m @@ -17,8 +17,8 @@ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ typeToUTI = @{ - @(KPKDatabaseTypeBinary) : MPLegacyDocumentUTI, - @(KPKDatabaseTypeXml) : MPXMLDocumentUTI + @(KPKDatabaseFormatKdb) : MPKdbDocumentUTI, + @(KPKDatabaseFormatKdbx) : MPKdbxDocumentUTI }; }); return typeToUTI; @@ -26,7 +26,7 @@ - (NSString *)typeForData:(NSData *)data { KPKFileInfo fileInfo = [self fileInfoForData:data]; - return [self _typeToUTIdictionary][@(fileInfo.type)]; + return [self _typeToUTIdictionary][@(fileInfo.format)]; } - (NSString *)typeForContentOfURL:(NSURL *)url { diff --git a/MacPass/MPConstants.h b/MacPass/MPConstants.h index 7e1e0360..60ed45ab 100644 --- a/MacPass/MPConstants.h +++ b/MacPass/MPConstants.h @@ -12,8 +12,8 @@ #import FOUNDATION_EXPORT NSString *const MPPasteBoardType; -FOUNDATION_EXPORT NSString *const MPLegacyDocumentUTI; -FOUNDATION_EXPORT NSString *const MPXMLDocumentUTI; +FOUNDATION_EXPORT NSString *const MPKdbDocumentUTI; +FOUNDATION_EXPORT NSString *const MPKdbxDocumentUTI; #endif diff --git a/MacPass/MPConstants.m b/MacPass/MPConstants.m index fab37b1f..4dec85c9 100644 --- a/MacPass/MPConstants.m +++ b/MacPass/MPConstants.m @@ -9,5 +9,5 @@ #import "MPConstants.h" NSString *const MPPasteBoardType = @"com.hicknhack.macpass.pasteboard"; -NSString *const MPLegacyDocumentUTI = @"com.hicknhack.macpass.kdb"; -NSString *const MPXMLDocumentUTI = @"com.hicknhack.macpass.kdbx"; \ No newline at end of file +NSString *const MPKdbDocumentUTI = @"com.hicknhack.macpass.kdb"; +NSString *const MPKdbxDocumentUTI = @"com.hicknhack.macpass.kdbx"; diff --git a/MacPass/MPDatabaseSettingsWindowController.m b/MacPass/MPDatabaseSettingsWindowController.m index bd9e04e8..bd5ae882 100644 --- a/MacPass/MPDatabaseSettingsWindowController.m +++ b/MacPass/MPDatabaseSettingsWindowController.m @@ -111,8 +111,9 @@ [defaults setBool:protectUsername forKey:kMPSettingsKeyLegacyHideUsername]; [defaults synchronize]; */ + + metaData.keyDerivationParameters = @{ KPKAESRoundsOption : [[KPKNumber alloc] initWithUnsignedInteger64: MAX(0,self.encryptionRoundsTextField.integerValue)]}; - metaData.rounds = MAX(0,self.encryptionRoundsTextField.integerValue); /* Register an action to enable promts when user cloeses without saving */ [self.document updateChangeCount:NSChangeDone]; [self close:nil]; @@ -124,8 +125,8 @@ - (IBAction)benchmarkRounds:(id)sender { [self.benchmarkButton setEnabled:NO]; - [KPKCompositeKey benchmarkTransformationRounds:1 completionHandler:^(NSUInteger rounds) { - self.encryptionRoundsTextField.integerValue = rounds; + [KPKAESKeyDerivation parametersForDelay:1 completionHandler:^(NSDictionary * _Nonnull options) { + self.encryptionRoundsTextField.integerValue = [options[KPKAESRoundsOption] unsignedInteger64Value]; self.benchmarkButton.enabled = YES; }]; } @@ -186,7 +187,8 @@ self.protectURLCheckButton.state = HNHUIStateForBool(metaData.protectUrl); self.protectUserNameCheckButton.state = HNHUIStateForBool(metaData.protectUserName); - [self.encryptionRoundsTextField setIntegerValue:metaData.rounds]; + [self.encryptionRoundsTextField setIntegerValue:[metaData.keyDerivationParameters[KPKAESRoundsOption] unsignedInteger64Value]]; + [self.benchmarkButton setEnabled:YES]; } diff --git a/MacPass/MPDocument.h b/MacPass/MPDocument.h index f7609b1a..f7f04373 100644 --- a/MacPass/MPDocument.h +++ b/MacPass/MPDocument.h @@ -78,7 +78,7 @@ FOUNDATION_EXPORT NSString *const MPDocumentGroupKey; @property (nonatomic, strong, readonly) KPKCompositeKey *compositeKey; @property (assign, readonly, getter = isReadOnly) BOOL readOnly; -@property (nonatomic, readonly, assign) KPKDatabaseType versionForFileType; +@property (nonatomic, readonly, assign) KPKDatabaseFormat versionForFileType; /* State (active group/entry) @@ -96,8 +96,8 @@ FOUNDATION_EXPORT NSString *const MPDocumentGroupKey; @property (nonatomic, copy) MPEntrySearchContext *searchContext; @property (nonatomic, strong, readonly) NSArray *searchResult; -+ (KPKDatabaseType)versionForFileType:(NSString *)fileType; -+ (NSString *)fileTypeForVersion:(KPKDatabaseType)version; ++ (KPKDatabaseFormat)versionForFileType:(NSString *)fileType; ++ (NSString *)fileTypeForVersion:(KPKDatabaseFormat)format; #pragma mark Lock/Decrypt - (IBAction)lockDatabase:(id)sender; diff --git a/MacPass/MPDocument.m b/MacPass/MPDocument.m index 87e690d7..89aa1569 100644 --- a/MacPass/MPDocument.m +++ b/MacPass/MPDocument.m @@ -89,23 +89,23 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou return [NSSet setWithObject:NSStringFromSelector(@selector(tree))]; } -+ (KPKDatabaseType)versionForFileType:(NSString *)fileType { - if( NSOrderedSame == [fileType compare:MPLegacyDocumentUTI options:NSCaseInsensitiveSearch]) { - return KPKDatabaseTypeBinary; ++ (KPKDatabaseFormat)versionForFileType:(NSString *)fileType { + if( NSOrderedSame == [fileType compare:MPKdbDocumentUTI options:NSCaseInsensitiveSearch]) { + return KPKDatabaseFormatKdb; } - if( NSOrderedSame == [fileType compare:MPXMLDocumentUTI options:NSCaseInsensitiveSearch]) { - return KPKDatabaseTypeXml; + if( NSOrderedSame == [fileType compare:MPKdbxDocumentUTI options:NSCaseInsensitiveSearch]) { + return KPKDatabaseFormatKdbx; } - return KPKDatabaseTypeUnknown; + return KPKDatabaseFormatUnknown; } -+ (NSString *)fileTypeForVersion:(KPKDatabaseType)version { - switch(version) { - case KPKDatabaseTypeBinary: - return MPLegacyDocumentUTI; ++ (NSString *)fileTypeForVersion:(KPKDatabaseFormat)format { + switch(format) { + case KPKDatabaseFormatKdb: + return MPKdbDocumentUTI; - case KPKDatabaseTypeXml: - return MPXMLDocumentUTI; + case KPKDatabaseFormatKdbx: + return MPKdbxDocumentUTI; default: return @"Unknown"; @@ -134,7 +134,6 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou self = [self init]; if(self) { self.tree = [[KPKTree alloc] initWithTemplateContents]; - self.tree.metaData.rounds = [[NSUserDefaults standardUserDefaults] integerForKey:kMPSettingsKeyDefaultPasswordRounds]; } return self; } @@ -183,15 +182,15 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou return nil; // Saving without a password/key is not possible } NSString *fileType = self.fileTypeFromLastRunSavePanel; - KPKDatabaseType version = [self.class versionForFileType:fileType]; - if(version == KPKDatabaseTypeUnknown) { + KPKDatabaseFormat format = [self.class versionForFileType:fileType]; + if(format == KPKDatabaseFormatUnknown) { if(outError != NULL) { NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"UNKNOWN_FILE_VERSION", "") }; *outError = [NSError errorWithDomain:MPErrorDomain code:0 userInfo:userInfo]; } return nil; // We do not know what version to save! } - return [self.tree encryptWithPassword:self.compositeKey forVersion:version error:outError]; + return [self.tree encryptWithKey:self.compositeKey format:format error:outError]; } - (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError { @@ -342,7 +341,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou [self.undoManager removeAllActions]; NSError *error; /* TODO let the tree chose the encryption */ - self.encryptedData = [self.tree encryptWithPassword:self.compositeKey forVersion:KPKDatabaseTypeXml error:&error]; + self.encryptedData = [self.tree encryptWithKey:self.compositeKey format:KPKDatabaseFormatKdbx error:&error]; if(nil == self.encryptedData && error ) { [self presentError:error]; return; @@ -354,7 +353,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou - (BOOL)unlockWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL error:(NSError *__autoreleasing*)error{ self.compositeKey = [[KPKCompositeKey alloc] initWithPassword:password key:keyFileURL]; - self.tree = [[KPKTree alloc] initWithData:self.encryptedData password:self.compositeKey error:error]; + self.tree = [[KPKTree alloc] initWithData:self.encryptedData key:self.compositeKey error:error]; BOOL isUnlocked = (nil != self.tree); @@ -410,7 +409,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou } #pragma mark Properties -- (KPKDatabaseType)versionForFileType { +- (KPKDatabaseFormat)versionForFileType { return [[self class] versionForFileType:self.fileType]; } diff --git a/MacPass/MPDocumentController.m b/MacPass/MPDocumentController.m index 1ebb3b6a..d6773153 100644 --- a/MacPass/MPDocumentController.m +++ b/MacPass/MPDocumentController.m @@ -34,7 +34,7 @@ NSArray *topLevelObjects; [myBundle loadNibNamed:@"OpenPanelAccessoryView" owner:self topLevelObjects:&topLevelObjects]; } - self.openPanel.allowedFileTypes = @[MPLegacyDocumentUTI, MPXMLDocumentUTI]; + self.openPanel.allowedFileTypes = @[MPKdbDocumentUTI, MPKdbxDocumentUTI]; self.allowAllCheckBox.state = NSOffState; self.showHiddenCheckBox.state = NSOffState; self.openPanel.accessoryView = self.accessoryView; @@ -46,7 +46,7 @@ BOOL allowAllFiles = HNHUIBoolForState(button.state); /* Toggle hidden to force a refresh */ self.openPanel.showsHiddenFiles = !self.openPanel.showsHiddenFiles; - self.openPanel.allowedFileTypes = allowAllFiles ? nil : @[MPLegacyDocumentUTI, MPXMLDocumentUTI]; + self.openPanel.allowedFileTypes = allowAllFiles ? nil : @[MPKdbDocumentUTI, MPKdbxDocumentUTI]; self.openPanel.showsHiddenFiles = !self.openPanel.showsHiddenFiles; } diff --git a/MacPass/MPDocumentWindowController.m b/MacPass/MPDocumentWindowController.m index 669fdb55..4626b332 100644 --- a/MacPass/MPDocumentWindowController.m +++ b/MacPass/MPDocumentWindowController.m @@ -198,8 +198,8 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); MPDocument *document = self.document; NSString *fileType = document.fileType; /* we did open as legacy */ - if([fileType isEqualToString:MPLegacyDocumentUTI]) { - if(document.tree.minimumType != KPKDatabaseTypeBinary) { + if([fileType isEqualToString:MPKdbDocumentUTI]) { + if(document.tree.minimumType != KPKDatabaseFormatKdb) { NSAlert *alert = [[NSAlert alloc] init]; alert.alertStyle = NSWarningAlertStyle; alert.messageText = NSLocalizedString(@"WARNING_ON_LOSSY_SAVE", ""); diff --git a/MacPass/MPSavePanelAccessoryViewController.h b/MacPass/MPSavePanelAccessoryViewController.h index 5663e725..1e7138a9 100644 --- a/MacPass/MPSavePanelAccessoryViewController.h +++ b/MacPass/MPSavePanelAccessoryViewController.h @@ -15,7 +15,7 @@ @property (nonatomic, weak) NSSavePanel *savePanel; @property (nonatomic, weak) MPDocument *document; -@property (nonatomic, assign, readonly) KPKDatabaseType selectedVersion; +@property (nonatomic, assign, readonly) KPKDatabaseFormat selectedVersion; @property (nonatomic, weak) IBOutlet NSPopUpButton *fileTypePopupButton; @property (nonatomic, weak) IBOutlet NSTextField *infoTextField; diff --git a/MacPass/MPSavePanelAccessoryViewController.m b/MacPass/MPSavePanelAccessoryViewController.m index f884bf57..51b79bdc 100644 --- a/MacPass/MPSavePanelAccessoryViewController.m +++ b/MacPass/MPSavePanelAccessoryViewController.m @@ -13,7 +13,7 @@ #import "KeePassKit/KeePassKit.h" @interface MPSavePanelAccessoryViewController () -@property (readwrite, assign) KPKDatabaseType selectedVersion; +@property (readwrite, assign) KPKDatabaseFormat selectedVersion; @end @implementation MPSavePanelAccessoryViewController @@ -41,11 +41,11 @@ - (IBAction)setFileType:(id)sender { NSString *uti = self.fileTypePopupButton.selectedItem.representedObject; - if([uti isEqualToString:MPLegacyDocumentUTI]) { - self.selectedVersion = KPKDatabaseTypeBinary; + if([uti isEqualToString:MPKdbDocumentUTI]) { + self.selectedVersion = KPKDatabaseFormatKdb; } - else if([uti isEqualToString:MPXMLDocumentUTI]) { - self.selectedVersion = KPKDatabaseTypeXml; + else if([uti isEqualToString:MPKdbxDocumentUTI]) { + self.selectedVersion = KPKDatabaseFormatKdbx; } NSAssert(uti != nil, @"UTI cannot be nil"); [self _updateNote]; @@ -66,10 +66,10 @@ NSView *view = self.view; NSAssert(view != nil, @"View has to be loaded at this point"); switch(self.document.versionForFileType) { - case KPKDatabaseTypeBinary: + case KPKDatabaseFormatKdb: [self.fileTypePopupButton selectItemAtIndex:1]; break; - case KPKDatabaseTypeXml: + case KPKDatabaseFormatKdbx: [self.fileTypePopupButton selectItemAtIndex:0]; break; default: @@ -82,7 +82,7 @@ - (void)_updateNote { NSString *uti = self.fileTypePopupButton.selectedItem.representedObject; - BOOL showInfoText = (self.document.tree.minimumType == KPKDatabaseTypeXml && [uti isEqualToString:MPLegacyDocumentUTI]); + BOOL showInfoText = (self.document.tree.minimumType == KPKDatabaseFormatKdbx && [uti isEqualToString:MPKdbDocumentUTI]); self.infoTextField.hidden = !showInfoText; } diff --git a/MacPass/MPSettingsHelper.h b/MacPass/MPSettingsHelper.h index 64d82ea6..36de2aca 100644 --- a/MacPass/MPSettingsHelper.h +++ b/MacPass/MPSettingsHelper.h @@ -76,7 +76,6 @@ typedef NS_ENUM(NSUInteger, MPDoubleClickTitleAction) { /* Password Generation */ APPKIT_EXTERN NSString *const kMPSettingsKeyCopyGeneratedPasswordToClipboard; -APPKIT_EXTERN NSString *const kMPSettingsKeyDefaultPasswordRounds; APPKIT_EXTERN NSString *const kMPSettingsKeyDefaultPasswordLength; APPKIT_EXTERN NSString *const kMPSettingsKeyPasswordCharacterFlags; APPKIT_EXTERN NSString *const kMPSettingsKeyPasswordUseCustomString; @@ -109,4 +108,4 @@ typedef NS_ENUM(NSUInteger, MPPasswordEncoding) { */ + (NSString *)defaultControllerPathForKey:(NSString *)key; -@end \ No newline at end of file +@end diff --git a/MacPass/MPSettingsHelper.m b/MacPass/MPSettingsHelper.m index 94f42793..b04243ce 100644 --- a/MacPass/MPSettingsHelper.m +++ b/MacPass/MPSettingsHelper.m @@ -47,7 +47,6 @@ NSString *const kMPSettingsKeyEnableQuicklookPreview = @"Enable NSString *const kMPSettingsKeyCopyGeneratedPasswordToClipboard = @"CopyGeneratedPasswordToClipboard"; -NSString *const kMPSettingsKeyDefaultPasswordRounds = @"KeyDefaultPasswordRounds"; NSString *const kMPSettingsKeyDefaultPasswordLength = @"DefaultPasswordLength"; NSString *const kMPSettingsKeyPasswordCharacterFlags = @"PasswordCharacterFlags"; NSString *const kMPSettingsKeyPasswordUseCustomString = @"PasswordUseCustomString"; @@ -70,6 +69,7 @@ NSString *const kMPDeprecatedSettingsKeyEntrySearchFilterMode = @"En NSString *const kMPDeprecatedSettingsKeyHttpPort = @"HttpPort"; NSString *const kMPDeprecatedSettingsKeyEnableHttpServer = @"EnableHttpServer"; NSString *const kMPDeprecatedSettingsKeyShowMenuItem = @"ShowMenuItem"; +NSString *const kMPDeprecatedSettingsKeyDefaultPasswordRounds = @"KeyDefaultPasswordRounds"; @implementation MPSettingsHelper @@ -118,7 +118,6 @@ NSString *const kMPDeprecatedSettingsKeyShowMenuItem = @"Sh kMPSettingsKeyAutotypeMatchTags: @NO, kMPSettingsKeyEnableQuicklookPreview: @NO, kMPSettingsKeyCopyGeneratedPasswordToClipboard: @NO, - kMPSettingsKeyDefaultPasswordRounds: @50000, kMPSettingsKeyDefaultPasswordLength: @12, kMPSettingsKeyPasswordCharacterFlags: @(MPPasswordCharactersAll), kMPSettingsKeyPasswordUseCustomString: @NO, @@ -141,6 +140,7 @@ NSString *const kMPDeprecatedSettingsKeyShowMenuItem = @"Sh kMPDeprecatedSettingsKeyDocumentsAutotypeFixNoteWasShown, kMPDeprecatedSettingsKeyDoubleClickURLToLaunch, kMPDeprecatedSettingsKeyEntrySearchFilterMode, + kMPDeprecatedSettingsKeyDefaultPasswordRounds, /* Moved to KeePassHttp Plugin */ kMPDeprecatedSettingsKeyHttpPort, kMPDeprecatedSettingsKeyEnableHttpServer, diff --git a/MacPassTests/MPDatabaseLoading.m b/MacPassTests/MPDatabaseLoading.m index dea66244..f6cf0d9c 100644 --- a/MacPassTests/MPDatabaseLoading.m +++ b/MacPassTests/MPDatabaseLoading.m @@ -28,7 +28,7 @@ XCTAssertTrue(document.encrypted, @"Loaded but unencrypted should be not decrypted"); XCTAssertTrue([document unlockWithPassword:@"1234" keyFileURL:nil error:&error], @"Should decrypt with password"); XCTAssertNil(error, @"No Error should occur on unlocking with correct password"); - XCTAssertTrue((document.tree.minimumType = KPKDatabaseTypeBinary), @"Minimal Version should not increase with KDB File loaded"); + XCTAssertTrue((document.tree.minimumType = KPKDatabaseFormatKdb), @"Minimal Version should not increase with KDB File loaded"); //STAssertTrue([document.fileType isEqualToString:[MPDocument fileTypeForVersion:KPKLegacyVersion]], @"File type needs to match opened file"); } diff --git a/MacPassTests/MPTestDocument.m b/MacPassTests/MPTestDocument.m index db290108..dfe17265 100644 --- a/MacPassTests/MPTestDocument.m +++ b/MacPassTests/MPTestDocument.m @@ -28,7 +28,7 @@ - (void)testCreateUntitledDocument { MPDocument *document = [[MPDocument alloc] initWithType:@"" error:nil]; XCTAssertNotNil(document, @"Document should be created"); - XCTAssertTrue(document.tree.minimumType == KPKDatabaseTypeBinary, @"Tree should be Legacy Version in default case"); + XCTAssertTrue(document.tree.minimumType == KPKDatabaseFormatKdb, @"Tree should be Legacy Version in default case"); XCTAssertFalse(document.encrypted, @"Document cannot be encrypted at creation"); XCTAssertFalse(document.compositeKey.hasPasswordOrKeyFile, @"Document has no Password/Keyfile and thus is not secured");