keepassxreboot / keepassxc

KeePassXC is a cross-platform community-driven port of the Windows application “Keepass Password Safe”.
https://keepassxc.org/
Other
21.47k stars 1.48k forks source link

Use Yubikey challenge-response secret to decrypt database #1734

Open Brocklobsta opened 6 years ago

Brocklobsta commented 6 years ago

Is it possible to use the Yubikey challenge-response secret (hex string) to decrypt a KeePassXC database using the KeePassXC yubichallenge implementation? I like how you guys implement the Yubichallenge btw, it is much closer to a true 2fa.

Expected Behavior

Have some way to enter the yubikey challenge-response secret when decrypting the database

Current Behavior

No option to input challenge-response secret

Possible Solution

Add a "Recovery" box to the challenge-response area that allows a hex string to be entered and used for the challenge response computation.

Steps to Reproduce (for bugs)

1: Create a database using Yubikey challenge-response (save the secret used the configure the yubikey) 2: try and decrypt the database without the use of the yubikey and only the secret.

Context

Basically since I own a Yubikey 4 and not a NEO variant, I am unable to use the Yubichallenge app to decrypt my database since it is not possible to perform a challenge-response over a USB connection with android at the time of this message. My solution to save my Yubikey secret to an encrypted android file storage and copy and paste when I need to decrypt my database.

Debug Info

KeePassXC - 2.3.1 Revision: REVISION

Libraries:

Operating system: Windows CPU architecture: Intel x64/x86 Kernel: Win10

Enabled extensions:

ananta-dev commented 5 years ago

@yeah-mike. It worked!!! I programmed the challenge-response into the Yubikey with the Yubikey Manager, instead of the Yubikey Personalization Tool . Then protected the test database with the newly programmed Yubikey. I generated a keyfile with the challenge extracted following @WiLars' instructions, and now the database can be decrypted with the password and the newly generated keyfile.

So we could say the Yubikey Manager and the Yubikey Personalization Tool are following different algorithms to program the secret into the Yubikey. Right?

ananta-dev commented 5 years ago

In case anybody would like to play with the database and keyfile that worked, I am attaching both in a zip file:

test-mini-with-yubikey-manager.zip

This database can be decrypted with the password "test01" and the keyfile-yubikey-manager keyfile. If you want to use Yubikey to open it, you need to program the Yubikey using the Yubikey Manager, with the secret "8313063e07fe63b474282d87870e7384bedccc9c".

CueHD commented 5 years ago

I just realized that the Yubikey Personalization Tool software has a Challenge-Response Tester in its tools section.

ananta-dev commented 5 years ago

@CueHD. Yes it does, but note if you want to make decryption with a keyfile work with the method explained earlier in this thread, you need to use the Yubikey Manager, not the Yubikey Personalization Tool.

Coeos3 commented 5 years ago

I would also love to see that recovery feature.

It would be way more user-friendly than the above workaround. Even reprogramming a new Yubikey in case the original(s) is lost is not at the reach of all users - I know that no one in my family would be able to remember how to do that. Besides, having to wait a week (at least - imagine it happens on holiday), isn't practical either.

PS: I've been using Keepass with keechallenge the last years, but their implementation isn't optimal as it exposes the secret on the Yubikey on every unlock. So 👍 to KeepassXC for the good implementation!

CueHD commented 5 years ago

I actually like the keyfile "workaround" as a recovery option for the Yubikey. It helps to keep the challenge/response secret a secret since it does not need to be inputted into KeepassXC nor stored anywhere.

My suggestion for a user-friendly recovery would be to have an option for KeepassXC to generate the keyfile. This way, there is no confusion as to what the correct response would be since KeepassXC knows exactly what the expected response is, and there is no reason to input the C/R secret anywhere.

droidmonkey commented 5 years ago

I like that option the best @CueHD

mrclschstr commented 5 years ago

Correct me, but the response changes everytime the challenge changes. So everytime you save the database you have to generate a new keyfile. Sounds not like a suitable solution to me.

Or did I get that wrong?

Coeos3 commented 5 years ago

If by generating a key file you mean typing the hex response into a KeepassXC recovery input box and KeepassXC then generating the file, then that still seems too geeky to me. Extracting the challenge using a hex-editor and doing the hashing with the secret isn't accessible to most users (including me without spending lots of time on it). On top of that, many users might simply go to a web site to do the hashing, therefore having to reveal the secret on the internet. Feels to me that it's easier to change the secret on the Yubikey if someone feels uncomfortable after a recovery.

CueHD commented 5 years ago

Correct me, but the response changes everytime the challenge changes. So everytime you save the database you have to generate a new keyfile. Sounds not like a suitable solution to me.

Or did I get that wrong?

The response only changes if you change the master password or the c/r secret.

CueHD commented 5 years ago

@Coeos3 No, I suggest that the user should never need to type the secret nor the HEX response at all. KeepassXC has the response. It had to in order to unlock the database. At whatever point is most convenient for the software either during the unlock process or after it is open, it could generate the keyfile with the response and save it. The only thing the user would need to do is input the master password as normal and have the Yubikey available as normal.

droidmonkey commented 5 years ago

@mrclschstr is correct, every time we save the database we generate a new seed which is what is sent as the challenge to the Yubikey. The response returned is what gets added to the master key (after being hashed). Unfortunately exporting the challenge seed will only protect you until you save the database again. I take back my endorsement.

For the curious (and also to document it a little) the call chain is as follows:

KDBX4Writer -> Database::setKey(...) -> New Seed Generated -> CompositeKey::Transform(...) -> CompositeKey::rawKey(...) -> Normal Keys Added to Hash Data -> CompositeKey::Challenge(...) -> Response from Yubikey using seed as challenge -> Add to hash data -> Perform KDF Transformation -> PHEW

**Note: for KDBX3.1 we screwed up yubikey implementation and added the response AFTER hashing the key, not as part of the overall key hash

CueHD commented 5 years ago

I was unaware of the seed aspect to the challenge. In this case, I would say that it is more of a reason to enable KeepassXC to generate a recovery keyfile.

phoerious commented 5 years ago

We cannot generate a recovery keyfile. It would need to contain the hmac secret which we do not have. If we had that, it wouldn't be any different from a normal keyfile.

Coeos3 commented 5 years ago

@CueHD. Yes it does, but note if you want to make decryption with a keyfile work with the method explained earlier in this thread, you need to use the Yubikey Manager, not the Yubikey Personalization Tool.

FYI, I tested it and you get the same results with the Manager and the Personalization Tool only if you choose "variable input" when programming with the latter.

mrclschstr commented 5 years ago

I opened an issue regarding the different behaviour of the Manager and the Personalization Tool using fixed 64 byte input. Can somebody join https://github.com/Yubico/yubikey-personalization-gui/issues/86#issuecomment-486638606? 😃

mrclschstr commented 5 years ago

This might be the reason for the different behaviour (haven't tested it yet): https://github.com/mmcguill/Strongbox/issues/95#issuecomment-504238115

jeinwag commented 4 years ago

I wrote a small tool which will generate a keyfile to unlock your database, provided you have the challenge-response secret.

droidmonkey commented 4 years ago

Can you put that in a pull request to add to our utils folder?

jeinwag commented 4 years ago

@droidmonkey Sure, no problem, I'll look into it in the next couple of days.

cristi-t commented 4 years ago

An alternative ( more compact ) way to open the KDBX4.0 database if the yubikey is lost is by producing the recovery keyfile with the help of the following Perl one liners:

c161f2f84002033cef4767cc42bf3de92aa08bd2

* to actually create the keyfile:

$ perl -e 'use Digest::HMAC_SHA1 qw(hmac_sha1);open $fh,"<:raw","NewDatabase.kdbx";seek $fh,0xC5,0;read $fh,$ch,32;print hmac_sha1($ch,pack("H*","0102030405060708091011121314151617181920"))'>keyfile

* to check that the keyfile has been written properly:

$ hexdump -C keyfile 00000000 c1 61 f2 f8 40 02 03 3c ef 47 67 cc 42 bf 3d e9 |.a..@..<.Gg.B.=.| 00000010 2a a0 8b d2 |*...| 00000014

jeinwag commented 4 years ago

@christi-t I don't think this will work under all circumstances, since the address of the seed is not fixed at 0xC5. For example, it's different when you save a database with keepass2android.

cristi-t commented 4 years ago

@christi-t I don't think this will work under all circumstances, since the address of the seed is not fixed at 0xC5. For example, it's different when you save a database with keepass2android.

@jeinwag You are right. The general form of the command is:

perl -e 'use Digest::HMAC_SHA1 qw(hmac_sha1);open $fh,"<:raw","<db_file>";seek $fh,<offset>,0;read $fh,$ch,<challenge_length>;print hmac_sha1($ch,pack("H*","<secret>"))'>keyfile

where:

Is there a procedure to get the challenge offset?

jeinwag commented 4 years ago

Is there a procedure to get the challenge offset?

@cristi-t You'll need to to read and interpret the header of the password database, that's what my little tool does.

jaredvacanti commented 4 years ago

Using keepassxc/utils/keepassxc-cr-recovery from the develop branch is producing an unexpected error:

$ ./keepassxc-cr-recovery ./Password.kdbx ./temp-key
Secret: <challenge-response secret>
couldn't read challenge: unexpected EOF

Note: I'm able to successfully authenticate with my password and challenge-response slot using a Yubikey. I'm testing the disaster recovery procedures.

Has something changed to the header of the DB that alters how keepassxc-cr-recovery identifies some file details? If not, should this work?

My KeePassXC details:

KeePassXC - Version 2.4.3
Revision: 5d6ef0c

Qt 5.12.4
Debugging mode is disabled.

Operating system: Ubuntu 19.10
CPU architecture: x86_64
Kernel: linux 5.3.0-46-generic

Enabled extensions:
- Auto-Type
- Browser Integration
- SSH Agent
- KeeShare (only unsigned sharing)
- YubiKey

Cryptographic libraries:
 libgcrypt 1.8.4
droidmonkey commented 4 years ago

Are you using kdbx4 database?

jaredvacanti commented 4 years ago

No, I wasn't. Updating to kdbx4 fixed it, and I can login with the utility.

Should everyone be on kdbx4 (unless they have some client reason not to) or should I update the docs to mention when keepassxc-cr-recovery is available?

droidmonkey commented 4 years ago

Everyone should be using kdbx4, there is no reason not to.

phoerious commented 4 years ago

We should ask users to upgrade in 2.6.

jacek-1 commented 4 years ago

.

jaredvacanti commented 4 years ago

Does KeePassXC look for a Yubikey specifically when looking for challenge-response device, either by vendor code in an AID, or only on a specific USB interface? For motivation, there is JavaCard applet https://github.com/arekinath/YkOtpApplet that achieves the same goal as the Yubikey with KeePassXC:

This is a JavaCard applet that emulates the HMAC challenge-response functionality of the Yubikey NEO/4. It presents the same interface that a real Yubikey presents over CCID (i.e. this applet does not have any HID features).

I can think of two options:

  1. Use a middlware to translate CCID -> HID, then the applet will appear as a Yubikey, or
  2. Interact with CCID devices through KeePassXC

There are mentions in other issues of Nitrokey HSM & PKCS#11 support as well, which would probably be related, although the tokens made available though cryptoki would be different than the OTP applet services.

Is one of the methods preferred, unfeasible, or something else?

Note: keepassxc/utils/keepassxc-cr-recovery still works - but this would enable security key backups.

droidmonkey commented 4 years ago

I have no interest in supporting additional hardware tokens at this time. PKCS#11, yes.

droidmonkey commented 3 years ago

The repair feature in keepass doesn't actually do anything. You must have corrupted your key file or wiped your yubikey, that would explain why it doesn't work in previous saves either. Highly highly unlikely your actual database is corrupt.

droidmonkey commented 3 years ago

Are you saving your database to a USB drive? That has been known to corrupt databases before.

droidmonkey commented 3 years ago

We don't hold any locks on files. The only time you can't touch a file is during open or saving, otherwise the file is not accessed at all.

Glutamat42 commented 2 years ago

Is there any way to use keepassxc/utils/keepassxc-cr-recovery if I'm already using a keyfile (and a password)

droidmonkey commented 2 years ago

Unfortunately, no.

Glutamat42 commented 2 years ago

Turns out it was quite easy to implement loading a 2nd keyfile. In case somebody else wants to restore access using the yubikey secrect, with an existing keyfile, this is how i've done it

  1. First generate a keyfile for the yubikey as explained here in the thread (with keepassxc-cr-recovery).
  2. Then add the ability to use a 2nd keyfile to keepassxc. Keepassxc is designed to use many secrets, so basically duplicating the code for loading a keyfile is enough. The relevant function is keepassxc/src/cli/Utils.cpp -> unlockDatabase(...). Here are the changes i did: https://github.com/Glutamat42/keepassxc/commit/7a978551baabe0e847da2d992a21e880fe6d4501
  3. Build the project. (I used docker, matimoreyra/qt5 as a base container, updated it to 20.04 and then installed the dependencies as i got the missing messages. There are no special build parameters required, just used cmake -DWITH_XC_ALL=ON .. )
  4. access the database with the keepassxc-cli tool. Installing the modified keepassxc is not required. Eg you can run src/cli/keepassxc-cli export -k <original keyfile> <XXX.kdbx> to get the whole content printed to stdout. Note that in my version i had to place the keyfile generated in step 1 at /keyfile2.key because i hardcoded that path.

I would like to have a recovery feature officially implemented (or the ability to officially load two keyfiles with the cli version + this procedure well documented) because imho one of the most important things is allowing to restore access if you lose or forget a key.

droidmonkey commented 2 years ago

Cool fix!

gilcu3 commented 9 months ago

Just in case someone tries to recover a database with the go package in keepassxc/utils/keepassxc-cr-recovery, it seems there is a typo when computing the padding of the challenge (why is this padding necessary in the first place?). Instead of 64 bytes it should be 32 on lines: https://github.com/keepassxreboot/keepassxc/blob/a472ef8a931dd64990d7f735394e949638e880d5/utils/keepassxc-cr-recovery/main.go#L172-L178 Tested and working on my current kdbx4 database.

phoerious commented 9 months ago

I recently debugged that part with someone in the chat and we found a few bugs or oversights in the implementation. I think they wanted to file a pull request, not sure what came of it. The padding is necessary for challenges of arbitrary length. How these are handled depends on how you programmed your YubiKey. There are two modes, fixed and variable, though the new management tool exposes only one to the user.

EtaoinWu commented 8 months ago

I created a static server-less HTML version of the cr-recovery tool, EtaoinWu/keepassxc-cr-recovery.html, for people (like me) who do not want to build the official go version, and/or want to run it on a mobile device without shell access. Tested with my own database.

It's also deployed on cloudflare pages, though you have to use the internet version at your own risk.

securitym0nkey commented 1 month ago

For everyone, like me, landing on this issue because the recovery tool of choice isn't working for them. Here is my summary of analyzing the situation.

Why is it like this?