Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TouchID unlock Feature for MacPass. #1089

Merged
merged 22 commits into from
Aug 31, 2022

Conversation

juliuszint
Copy link
Contributor

@juliuszint juliuszint commented Jun 28, 2020

Feature

This patch enables MacPass users to unlock their KeePass containers with TouchID. In contrast to #638, the implementation does not store the master password directly into the keychain of macOS. Instead it creates a RSA 2048 key pair and uses the public key to encrypt the password. The encrypted password is then kept in memory as long as the MacPass process is alive.

The private key is then used on a subsequent unlock to decrypt the master password. macOS will only return the private key if the device is unlocked and a user, who`s fingerprints were enrolled at the time the key pair was created, authenticates via TouchID.

On every launch of MacPass the user has to supply the master password once for TouchID unlock to work. This is a trade of between security and convenience. But on macOS system restarts are fewer than on windows and the MacPass process stays alive, even if all windows are closed.

Todo

    • SecKeyGeneratePair returns with the error: Required entitlement isn't present if the Keychain Sharing capability is not enabled. For this reason i tested most of this code in a small test project with this capability enabled. For testing in MacPass i commented out this line. With this change the key is created successfully even if the entitlement is not set. This is only for testing purposes since the user is not prompted for authentication via TouchID.
      In short: it would be great if someone could enable this entitlement and build a signed version to actually verify it.
    • The used dictionary supports storing passwords for multiple KeePass databases. Right now the constant key @DatabaseID is used and needs to be replaced in order to support multiple databases.
    • I have no prior experience programming in Objective-C. So a very detailed code review would be appreciated especially concerning memory management. The bulk of the new code is around 150 lines so it should not be too time consuming.
    • static variables are often viewed as bad practice. i am open to changing this to something that gets injected. For the first pull request this was the easiest way.

@georgesnow
Copy link
Contributor

Cool so is this fully working? I had been working on it but just have had limited time to finish. There was one other person who was working on GUI implementation which was the last piece. Did you fork out work or is this from scratch?

@georgesnow
Copy link
Contributor

Ok So I read further. I will take a look. I am not married to the implementation I was working on. If this is a better and the preferred direction.

@juliuszint
Copy link
Contributor Author

@georgesnow Its written from scratch and with the Keychain sharing entitlement enabled, it should be fully functional. If you could enable this entitlement and build a signed version of MacPass it should in theory work.

@georgesnow
Copy link
Contributor

@juliuszint i tried it. I am having code signing issues with enabling Keychain sharing. I believe I have been able to use this entitlement before without a paid developer cert. I could be wrong though. I can't seem to get the correct configuration as it crashes on launch because of the code signing.

This would be my only hesitation with this implementation. If you have to have paid dev cert to use this entitlement. Then for the people who build MacPass from code (like me). They won't be able use this feature without the paid developer cert. Or you have to add flags to compile with the feature turned off, which adds complexity.

I like that this implementation as it seems to be more secure. It will require more investigation to figure out if and how you can build it without paid developer cert.

@juliuszint
Copy link
Contributor Author

juliuszint commented Jul 30, 2020

@georgesnow thanks for trying it out. My own Apple account is not a paid either, but it is part of a Team that pays the 100$ annually (not sure if this makes it a paid account).

With the latest changes that i have pushed, i was able to build an run it locally and have the TouchID Feature working as expected for a single database. I would appreciate if you could try it as well by doing the following steps.

  1. Pull the latest changes from the feature-touchidunlock branch.
  2. Create a clean working directory by executing git clean -fdx && git reset --hard
  3. Restore frameworks by executing carthage bootstrap --platform macOS
  4. Open MacPass in Xcode
  5. Goto the Siging & Capabilities tab of MacPass
  6. Turn on Automatically manage signing
  7. For Team select your Personal Team (for Debug and Release)
  8. Change the Bundle identifier (e. g. com.$(YOURNAME).macpass)
  9. Compile and Run -> Open a Container -> Lock it -> TouchID unlock button should be visible

}
else {
NSError *err = CFBridgingRelease(error);
NSLog(@"Error while trying decrypt password for TouchID unlock: %@", [err description]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing to between trying and decrypt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Thanks for the review.

@georgesnow
Copy link
Contributor

From what I gathered on apple’s website that keychain sharing doesn’t require a paid developer certificate. I will give it go.

@corporate-gadfly
Copy link

corporate-gadfly commented Jul 30, 2020

I tried to give it a fair shot to try to build MacPass:

  • 7G+ Xcode download/install
  • carthage issues while bootstrapping due to ln from coreutils
  • navigating the code signing minefield of Xcode
  • compile errors after all of that

I'm inclined to wait for official releases, at this point. Unless people are prepared to do some more hand holding.

@corporate-gadfly
Copy link

Not a mac coder, but here is what I tried:

$  carthage bootstrap --platform macOS
*** Checking out HNHUi at "3.0"
*** Checking out KeePassKit at "2.4.7"
*** Checking out TransformerKit at "b28de3a7de9249dd886979cae4985092523b6dd1"
*** Checking out KissXML at "5.3.1"
*** Checking out Sparkle at "1.22.0"
*** xcodebuild output can be found in /var/folders/4h/f2lfvd8x1zl4pnk6j72cknb80000gn/T/carthage-xcodebuild.Cl49mr.log
*** Downloading KissXML.framework binary at "Version 5.3.1"
*** Downloading Sparkle.framework binary at "Many small improvements"
*** Building scheme "HNHUi" in HNHUi.xcodeproj
*** Building scheme "KeePassKit macOS" in KeePassKit.xcodeproj
*** Building scheme "Sparkle" in Sparkle.xcodeproj
*** Building scheme "TransformerKit macOS" in TransformerKit.xcworkspace
  • Followed @juliuszint instructions about code signing.
  • Clicked the play button and got the error about DDHotKeyCenter.h file not found
    image

@juliuszint
Copy link
Contributor Author

* Followed @juliuszint instructions about code signing.

* Clicked the play button and got the error about `DDHotKeyCenter.h` file not found

I think the only thing you need to do is to add the --recursive flag when cloning the repository.

@corporate-gadfly
Copy link

Thanks for that tip @juliuszint . For an existing cloned directory, I issued:

git submodule update --init --recursive

and that brought in submodule DDHotKey. I have a working MacPass binary now.

@corporate-gadfly
Copy link

corporate-gadfly commented Jul 30, 2020

I have a .kdbx with an associated keyfile. After locking the container, here is what I see:
image

Perhaps I missed something. Thanks in advance.

@corporate-gadfly
Copy link

Works fine with a .kdbx which does not have a keyfile. See:
image
Hope that helps.

@juliuszint
Copy link
Contributor Author

I have a .kdbx with an associated keyfile. After locking the container, here is what I see:

Perhaps I missed something. Thanks in advance.

That is indeed something i have not implemented yet. I have to take a closer look at how big these keyfiles are and whether it is possible to pass a memory stream to the underlying layers instead of a filename.

@juliuszint
Copy link
Contributor Author

The latest commit enables support for multiple Databases. Any feedback is appreciated.

@corporate-gadfly
Copy link

corporate-gadfly commented Aug 16, 2020

No luck, unfortunately. I'm not sure, if this was intended for me (multiple databases)?
image

-edit- never mind. I was using the wrong .kdbx file. So, no change from my perspective.

@juliuszint
Copy link
Contributor Author

juliuszint commented Aug 17, 2020

No luck, unfortunately. I'm not sure, if this was intended for me (multiple databases)?

It was indendet for everyone who wants to give it a shot, but keyfiles are sadly still not supported. But you can now for example unlock Secrets.kdbx and Secrets2.kdbx with TouchID undlock. (Previously you could only open a single one)

@mstarke
Copy link
Member

mstarke commented Aug 17, 2020

[...] but keyfiles are sadly still not supported.

Currently the completion handler uses the password and the key file url as parameters. You store the encrypted password and restore it when unlocking. Refactoring this to use the KPKCompositeKey might allow for a better way to store the complete key and not only a part of it. This would require KPKCompositeKey to conform to NSCoding.

Another way might be to simply store the url as well and then retrieve it. This would add a bit of security since the key-file still needs to be present when unlocking (e.g. when it's stored on a thumb drive)

@juliuszint
Copy link
Contributor Author

Currently the completion handler uses the password and the key file url as parameters. You store the encrypted password and restore it when unlocking. Refactoring this to use the KPKCompositeKey might allow for a better way to store the complete key and not only a part of it. This would require KPKCompositeKey to conform to NSCoding.

This seems to me like the best option after thinking about it. While TouchID unlock can eliminate attack vectors like shoulder surfing, when you unlock your database in a public place. Ultimately it lowers the security, by introducing another way (that might contain security vulnerabilities) to unlock your database.

The TouchID feature should be optional anyway, so if the user decides to trade in security for ease of use, then we might as well cache the keyfile in memory. @mstarke Would you agree with that?

@juliuszint
Copy link
Contributor Author

juliuszint commented Aug 22, 2020

Databases with key files are now supported. If you want to try it out, you have to apply the following patch first.

diff --git a/Cartfile b/Cartfile
index a54864ad..46ba2d12 100644
--- a/Cartfile
+++ b/Cartfile
@@ -1,4 +1,4 @@
 github "sparkle-project/Sparkle" ~> 1.22
 github "MacPass/TransformerKit" "b28de3a7de9249dd886979cae4985092523b6dd1"
-github "MacPass/KeePassKit" ~> 2.4
+github "juliuszint/KeePassKit" "ff730f290c142398d57ddb9e78636df1f92c9878"
 github "mstarke/HNHUi" ~> 3.0

After this you need to run carthage update --platform macOS and then just build.

@corporate-gadfly
Copy link

Note to self: ln from coreutils does not work with carthage.

Can't get the Touch ID button to appear:
touchid-macpass
Ideas?

@juliuszint
Copy link
Contributor Author

Ideas?

Some more information would be good. First: The Xcode Application output while Debugging would be good. Second: The output of git diff inside your working directory.

@corporate-gadfly
Copy link

Some more information would be good. First: The Xcode Application output while Debugging would be good. Second: The output of git diff inside your working directory.

Not sure if this is what you're looking for, but in Xcode, under Target Output, I see the following when I click the 'Unlock' button:

2020-08-23 14:04:48.694891-0400 MacPass[15342:8309368] -[KPKCompositeKey encodeWithCoder:]: unrecognized selector sent to instance 0x600000261aa0
2020-08-23 14:04:48.695199-0400 MacPass[15342:8309368] [General] -[KPKCompositeKey encodeWithCoder:]: unrecognized selector sent to instance 0x600000261aa0
2020-08-23 14:04:48.696748-0400 MacPass[15342:8309368] [General] (
	0   CoreFoundation                      0x00007fff34380b57 __exceptionPreprocess + 250
	1   libobjc.A.dylib                     0x00007fff6d1c75bf objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff343ffbe7 -[NSObject(NSObject) __retain_OA] + 0
	3   CoreFoundation                      0x00007fff342e53bb ___forwarding___ + 1427
	4   CoreFoundation                      0x00007fff342e4d98 _CF_forwarding_prep_0 + 120
	5   Foundation                          0x00007fff36988cad _encodeObject + 1214
	6   Foundation                          0x00007fff36a30c5c +[NSKeyedArchiver archivedDataWithRootObject:] + 133
	7   MacPass                             0x000000010002f48f -[MPPasswordInputController _storePasswordForTouchIDUnlock:forDatabase:] + 143
	8   MacPass                             0x000000010002eb99 -[MPPasswordInputController _submit:] + 1289
	9   AppKit                              0x00007fff317b77a7 -[NSApplication(NSResponder) sendAction:to:from:] + 299
	10  AppKit                              0x00007fff317b7642 -[NSControl sendAction:to:] + 86
	11  AppKit                              0x00007fff317b7574 __26-[NSCell _sendActionFrom:]_block_invoke + 136
	12  AppKit                              0x00007fff317b7476 -[NSCell _sendActionFrom:] + 171
	13  AppKit                              0x00007fff317b73bd -[NSButtonCell _sendActionFrom:] + 96
	14  AppKit                              0x00007fff317b369b NSControlTrackMouse + 1745
	15  AppKit                              0x00007fff317b2fa2 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 130
	16  AppKit                              0x00007fff317b2e61 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 691
	17  AppKit                              0x00007fff317b21dd -[NSControl mouseDown:] + 748
	18  AppKit                              0x00007fff317b05f0 -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4914
	19  AppKit                              0x00007fff3171ae21 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 2612
	20  AppKit                              0x00007fff3171a1c9 -[NSWindow(NSEventRouting) sendEvent:] + 349
	21  AppKit                              0x00007fff31718554 -[NSApplication(NSEvent) sendEvent:] + 352
	22  AppKit                              0x00007fff315655bf -[NSApplication run] + 707
	23  AppKit                              0x00007fff31537396 NSApplicationMain + 777
	24  MacPass                             0x000000010000eab6 main + 54
	25  libdyld.dylib                       0x00007fff6e36fcc9 start + 1
	26  ???                                 0x0000000000000005 0x0 + 5
)
2020-08-23 14:04:48.698265-0400 MacPass[15342:8309368] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.

git diff:

diff --git a/Cartfile b/Cartfile
index a54864ad..46ba2d12 100644
--- a/Cartfile
+++ b/Cartfile
@@ -1,4 +1,4 @@
 github "sparkle-project/Sparkle" ~> 1.22
 github "MacPass/TransformerKit" "b28de3a7de9249dd886979cae4985092523b6dd1"
-github "MacPass/KeePassKit" ~> 2.4 
+github "MacPass/KeePassKit" "ff730f290c142398d57ddb9e78636df1f92c9878"
 github "mstarke/HNHUi" ~> 3.0
diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj
index c8f89e9c..cff5ceae 100644
--- a/MacPass.xcodeproj/project.pbxproj
+++ b/MacPass.xcodeproj/project.pbxproj
@@ -1843,11 +1843,12 @@
 			isa = PBXProject;
 			attributes = {
 				CLASSPREFIX = MP;
-				LastUpgradeCheck = 1130;
+				LastUpgradeCheck = 1160;
 				ORGANIZATIONNAME = "HicknHack Software GmbH";
 				TargetAttributes = {
 					4C77E36115B84A240093A587 = {
-						DevelopmentTeam = 55SM4L4Z97;
+						DevelopmentTeam = WNWAMP88G8;
+						ProvisioningStyle = Automatic;
 					};
 				};
 			};
@@ -2961,9 +2962,11 @@
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
 				CODE_SIGN_ENTITLEMENTS = MacPass/MacPass.entitlements;
-				CODE_SIGN_IDENTITY = "";
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
 				CURRENT_PROJECT_VERSION = "${CURRENT_PROJECT_VERSION}";
+				DEVELOPMENT_TEAM = WNWAMP88G8;
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(PROJECT_DIR)/Carthage/Build/Mac",
@@ -2976,9 +2979,10 @@
 					"-lxml2",
 					"-Wl,-rpath,@loader_path/../Frameworks",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "com.hicknhacksoftware.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_BUNDLE_IDENTIFIER = com.XXXXXX_NAME_HIDDEN_XXXX.MacPass;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE = "";
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SDKROOT = macosx;
 				STRIP_STYLE = debugging;
 				WRAPPER_EXTENSION = app;
@@ -2992,9 +2996,11 @@
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_ARC = YES;
 				CODE_SIGN_ENTITLEMENTS = MacPass/MacPass.entitlements;
-				CODE_SIGN_IDENTITY = "";
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
 				CURRENT_PROJECT_VERSION = "${CURRENT_PROJECT_VERSION}";
+				DEVELOPMENT_TEAM = WNWAMP88G8;
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(PROJECT_DIR)/Carthage/Build/Mac",
@@ -3008,9 +3014,10 @@
 					"-lxml2",
 					"-Wl,-rpath,@loader_path/../Frameworks",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "com.hicknhacksoftware.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_BUNDLE_IDENTIFIER = com.XXXXXX_NAME_HIDDEN_XXXX.MacPass;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE = "";
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SDKROOT = macosx;
 				STRIP_STYLE = debugging;
 				WRAPPER_EXTENSION = app;
diff --git a/MacPass.xcodeproj/xcshareddata/xcschemes/MacPass.xcscheme b/MacPass.xcodeproj/xcshareddata/xcschemes/MacPass.xcscheme
index f693d37d..9f3f7d72 100644
--- a/MacPass.xcodeproj/xcshareddata/xcschemes/MacPass.xcscheme
+++ b/MacPass.xcodeproj/xcshareddata/xcschemes/MacPass.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1130"
+   LastUpgradeVersion = "1160"
    version = "2.0">
    <BuildAction
       parallelizeBuildables = "YES"

Hope that helps.

@juliuszint
Copy link
Contributor Author

juliuszint commented Aug 23, 2020

I think i have spotted a mistake on my side. I updated the diff that needs to be applied to the Cartfile. Would you be willing to give it one more shot? Revert the Cartfile with git checkout Cartfile and then once again apply the updated diff. Thanks for trying it out.

@corporate-gadfly
Copy link

Cartfile.resolved is still dated from July 30th (even after running carthage update --platform macOS):

$ stat -c "%y %s %n" Cartfile.resolved
2020-07-30 13:15:57.040797864 -0400 220 Cartfile.resolved

Output of git diff Cartfile:

diff --git a/Cartfile b/Cartfile
index a54864ad..934f12ad 100644
--- a/Cartfile
+++ b/Cartfile
@@ -1,4 +1,4 @@
 github "sparkle-project/Sparkle" ~> 1.22
 github "MacPass/TransformerKit" "b28de3a7de9249dd886979cae4985092523b6dd1"
-github "MacPass/KeePassKit" ~> 2.4 
+github "juliuszint/KeePassKit" "ff730f290c142398d57ddb9e78636df1f92c9878"
 github "mstarke/HNHUi" ~> 3.0

@corporate-gadfly
Copy link

Output of carthage update --platform macOS:

*** Checking out Sparkle at "1.22.0"
*** Checking out KeePassKit at "2.4.7"
*** Checking out HNHUi at "3.0"
*** Checking out TransformerKit at "b28de3a7de9249dd886979cae4985092523b6dd1"
*** Checking out KissXML at "5.3.1"
*** xcodebuild output can be found in /var/folders/4h/f2lfvd8x1zl4pnk6j72cknb80000gn/T/carthage-xcodebuild.n6kSKh.log
*** Downloading KissXML.framework binary at "Version 5.3.1"
*** Downloading Sparkle.framework binary at "Many small improvements"
*** Building scheme "HNHUi" in HNHUi.xcodeproj
*** Building scheme "KeePassKit macOS" in KeePassKit.xcodeproj
*** Building scheme "Sparkle" in Sparkle.xcodeproj
*** Building scheme "TransformerKit macOS" in TransformerKit.xcworkspace

@juliuszint
Copy link
Contributor Author

juliuszint commented Aug 23, 2020

Thats odd. I myself am no expert with carthage. You could try to just update the resolved file itself and replace the KeePassKit line. At that point it should work in my opinion. But you do need to run carthage update --platform macOS after changing it.

@corporate-gadfly
Copy link

Everything works (including unlock with touch ID while a database uses a key file):

  1. Updated Cartfile.resolved manually
  2. Ran carthage update --platform macOS:
    Saw the following output:
    *** Checking out KeePassKit at "ff730f290c142398d57ddb9e78636df1f92c9878"
    ***  Fetching KeePassKit
    

Fantastic work and appreciate your help.

Looking forward to the pull request being merged.

@corporate-gadfly
Copy link

My daily driver is the "other" program. Hoping to use MacPass as a daily driver.

@mstarke
Copy link
Member

mstarke commented Aug 23, 2022

@juliuszint Just a heads-up. I've merged your code. I've started refactoring it to slim down the view controller a bit. The UI has not changed but I have an idea to use a more verbose system than the check-box. The three-state checkbox is an elegant solution but I did find it a bit too undiscoverable. MacPass tends to have those things but I have to try to minimize that so people actually find stuff and how it works :)

@mstarke
Copy link
Member

mstarke commented Aug 31, 2022

Another status update: Merge is complete. Everything works. A couple of memory mananagement issues where also fixed in the process. I did change the touchID unlock button but this isn't final.
Screenshot 2022-08-31 at 14 40 24

I do want to change the ui a bit more. TouchID settings with a popup button. Hide the password and keyfile input when touchID is available.

@hasnolen
Copy link

Can you push the merged branch if you get a chance? I’ve been working off of this branch for basically years now (rebuilding every month to get around the licensing issue) and would love to test it immediately.

@mstarke
Copy link
Member

mstarke commented Aug 31, 2022

@hasnolen sure will do.

@mstarke
Copy link
Member

mstarke commented Aug 31, 2022

The checkbox on the password input screen bothers me. All other password managers set those things inside the preferences since it's an global application setting and has nothing to do with an individual database.

Would it be so bad to move this into an own settings tab "Biometrics" and let the user decide what to do there? This would also allow for some explanations to get the user to understand better what's going on? This then could be coupled with the regeneration of the encryptions keys and might even go as far as show a list of all known databases and the ability to purge them selectively?

@mstarke mstarke merged commit 68b8a59 into MacPass:master Aug 31, 2022
@mstarke
Copy link
Member

mstarke commented Aug 31, 2022

I should apologise to @juliuszint for taking so long for merging your awesome feature!

@slashrsm
Copy link

🎉 🎉 👯 🥂

Thank you all!

@slashrsm
Copy link

When can we expect a new release with this feature?

@mstarke
Copy link
Member

mstarke commented Sep 2, 2022

@slashrsm When it's done. But I do intend to release it soon since there are also a couple of bug-fixes included

@juliuszint I did encounter a bit of a problem and wanted to ask what your intentions where:

When the touchID settings (checkbox) is changed, those changes are stored as a user default and then nothing happens. Only after unlocking via typing in the correct password/using the correct key-file does this setting make any effect.
Hence, if you had touchID set to persistent and then unlock with touchID all the time, nothing gets purged. The key is never deleted. Also, this only affects a database at the time. The setting is global, but the effect only local. Meaning: if you disable it globally you have to open each databases with a stored key and unlock with credentials not touchID to clear all keys.

I would change this to the following:

  • Move the key storage from single-key entries to an NSDictionary<NSString *, NSData *> in the preferences which helps search since NSUserDefaults cannot be queried with wildcard matching
  • Add or update keys in the dictionary as needed just like now with the entries in NSUserDefaults. This mirrror the storage of transient keys
  • Maybe store the document keys as hashed values not as clear text file names
  • remove all keys according to touchId settings directly on change an on startup if the setting was changed outside of MacPass via the command line
  • evaluate touchId Setting for every unlock type (touchId or normal) just to be sure
  • Add user feedback if stored touchID key is wrong and allow user to clear it (or do it automatically)

@juliuszint
Copy link
Contributor Author

@juliuszint I did encounter a bit of a problem and wanted to ask what your intentions where:

When the touchID settings (checkbox) is changed, those changes are stored as a user default and then nothing happens. Only after unlocking via typing in the correct password/using the correct key-file does this setting make any effect. Hence, if you had touchID set to persistent and then unlock with touchID all the time, nothing gets purged. The key is never deleted. Also, this only affects a database at the time. The setting is global, but the effect only local. Meaning: if you disable it globally you have to open each databases with a stored key and unlock with credentials not touchID to clear all keys.

There were to reasons for this approach.

  1. Keep it as simple as possible to make the code review easy on the eyes and also to reduce the likelihood of me introducing any security vulnerabilities.
  2. Preventing unauthenticated users from changing settings for my KeePass database. I think it is still very much possible to just edit the plist but it makes it a little bit more complicated.

All of the changes that you proposed will either improve the user experience or the security (hashed filenames) and are therefore a good thing. Sorry for taking so long to respond and I am looking forward to seeing the improvements that you are implementing.

@mstarke
Copy link
Member

mstarke commented Sep 24, 2022

@juliuszint No worries about the delay. I'm the last one that is allowed to complain about having to wait. Your goal to keep it simple makes sense and explains your approach. About point 2: That's something I haven't – shockingly – thought about. There are a couple of ways to deal with this:

  1. Change the settings directly after the user has altered them. The only thing a third party can do is remove the convenience for you to unlock your databases. You should have the keys to them as well so you should be able to unlock without touchID as well.
  2. Update the settings only after a successfull unlock attempt regardless of method. If you unlock via TouchID settings get updated as well as if you unlock by providing the normal credentials.
  3. Only allow to set the storage for touch Id if a database is unlocked already. This seems rather cumbersome.

I tend to lean to 2 which makes this a mix of the current solution and the one I had in mind.

@juliuszint
Copy link
Contributor Author

I also think that 2 is the best approach. This also enables the use case of having a system with multiple KeePass files where the user wants to unlock one with TouchID and not the other.

@cfecherolle
Copy link

Hi,
Is there anything we can do to help? (testing, or anything else 😄)
TouchID would be so handy to have in MacPass! I see this has been merged, but no releases have been published since February.
Sorry if my question is stupid, I'm not aware of how this repo and project work.

@mkah911
Copy link

mkah911 commented Nov 3, 2022

Any updates on releasing this change? 😊

@mbay-ODW
Copy link

It's been a while, any news on that?

@emikaadeo-git
Copy link

Also waiting for TouchID feature in MacPass, any ETA for release ? :)

@mstarke
Copy link
Member

mstarke commented Jan 20, 2023

Oh man, what an ass I am. I'm currently drowning in work since we have a tight project that consumes a lot of my energy and spending time with my family is also a nice thing to do so development time for MacPass is sparse right now. I am fully aware of the dreadful timeline and will try my best to push this out ASAP.

@emikaadeo-git
Copy link

Thank you! Will wait

@cfecherolle
Copy link

@mstarke No worries! Personal life and health should always come first. Thank you for the update 😁

@n6g7
Copy link

n6g7 commented May 3, 2023

Hi @mstarke, any chance for an update on this feature? 😃

@ijoseph
Copy link

ijoseph commented Jul 26, 2023

It's merged; it just hasn't been tagged and released; all* you have to do is clone and build from source.

*took me about an hour of intense debugging to actually accomplish this. The issue(s) seem to be that Carthage fails to build the dependencies due to changes in dependent files packaged with XCode itself. Basically, it consisted of hunting down xcodeproj files under <repo_root>/Carthage/Checkouts, opening them with XCode, and removing (1) irrelevant targets (non-macOS) and (2) setting Minimum Deployments to 10.15. Happy to provide details if there's interest.

@jankkm
Copy link

jankkm commented Jul 26, 2023

It's merged; it just hasn't been tagged and released; all* you have to do is clone and build from source.

*took me about an hour of intense debugging to actually accomplish this. The issue(s) seem to be that Carthage fails to build the dependencies due to changes in dependent files packaged with XCode itself. Basically, it consisted of hunting down xcodeproj files under <repo_root>/Carthage/Checkouts, opening them with XCode, and removing (1) irrelevant targets (non-macOS) and (2) setting Minimum Deployments to 10.15. Happy to provide details if there's interest.

I tried doing this but failed. A quick guide would be very helpful. Thanks!

@mstarke
Copy link
Member

mstarke commented Aug 14, 2023

I'll try to get a new release out in August to fix up some long standing issues and get development rolling again.

@dominikIncibit
Copy link

@mstarke when will the new release be available? would love to have this feature

@gabbocz
Copy link

gabbocz commented Jan 5, 2024

Any chance we can get this feature in 2024?

@cathyjf
Copy link

cathyjf commented Jul 7, 2024

I built an unofficial release of MacPass that includes the fingerprint feature. You can find my build here: https://github.com/cathyjf/MacPass/releases/tag/0.8.1.1

@mstarke
Copy link
Member

mstarke commented Jul 11, 2024

@cathyjf awesome! I hope I can make the official version be compatible with your built so users will have a seamless transition. If this fails the only real issue then would be that all your TouchId unlocks won’t work anymore.

Regarding the inner workings the keys have to be associated with a specific database file since the only way to truly determine uniqueness is via the root node id but this is only available for unlocked files. Currently the file name is used wich might require some changes to allow for multiple different files with the same name using different keys. My idea there was so store all known keys for a file name and then iterate through then to unlock the file. This then requires some housekeeping since we need to prevent those list to get too long.

All that aside, I’m thankful for @cathyjf for providing the built until I get “my shit together” and release an official version with this feature!

@cathyjf
Copy link

cathyjf commented Jul 11, 2024

@mstarke, I think that because your release's app bundle will be signed with a different Team ID than mine, your release won't be able to access any items stored in keychain by the app bundle signed by my key. However, as you say, it really won't be a big deal -- it just means that, after upgrading to your build, users will need to authenticate once to their password database in the same way they did before the touch ID feature was added to the app. After that, users can go back to using touch ID normally.

@mstarke
Copy link
Member

mstarke commented Jul 12, 2024

@cathyjf I totally forgot about the team id for signing since Touch ID forces the need to sign the app. Before this feature was present MacPass was able to work with all features without any signing so this is still a bit stuck in my head. Thanks for the clarification!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.