keepassxreboot / keepassxc

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

Add Nitrokey Pro and PKCS#11 support [$520] #255

Open Germano0 opened 7 years ago

Germano0 commented 7 years ago

Nitrokey Pro is an Open Hardware device and FOSS software that allows people to use such device as a secure token for various security needs, like two factor authentication, GPG/PGP, SSH keys, etc. It would be great to have support for such device

albrechtd commented 7 years ago

I think this extension would be extremely useful and thus I strongly support this suggestion.

Maybe you know that there has been a somewhat similar Feature Request for keypassx in 2010. The workaround using the gpg pipe doesn't work for me, though.

Instead of directly interfacing to a smartcard, an alternative could be a gpg-encrypted keyfile which is fed through gpgme which in turn uses the gpg key from any smartcard.

droidmonkey commented 7 years ago

I wish these devices used the PKCS#11 standard like smart cards.... I am not keen to include the libraries of all the various hardware tokens out in the world.

Germano0 commented 7 years ago

@droidmonkey Nitrokey Pro should really be PKCS#11 compatible https://raymii.org/s/articles/Get_Started_With_The_Nitrokey_HSM.html#PKCS%2311,_%2315_and_OpenSC

droidmonkey commented 7 years ago

Hmmmm i wonder if we could just create a pkcs#11 module instead and then you could also use smart cards /pivs

drdaeman commented 7 years ago

I have a Gnuk-based FST-01, which should be quite similar to Nitrokey Start. I think while it works as OpenPGP Card v2, it doesn't really work as PKCS#11, at least not without something like Scute. I.e. gpg --card-status works out-of-box, but pkcs11-tool --show-info fails with CKR_DEVICE_ERROR. Maybe that's just me not understanding something, though.

How about an option of having an encrypted keyfile and talking to GnuPG (via GPGME or whatever), letting it handle the actual hardware, whatever it is? (Or maybe even a generic option of an external keyfile material provider using pipes?) Something similar in spirit to the linked KeepassX feature request, but with auth process explicitly started and controlled by KeepassXC.

livelace commented 7 years ago

@droidmonkey

Hello. When do you plan to add support PKCS #11 ?

droidmonkey commented 7 years ago

Probably 2.3.0

livelace commented 7 years ago

@droidmonkey

Thanks. I will wait with impatience.

AzureRaptor commented 6 years ago

I'm also interested in seeing any support, PKCS or otherwise, that would let us use NitroKeys. I started to look at getting a YubiKey recently, but it seems like they are turning their backs on open source just lately, and their excuses are all very facile and shady.

droidmonkey commented 6 years ago

I noticed their GitHub is not very organized.

rhetr commented 6 years ago

https://github.com/Nitrokey/nitrokey-keepass-plugin they have a plugin repo for keepass with no documentation ✌

protobits commented 6 years ago

It would be also interesting for me to have support for Gnuk-based device. This would involve talking to gpg-agent for authentication. I understand this uses a standard protocol.

phoerious commented 6 years ago

We cannot use Nitrokeys directly, because they do not support HMAC-SHA1. We have some ideas for supporting PGP-encrypted keys, but it will take some time to implement then.

szszszsz commented 6 years ago

Hi! Just noticed this issue and I thought I could reply some questions regarding Nitrokey.

@droidmonkey Nitrokeys support PKCS#11 with OpenSC.

@drdaeman PKCS#11 with Nitrokey Start was used in Raymii's tutorial - maybe you would find this helpful. See guides from official Nitrokey's site as well.

@rhetr I do not know the details, but this is an attempt to use PKCS#11 in Keepass2. It perhaps worked 5 years ago, but I am not so sure about it right now. Good point to mention that in Readme.

@phoerious We support HOTP at the moment. Maybe we could work something out with it, like using HOTP codes in encryption of the database (similarly to Keepass2 solution)? In the future we could support HMAC-SHA1 directly, if there would be a request (no one registered it in Pro's firmware project yet).

Love the project - all the best!

livelace commented 6 years ago

I'm still waiting PKCS11 :)

phoerious commented 6 years ago

We haven't had time for working on the PGP thing yet, there are too many other more urgent things that need to be done first, but it's on the agenda. HOTP is basically just manual HMAC-SHA1. We could support it. I was also thinking to provide some sort of HMAC-SHA1 backup function where you enter the secret directly and let KeePassXC generate the challenge from it. That way you can still access the database if you lost your key, but still know its secret.

jans23 commented 6 years ago

@phoerious Let me know if there is anything we at Nitrokey could do to support you.

svenseeberg commented 6 years ago

@jans23 I started working on this issue. However, libnitrokey has a steep learning curve (as has KeepassXC). Anyways, I do not understand how to connect to a Nitrokey while the Nitrokey app is running. Or put differently: NitrokeyManager->connect() only works while the Nitrokey app is not running. How do I solve this?

szszszsz commented 6 years ago

@svenseeberg Current protocol is not designed to be used for multiple applications thus opening in libnitrokey blocks further connections. Do you have a specific need to have both Nitrokey App and KeepassXC opened at the same time?

svenseeberg commented 6 years ago

@szszszsz Thanks for getting back to me that quick. No, there is no specific need. It's just about usability. Maybe I'll add a function that detects whether the app is running and notifies the user. And I guess that the user could manually copy the one time pad if both programs are being used at the same time.

*edit: Now that I know that both programs cannot use a Nitrokey at the same time, I think I'll only implement a manual HOTP method. That means the user has to manually copy the shared secret and one time pads from the Nitrokey App to KeepassXC. Better ideas?

szszszsz commented 6 years ago

OK! Detecting solution as you speak should work (maybe supported with libusb). Perhaps adding such function directly to libnitrokey would be handy - if so, please register an issue there. Let me know if you would need any help with the library - I will happily support you. I have added myself to the fork watchers, so we could discuss issues there as well.

svenseeberg commented 6 years ago

Sorry for causing confusion. HOTP is no use because the shared secret would have to be stored unencrypted along the kdbx file. So we're back at waiting for PKSC11 support.

gartfr commented 6 years ago

Maybe have a look to this old keepass2 plugins which enables the possibility to store the master key which encrypts the DB to a pkcs11 token. I use it since a long time now working quite well. It relies on the driver DLL which do the interface between the hardware token and the software. Personnaly, I use ePass2003 token and opensc lib.

Main drawback, it is actually not working under linux... only Windows.

I'm no coder, I can't help anymore... sorry...

CryptokiKeyProvider_0.1.3.zip

There is actually no other similar plugin or more recent or anything else... It makes a long time I'm scruting the web...

maufl commented 5 years ago

Hey, I just found this issue. What I would love is PKCS#11 support and support for encrypting it for multiple public keys. We use smart cards at work and it would be awesome if we could share password databases.

svenseeberg commented 5 years ago

So I started collecting ideas on how I can solve this issue. Feel free to suggest alternatives or improvements.

To me it seems like a good idea to use GnuPG/GPGME with its C++ bindings. As GnuPG supports smart cards (including Nitrokey Pro), it would then be possible to encrypt a secret with any normal public key. If the corresponding secret GPG key is stored on a smart card, it will ask for the PIN of this card.

The GPG encrypted KDBX secret can be stored in the public headers of the KDBX file. It should also be possible to encrypt the KDBX secret with multiple public keys in order to grant access to multiple users. Is it a good idea that the encrypted secret is the normal password to the KDBX file? This provides a fallback decryption mechanism if the GPG secret key is lost. The password/KDBX secret could be a much longer key than most users probably use.

I envision the UI to have an additional field "GPG Key" on opening a KDBX file. In this field, an available GPG secret key is automatically selected, if the secret key is available on the current machine. The "Change master key ..." could contain an input field that simply allows pasting any PGP public key block which is then used to encrypt the secret.

droidmonkey commented 5 years ago

This is good for *nix environments. For Windows you would want to interface directly with the certificate store so that third party PKCS#11 solutions (such as ActivClient) or even Windows itself can perform the interactions with the smart card.

https://docs.microsoft.com/en-us/windows/desktop/secauthn/smart-card-authentication

jans23 commented 5 years ago

To clarify: Windows' certificate store is different than PKCS#11. GnuPG supports only devices compatible with OpenPGP Card (e.g. Nitrokey Start, Pro, Storage) but not PKCS#1. You can choose to support PKCS#11 and/or Windows and/or GnuPG/OpenPGP Card.

phoerious commented 5 years ago

As mentioned earlier, I had some ideas about integrating OpenPGP with KeePassXC myself. Personally, however, I would prefer not to paste the keys into KeePassXC, but use the gpg-agent interface for encryption and decryption. That provides a lot more transparency and KeePassXC would be fully agnostic of the underlying hardware, keys, and algorithms and we do not have any extra hard dependencies in our code.

My idea was that if a database is open, you can "add" a PGP key by clicking a button in the database settings, which generates a random secret and lets the gpg-agent encrypt it. The encrypted secret is then stored in the KDBX public custom data block together with other keys by other people. For backup purposes, we can also display the plain secret to the user afterwards. Generally, the database settings allow you to add or remove any number of PGP-encrypted secrets. As an additional feature, one could generate an additional encrypted secret to be shared on a secure authenticated channel with a third party, so they can add it to their database so as to give you access without the need for your own private key.

jans23 commented 5 years ago

HMAC-SHA1 was mentioned earlier. Could somebody describe what exactly is required in this respect? Is this a standard or custom solution?

Note, Nitrokey supports standard HOTP and TOTP.

phoerious commented 5 years ago

It's just standard HMAC-SHA1. Nothing special. I don't know about the actual protocol for talking to the USB device, though. That is handled by the YubiKey lib.

jans23 commented 5 years ago

Perhaps HOTP would be a better alternative to HMAC-SHA1 because it is standard-compliant. However, PKCS#11 is still a more secure alternative.

svenseeberg commented 5 years ago

How would HOTP be used? AFAICT it requires a shared secret and this shared secret would have to be stored in the KDBX file. Therefore it provides no additional security. Am I getting something wrong?

jans23 commented 5 years ago

Yes, HOTP uses a shared secret. I was assuming that HMAC-SHA1 works with a shared secret too. Doesn't it?

szszszsz commented 5 years ago

Hi! @svenseeberg If I got this right (and as long as I remember), in the original solution [1] the HOTP code was either part of the final secret used to encrypt the database, or a key for decryption of the semi-stage secret, which was further used with the final secret to open the database. The former requires rewriting the database file due to re-encryption, the latter - only re-encrypting the semi-password stored in the header I guess. [1] is open source, so it should be easy to confirm that.

Edit: the semi-secret can be stored in a support file as well, to avoid rewriting of the whole database.

[1] https://keepass.info/plugins.html#otpkeyprov

beelze commented 5 years ago

Voting for pkcs#11 support. Something alike in Firefox, with ability to use custom (e.g. proprietary) pkcs#11 libraries

rugk commented 5 years ago

IMHO we should split this issue to "Nitrokey Pro support" and "PKCS#11 support" as it is really not clear whether PKCS#11 support would work for Nitrokey and solve the issue.

The thing is: Whatever implemented, it should be compatible with other KeePass-compatible client applications. And actually, there is already something done and both solutions seem to use HOTP instead of PKCS#11:

So as I see it, PKCS#11 support is not the thing other clients want to use for Nitrokey support. They all seem to use HOTP. So why exactly do you think it is not possible/secure here?

droidmonkey commented 5 years ago

Just because people are using HOTP doesn't make it the right or desirable answer.

rugk commented 5 years ago

Obviously yes, but we should tell these people this, then. The question is then, why is not it the right answer?

droidmonkey commented 5 years ago

HOTP requires a rider file in addition to your database file OR the shared "semi-secret" stored in the unencrypted portion of the database file. Read the posts from svenseeberg and szszszsz above. This has also been discussed elsewhere on the issue board.

Read more here: https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_algorithm

HOTP works great for client-server type relationships. It does NOT work great for encrypted data at rest (ie, KDBX)

rugk commented 5 years ago

"rider file"?

droidmonkey commented 5 years ago

An extra file in addition to your database file.

rugk commented 5 years ago

So that's the only issue? I mean, as long as it is cryptographically secure I see no problem with that, it's okay if it needs some extra data. In here it is mentioned it may also need to re-encrypt/rewrite some data, but especially if it is just the header, I think there is no problem if it is an one-time step. (and when people setup their Nitrokey I guess they may also wait some seconds)

svenseeberg commented 5 years ago

(I'm not an expert, but) As far as I can tell, HOTP does not help in this case. HOTP is designed for message verification between two devices, both of which know the shared secret. HOTP basically derives a hash from a message and a shared secret. With this hash, the receiver can verify, that the sender also knows the shared secret.

This mechanism does not help in securing Keepass databases. It would be necessary to store the secret unencrypted along the database. Therefore, anybody can read it and fake the presence of the HOTP device.

/edit: I started working on an OpenPGP implementation. I don't think that this is what is currently expected by most contributors to this issue, but IMHO easiest to achieve. Extending the code for PKCS#11 support should be possible later.

gartfr commented 5 years ago

I agree with the previous post, OTP is only adding the ability to avoid brute force attack and a factor of authentication (something you own). PKCS#11 gives the 2 previous, but also gives the ability to store a complex encryption key on a secured device. To me, PKCS11 support in conjunction with a USB Token or SmartCard is the ultimate security for Keepass. Keepass security relies mainly on the hardeness of the database key which is used for encryption. PKCS11 adds the ability to store a very complex key on a device which will take care of the security of this precious encryption key : hardware encrypted storage, unlocked by pincode or more secured biometric function.

OpenPGP is also great, it provides quite the same mechanism, as long as you use an OpenPGP device like Yubikey and you store your private key on it.

phoerious commented 5 years ago

The way HOTP is implemented in KeePass is that you store a secret in a sidecar file and encrypt it a couple of times with a series of one-time passwords. The scheme works, but is a hack at best. Six- or eight-digit numbers are quite easy to brute force, so the protection you gain depends a lot on the number of OTPs you generate. But since those OTPs are not actually independent of each other, the actual entropy is much lower than that of a random string of the same length.

mikolaj-kow commented 5 years ago

Voting for HSM/SmartCard support via PKCS#11.

This is the last thing that is stopping me from Keepass migration. Currently using CertKeyProvicer plugin which is accessing Microsoft CryptoAPI (CAPI).

droidmonkey commented 5 years ago

In the meantime, if you really want to switch, I recommend just buying a Yubikey and using that as your token. It has the same level of protection as a smartcard.

onlykey commented 5 years ago

I found this issue while doing some research for another issue where we are implementing open source challenge and response https://github.com/keepassxreboot/keepassxc/issues/2064 and thought I would give my 2 cents.

HOTP - This value changes every time so its not clear to me how this will be used to encrypt a database. Sorry I didn't read all the comments above maybe there is a way. You could definitely store HOTP seeds in the encrypted databases for accounts but that is something different.

Challenge-response (HMACSHA1) - This value does not change every time it is dependent on input. So you can send a challenge, get a response, use the response to encrypt database. You can also store the challenge in plain-text with the encrypted database as its not sensitive. To decrypt you send the challenge, get the same fixed response to decrypt. This is pretty good as the threat model here is an attacker would have to have root access on your computer and in real time capture the USB data containing the fixed response. One thing here is that the HMACSHA1 input should change often to mitigate threat.

OpenPGP - Here you would encrypt the entire database with a private key. Usually what is done is there is an RSA/ECC key stored on a USB device (smartcard or token), that key is used to encrypt a symmetric key (32 bytes AES-256), that symmetric key is used the encrypt the database. This is basically how GPG/PGP works. This is a little better than challenge-response as the threat model here is an attacker would have to have root access and memory access to where the decrypted database resides. Each time the database is encrypted a new symmetric encryption key is used.

One additional threat model to consider with smartcard/token is that you are entering your PIN to unlock it on your keyboard. In the event that there is a keylogger on your computer and you forget to remove the device an attacker can unlock your smartcard/token and use it as they will. This is one area where challenge-response has the advantage as you can require physical button press on the device. This threat model is one reason why OnlyKey has the PIN entry on the device itself.

phoerious commented 5 years ago

HOTP does not "change every time". It simply depends on a secret and a counter. So given a fixed secret and a fixed counter, the generated OTP is also fixed.

onlykey commented 5 years ago

@phoerious OK I see what you are trying to do. If you are able to specify to the token the counter to use it would be fixed, however I thought for security reasons tokens always keep this counter internally. Either way, even if this works a fixed 6-8digit OTP is trivial to brute force so I am not sure what benefit this would offer.