KeePassDX icon indicating copy to clipboard operation
KeePassDX copied to clipboard

Advanced unlocking doesn't replace hardware key authentication

Open kaoneko opened this issue 2 years ago • 6 comments
trafficstars

KeePassDX 3.5.0. Happy to see YubiKey support! I bought the Pro version as a thank you ❤️🙏🏻

While Advanced unlocking says in its settings menu that it Lets you scan your biometric to open the database or Lets you use your device credential to open the database, it doesn't replace authentication with a hardware token (challenge-response), whereas I expected it to work the same no matter what type of credential the database is protected with. Let me explain...

Use case 1, working: I have a database protected with a password as the sole credential. I can provide the password and then tap the fingerprint icon to setup Advanced unlocking. From then on I can unlock the database with my fingerprint.

Use case 2, not working: I have a database protected with a hardware key as the sole credential. I activate Hardware key and select Yubikey challenge-response from the drop down menu. I then tap the fingerprint icon and it says Type in the password, and then click this button (whereas the Password credential wasn't even enabled).

What I expected to happen: I tap the fingerprint icon, it asks to scan my fingerprint and then my hardware key, and from then on lets me unlock the database with my fingerprint and only asks for the hardware key after I make a change to the database. (Just as it would be inconvenient for me to type my password every time I use KeePassDX to fill in some credentials, it's inconvenient to retrieve my keyring and hold it to my phone everytime I use KeePassDX to fill in some credentials.)

I always thought Advanced unlocking just stored the decryption key of the database in the device's TPM, but maybe I misunderstood and it just stores the password. In that case, when my only credential is a hardware key with challenge-response, it should store the response (and do so everytime it changes as well). (And when I also use a password, it should store the combination of password + response I guess, while also providing the option to replace only one of the factors with Advanced unlocking.)

Additionally let me address the fact that people tend to consider a hardware token a second factor for additional security, while it can be perfectly fine to use it as the sole factor. Replacing a password with a hardware key has its own advantages. Please consider this perspective if your gut reaction is something along the lines of "you shouldn't even want to do what you describe here". Thank you.

kaoneko avatar Feb 08 '23 16:02 kaoneko

KeePassDX 3.5.0. Happy to see YubiKey support! I bought the Pro version as a thank you heart🙏🏻

Thank you, it is much appreciated. :tada:

Currently, the advanced unlock connection with the Keystore is only made on the password, so you can always use the other factors separately.

I do not recommend keeping the physical key as the only factor, the best is to cumulate 3 factors: Something you know - the password Something you have - the key file or hardware key Something you are - here unfortunately the fingerprint is not part of the hash as it is not standardized, so I thought I could make the key file compatible with advanced unlocking. https://github.com/Kunzisoft/KeePassDX/issues/1420 https://github.com/Kunzisoft/KeePassDX/issues/1315

The hardware key does not need to be compatible with advanced unlocking, as its purpose is to be present when there is a file opening or modification, otherwise there is no point in having a hardware key.

J-Jamet avatar Feb 08 '23 19:02 J-Jamet

The point is to not have to remember or store a password anywhere. It surprises me how hard it is for people to think outside of the box and see the applications of a hardware key as the sole factor. We use it in so many other areas of our life: homes, cars, lockers. But in ICT, the password is this untouchable foundation of security and everything else is complementary. You're urged to use a hardware key as a second factor, but talk about using it as the FIRST factor and people just can't wrap their minds around it as if the concept is too far out there. At the same time, when you mention using only a password is sufficient for your threat model, people will just urge you to make it a strong randomly generated one. Which is of course what only using a hardware key also accomplishes (the response of a YubiKey is 40 random characters), with the additional benefit of it being much harder to intercept the password.

Using a YubiKey with challenge-response instead of a password gives me:

  • a very long randomly generated password
  • that I don't need to remember, store and type
  • that automatically changes regularly
  • that is much, much harder to intercept than a regular password
  • thus for all but the most skillful attackers, the requirement of being in possession of a physical token to access the database

So the only thing a password would add is protection against real world attacks (i.e. theft of the YubiKey), which are not a part of my threat model. So I trade in the theoretical gain in security for an actual gain in convenience. Everyone's threat model is different of course, but reading discussions on the internet it seems to me that a lot of people are so caught up in theorizing about maximum security that they don't pause to consider someone's threat model.

Forgive me the rant, it's not meant as an attack or anything, just needed to vent that I guess.

Regarding the issue at hand, I realized it's actually not a big inconvenience to scan my YubiKey every once in a while—I don't even need to access my keepass vault that often anyway (on my phone). I just assumed Advanced unlocking would work with any credential, the UI is not clear on the fact that it only works for passwords (hence I chose Bug instead of Feature). And just like with most apps, where you usually only provide the login credentials once and then it remembers them for you and sometimes additionally protects access to the app with your fingerprint or a PIN, I thought I'd provide the credentials to my database only once when setting up my phone and would then be able to access it with my fingerprint. Those were my expectations...

O well, I hope this wall of text provides some insight into the kind of usecase where using just a hardware token to secure a database makes sense and expecting it to work with Advanced unlocking is not as crazy as it may sound ;)

Cheers!

kaoneko avatar Feb 09 '23 18:02 kaoneko

I did not say that only the password was sufficient. I only said it was best to have several factors. You can see the hardware key as the first factor and the others as other factors, it doesn't bother me at all. If you notice, the UI shows switch buttons to select the factors independently of each other, without the need to have a password, so that the user can use the unlocking mode he wants. ;)

I understand that the interface needs to be revised for the advanced unlock association, historically KeePassDX is a fork of KeePassDroid and the fingerprint unlock was only linked to the password. As I said, I would like to improve the concept to make it compatible with the key file as well.

It's not crazy, never says that either, for me it is just not useful to make it compatible with the challenge response because the main purpose of this unlocking is to have an external physical access of the user. When you use your car key, you often register it on another device to unlock your car with your fingerprint?

J-Jamet avatar Feb 09 '23 19:02 J-Jamet

No, but on smartphones it's quite normal to only need full authentication once when setting up an app, and after that being able to access it after unlocking your phone or the app with your fingerprint or PIN, because the device is now "trusted". So I thought of Advanced unlocking in that frame of reference.

kaoneko avatar Feb 12 '23 11:02 kaoneko

With Keepass2Android, once you've unlocked your DB with your Yubikey, you can unlock, read, and autofill from it with only your fingerprint. You do still need the key to edit an entry though (which is fine).

I think you are talking about KeePass2Android's quick unlock (because I don't understand the purpose of unlocking an already unlocked database), but the quick unlock simply leaves the database open in memory, but not visible to the user. This is not a solution : https://github.com/Kunzisoft/KeePassDX/wiki/Advanced-Unlocking#why-not-quick-unlock

The use of the Yubikey is precisely to add a layer of security that REQUIRES an action from the user. If this is not the behavior you are looking for, simply do not use this factor. But it's like every time, you have to make a choice between usability and security.

J-Jamet avatar Apr 23 '23 20:04 J-Jamet

A couple of years ago, after this issue was opened, I reluctantly switched from KeePassDX (even though I had previously purchased the Pro version) to KeePass2Android. The key factor for me is the ability to authenticate with my YubiKey once, then have read-only access to my database until the app is closed or the device is restarted. This feature is absolutely crucial for me. KeePass2Android is a great app, but I honestly prefer KeePassDX a hundred times over, and I desperately want to return to it.

I use my password manager multiple times a day, every day. It's no exaggeration to say that for the past two years, I've wished multiple times a day that this feature could be added to KeePassDX.

The hardware key does not need to be compatible with advanced unlocking, as its purpose is to be present when there is a file opening or modification, otherwise there is no point in having a hardware key.

It's not crazy, never says that either, for me it is just not useful to make it compatible with the challenge response because the main purpose of this unlocking is to have an external physical access of the user. When you use your car key, you often register it on another device to unlock your car with your fingerprint?

I'd like to take a moment to address why I want this feature. I use my KeePass database across 4 devices. A personal laptop, a school laptop, an old desktop, and my phone. I also have four YubiKeys. Three YubiKey nanos, and one full size. All three YubiKey nanos are perpetually left in the three computers. I never take them out.

For me, the purpose of having a YubiKey attached to the database is knowing that there is something physical, not digital, like a Key File, protecting the database in case the database falls into the wrong hands. If somehow the contents of my computer got into the wrong hands, such as a someone obtaining one of my backups or whatever that might look like, I have peace of mind knowing that there is some element to my database that is NOT stored on the computer, it is stored externally in a physical device. This is why a Key File is not, on its own, suitable (although, for what it is worth, I do use both a YubiKey and a Key File).

What I am not worried about is someone stealing my physical devices. Some people are worried about that, but my threat model doesn't call for that. I am fairly confident in the physical security of my devices, and that is why I am OK with doing something like leaving YubiKeys perpetually plugged in.

Given my threat model, I am happy with the balance of requiring a YubiKey to unlock the database in the first instance, but then remembering that credential, at least for read access, for the duration of my "session". This is why I am OK using Keepass2Android's quick unlock, even if it stores the database unlocked and in memory. I want a fingerprint lock so that I can pass my phone to a friend and not have them have unfettered access to all of my logins, but otherwise, I am comfortable leaving the database unlocked on my phone so long as I need the YubiKey to prove myself at the beginning of my session.

Unlike with laptops or desktops, I often use my phone in situations where it’s just not practical to have my YubiKey on hand—whether I’m in bed, in the shower, or using my phone in one hand while exercising. These are unique problems for mobile. For the reasons above, I don't want to simply "remove" the YubiKey. I like the peace of mind of the physical device, and on every other device besides my phone, I can leave the key plugged in anyways.

For my phone, however, I cannot leave the key inside, and thus it is essential to have something akin to a Quick-Unlock (or Advanced Unlock, as it were) to be able to access the database.

I hope this helps explain why this feature matters to me and people with similar needs. It’s been two years since this issue was raised, but honestly, I think about it multiple times a day, every single day. Is there any hope for getting this feature added—the ability to have "Advanced Unlock" unlock the database without providing the YubiKey again for the duration of the Advanced Unlock?

Do you accept bounties? I’m just a student, so I can't contribute much, but I’d be happy to put up $50 or even $100 if that would help move things forward. I want this feature added so badly that it would be worth it if I can make it happen.

I can’t overstate how much I want to go back to KeePassDX. I use my password manager so much every day, and it’s important for me to use something I’m comfortable with and confident in. While I do like KeePass2Android, I love KeePassDX, and I really want to return to it if this feature can be added. For two years now I have thought about this every day, every time I open my password manager on my phone.

I hope this plea helps incentivize adding the feature. If bounties are accepted and that would push this forward, please let me know how I can contribute. I’d do it in a heartbeat. Unfortunately, I know Python but not Kotlin or Java, so I can’t implement the feature myself—but if I could, I would have done it ages ago.

Thanks so much for hopefully at least considering it, Andell

Andell4301 avatar Feb 26 '25 01:02 Andell4301

I spent around 20 hours or so trying to figure out how to add this functionality myself over the last few weeks, but alas, with no prior Java or Kotlin experience (or Android/mobile development experience in general), the codebase proved a bit too complex for a first project.

To recap, the functionality I was hoping to add is the ability for Advanced Unlock biometrics to work without requiring me to re-present my YubiKey while Advanced Unlock is active—at least for reads—for my database, which in my case uses a password, keyfile, and YubiKey.

I noticed that there appeared to be some commits related to advanced unlocking in the dev branch today, and while they don't seem to be related to this feature unfortunately, if you're working on advanced unlock, I thought I would try my luck and mention that it would be absolutely amazing if, just maybe, you could squeeze this feature in 🙏. Its absence is the only thing preventing me from using your otherwise incredibly polished and high quality app, and its addition would mean a lot.

Andell4301 avatar Aug 11 '25 04:08 Andell4301

I am currently refactoring the advanced unlock code, which I am renaming device unlock for simplicity's sake. The architecture is being redesigned to allow one or more factor to be associated but only for a combination of the password and/or key file.

Indeed, there is a major problem, the challenge response principle is designed to change the key with each modification, which is why it requires an external element and action; that is its purpose. Here, the solution for a physical key is to reproduce the complete challenge-response behavior but without the key. This is possible, but not in KeePassDX. Here, we need to create an emulator in the driver application that would copy the behavior of a Yubikey.

J-Jamet avatar Aug 11 '25 08:08 J-Jamet

That's what I had in mind, but I'm already focusing on linking the fingerprint to the combination of the password and/or key file. As I said before, the Yubikey has a specific purpose, which is to provide physical interaction. If we remove that requirement, the Yubikey is no longer necessary. So creating a Yubikey emulator would be a plus, but I have to prioritize features based on needs.

J-Jamet avatar Aug 11 '25 08:08 J-Jamet

@Andell4301

For me, the purpose of having a YubiKey attached to the database is knowing that there is something physical, not digital, like a Key File, protecting the database in case the database falls into the wrong hands.

It is something digital in the end: a 40 character hexadecimal string that is returned by the YubiKey's OTP application which can theoretically be intercepted. Meaning it is not bound to the YubiKey, it can be extracted, and is each time the YubiKey is used to unlock the database.

It's not as obvious as a key file and a much more sophisticated attack may be needed to get hold of it. One you might not be concerned with. However, since you said:

It's no exaggeration to say that for the past two years, I've wished multiple times a day that this feature could be added to KeePassDX.

Couldn't you consider protecting your database with a keyfile stored on a dedicated physical device (i.e. a USB stick)? This way you could use KeePassDX as it is now, in the way you described, while minimizing exposure of part of your credential to an internet connected device.

If somehow the contents of my computer got into the wrong hands, such as a someone obtaining one of my backups or whatever that might look like, I have peace of mind knowing that there is some element to my database that is NOT stored on the computer, it is stored externally in a physical device.

Which exactly describes your situation if you went that route. Make two or three USB sticks with the keyfile, and store it nowhere else, just like you do with YubiKeys.

Edit 1: Or am I mistaken, and will you have the same problem? I was operating under the assumption that Advanced unlocking does remove the need to provide the keyfile each time, but it seems I was wrong:

Currently, the advanced unlock connection with the Keystore is only made on the password, so you can always use the other factors separately.

So it's back to square one...

Edit 2: Although you could achieve something similar by programming your YubiKeys with a long random static password and appending this to your database's password.

kaoneko avatar Aug 11 '25 14:08 kaoneko

@J-Jamet

I have to prioritize features based on needs.

I totally get it and don't mean to bother you about it, I only brought it up since I noticed you were working on Device Unlock and thought it could be easier to do them together. I totally understand working on higher priority features first; I'm just glad you're willing to consider it for the future! 😊

the challenge response principle is designed to change the key with each modification

It's true it changes on modification, but write/modification access is not that important. KeePass2Android only provides read access; it requires users to re-present the yubikey to write/modify the DB. Read access is also all I'm asking for. Presumably, it is all others who use KP2A's quick unlock would want.

The short version of the problem I (and presumably other K2PA Quick Unlock users) am trying to solve is that I need to log in to sites/services many times a day, and am not always in a position to present my yubikey when doing so. However, at least personally, while I need read access many times a day, I write once a week or less. Read only access would match the feature of KP2A, solve the needs of people like me, and probably be much, much easier than a full emulator. It would be a shame to delay this feature to add write access that many people like me do not need.

A full emulator is really not what I am hoping for. If Device Unlock had an option to store the yubikey response, but expire if you try to modify the DB, that would be perfect for people with use cases like mine.

As I said before, the Yubikey has a specific purpose, which is to provide physical interaction. If we remove that requirement, the Yubikey is no longer necessary.

To me, I think it's akin to the debate about storing 2FA codes in your DB. Some say they're designed to be "something you have" and storing them together defeats the purpose. Others counter that even so, they're still useful as two step verification. I think the same principle applies here; while physical interaction is a strong benefit, I think it's ok to accept less than the maximum possible benefits from the yubikey as per one's threat model. In any case, I just hope my perspective is valuable in showing why some users might want this feature. I am very happy you're willing to consider it for the future! Thank you so much - Andell


@kaoneko

It is something digital in the end

This is true; in fact, I have a copy of the HMAC secret stored somewhere myself as part of my disaster recovery plan. With that said, and as you indicated, getting hold of the yubikey secret would be a more sophisticated attack than, e.g., pulling a file off a USB.

Couldn't you consider protecting your database with a keyfile stored on a dedicated physical device (i.e. a USB stick)?

I’ve considered it before, but decided against doing so for two reasons. First, I’m more comfortable keeping all three factors on my database—it gives me peace of mind, which is important for something managing my most sensitive information. Second, my current setup works, though it requires using KeePass2Android. I find KeePassDX more polished and would prefer to use it, but nevertheless, since my current setup functions, I’m not willing to drop one factor just to switch, even though I’d really like to—hence my push for this feature.

Andell4301 avatar Aug 11 '25 15:08 Andell4301

This isn't exactly the same feature described in this issue (device unlock), but if anyone finds this issue seeking read only access to the DB without re-presenting your YubiKey like I wanted, I had ChatGPT help me make a fork of the Hardware Key driver that adds this functionality. I've been using it for a day and it works perfectly.

I'm not a Kotlin dev, so I can't vouch for the vibecoding that was done here, but at least in my experience testing it it does exactly what I've been wanting all these years. If the preference is enabled, if you successfully complete your challenge response, it will store the response in an encrypted state using the Android Keystore. If you then present it with the same challenge (read only access to the DB), it will ask you if you want to use the cached response. You can do so, or you can clear it and proceed as if there was not yet a cached response. You can also clear the cached response in the menu beneath the toggle. If you present it with a different challenge (e.g., you are writing to the DB), it will clear the cached response and proceed as if there wasn't one. When you write to the KeePassDX DB, your challenge changes, so the flow is: You save changes --> It asks for your key, since challenge changed --> it caches the new response --> your changes commit to the DB, and you have read-only access with the response cached during the write. It's completely seamless.

You can see exactly what code has been changed in the commit below (I did need to bump the minSdkVersion to make ChatGPT's changes build):

https://gitlab.com/AndellDev/android-hardware-key-driver/-/commit/5d2262c18e49fc8f96d1eb565faff0f8ccd2f0d7

Again, I'm not a Kotlin dev, this was vibecoded. This solution would also not be ideal if the hardware key driver were ever used with apps other than KeePassDX, because each time you switched apps it would clear the cache as the challenge would have changed. You would need per-app caching in that case.

However, with those important disclaimers aside, hopefully this can help anyone who needs this feature like I did until a proper version is added to KeePassDX in the future. This is the exact hardware key flow I have wanted all this time and I am finally able to use KeePassDX again. I am over the moon and hope it can help someone else out like me.

Andell4301 avatar Oct 12 '25 19:10 Andell4301

This is a good first step. It's great to get started and propose new code; that's how the feature will be completed. If it works for a read-only database, that's already a realy good step forward. I also had the idea of completely emulating the challenge response system to offer a virtual Yubikey and accept write mode, but your first approach is much easier to implement. I'll test it when I get the chance; the driver app needs to be updated in any case. Thank you for your work, it's really cool.

J-Jamet avatar Oct 12 '25 21:10 J-Jamet

This is a good first step. It's great to get started and propose new code; that's how the feature will be completed. If it works for a read-only database, that's already a realy good step forward. I also had the idea of completely emulating the challenge response system to offer a virtual Yubikey and accept write mode, but your first approach is much easier to implement. I'll test it when I get the chance; the driver app needs to be updated in any case. Thank you for your work, it's really cool.

Thank you! I wish I knew Kotlin to do this without AI help, but still just Python and Rust for me. I did try to guide it on how to do this in a way that made sense, though.

The actual database doesn't have to be set to read only mode either; you'll have to present your key when you write, but it will save your response during the write so that you can read without the key until you write again.

It's perfect for my needs, at least! 😁

Andell4301 avatar Oct 12 '25 21:10 Andell4301