OpenSSH's Support for U2F/Fido Security
github.com
github.com
- U2F Tokens cost $8-$25 and are significantly cheaper than full-blown Yubikeys
- U2F Tokens do not have a key limit, which enables using a unique public key per server for privacy/anonymity
[1] https://github.com/openssh/openssh-portable/blob/master/PROT...
They must have some limit. EC Keys are roughly 32 (256 bit) or 48 (384 bit) bytes (x2 to store the public half, right?), and most of these devices don't have MB of storage afaik... I think they have security chips with like 64-256kb of secure storage. So once you get into the range of thousands of sites, wouldn't you run out of room?
ETA: thanks akerl, I didn't realize that's what they (or most of them) were doing; I didn't even realize deterministically generating an EC key from a seed was efficient enough to do it quickly on a tiny embedded chip.
The OpenSSH protocol doc alludes to this requirement when they talk about why U2F needed a custom method for interfacing with SSH: the site’s handle needs to be provided as input to the key, so that it can re-derive the site-specific private key, and that communication channel didn’t already exist in ssh-agent.
The handle (IIRC the FIDO spec calls it a cookie but that doesn't matter) is NOT chosen by the relying party (in this case a SSH server you're logging into). It's chosen by the token itself during the enrollment process and given to the relying party with the other results of enrollment to be stored.
The token will use local random data in addition to random data supplied by the relying party for choosing a private key (and thus in the design you describe, the handle). This is a common design choice in cryptographic systems because it means if either Alice OR Bob really used random numbers the results are truly random, things only go badly if both parties defect.
In WebAuthn this means if you use your token to enroll with Google, and Facebook, and say Twitter, so long as the people who built the token did a good job it won't matter if both Google and Facebook are trying to betray you and deliberately didn't use random data, they can't attack your Twitter account this way.
Edit: refer to the device as a "token" not a key for clarity
Nothing in my comment implied that if google betrayed you, it would leak your facebook token.
One example way you can do this goes like this:
* Token has a Secret Key S baked inside it
* During enrollment the token makes a random private key P1 and a corresponding public key K1
* It makes a Cookie C1 by encrypting P1 using S
* It signs a message Ma with P1 to produce Za
* It sends C1, K1 and Za
The relying party gets to influence Ma but they do NOT get to pick any of these other values like P1, C1, K1.
The relying party verifies that Za is indeed a signature of Ma with K1 and if so enrollment worked, store C1 and K1
Now, after enrollment the relying party can produce new challenge messages Mb Mc Md and so on for ever, and each time it supplies the token with C1.
Given C1 and Mb, the token can decrypt C1 with S to get back P1, and then it can sign Mb with P1 to produce Zb. It sends that back.
The relying party can confirm that Zb is a signature of Mb with K1 and so this must be the genuine token that was enrolled previously.
AFAIK It does not.
And if it does not, your explanation contains bigger errors about enrollment/process.
@akrel described it much better.
You've become fixated on the part akerl_ (not @akrel) got right, that tokens don't store the private key but missed the _essential_ element they got wrong which is how this key is generated.
One really obvious consequence of things working as I explained rather than as akerl_ (presumably mistakenly not maliciously) explained is what happens if we do enrollment again with the same token for the same Relying Party, for example maybe Alice and Bob are a couple sharing a token.
In reality, as in my explanation, these enrollments produce completely different results, the token will pick a random P1 (thus K1, C1, etc.) when Alice enrolls and a different random P2 (thus K2, C2, etc.) when Bob enrolls, and for the Relying Party everything is different between these two enrollments, just as if the token was different.
In akerl_'s description Alice and Bob would get the same application ID, same results, and now a Relying Party can tell that Alice and Bob are using the same token.
(a) you can exclude those explicitly with a tiny amount of effort
AND
(b) probability of picking any such number for a 128-bit key is insignificant
This is also available on PKCS/OpenPGP for some tokens (and not only for auth keys). See: https://developers.yubico.com/PIV/Introduction/PIV_attestati... and https://developers.yubico.com/PGP/Attestation.html
On top of that, U2F tokens have no memory.
This makes them more durable and make the chipset even smaller.
I don't know whether FIDO2 has the same design.
U2F security keys are cheaper too.
By contrast, GPG is full of footguns. To pick an arbitrary example: many guides walk you through generating the GPG key on your regular computer and then importing it to the the Yubikey, and at best there’s a note suggesting you remove the key afterwards. At worst, there’s not.
If your U2F token was lost or damaged it would thus permenantly render your accounts inaccessible (depending on whether or not account recovery bypasses U2F), and the best practice to avoid that was to have two tokens initialised with the same key material and to keep one in a safe place at home / bank safe-deposit box / other secure location. Then, if you needed to regain control you still had a valid U2F token.
As U2F gains traction more sites are implementing it properly with multi token support, which renders this method obsolete, but that's the historical reasoning.
Yes, those sites should implement U2F support better, but the question was about why U2F is more secure than GPG, and ~“because it’s harder to mishandle the private key during setup” is pretty solidly an accurate answer.
1. The Yubikey docs describe the pre-Sierra process — https://support.apple.com/en-us/HT208372 has what most people will want to use after 2016. See https://github.com/Yubico/developers.yubico.com/issues/197.
Setting up a yubikey via gpg to be an agent for ssh was such a pain at least 2 years ago.
There's also a weird intermediary introduced that I think users may struggle to get their heads around. The FIDO cookie (this doc calls it a "handle" and the WebAuthn spec calls it the "Credential ID") is needed before a client can authenticate, and naturally you'd want to store this on a server, but in SSH the client chooses the authentication method to try not the server, so this cookie has to be stored on the client machine.
Say you enroll on your laptop. The laptop knows a cookie, the FIDO can take that cookie and prove it knows the private key, and that's enough to sign into the server. But without the FIDO key the laptop can't do anything, and without the laptop the FIDO key doesn't know which cookie is needed.
In effect it's two of the same factor. Something you have: The laptop and Something Else that you also have: The FIDO token.
Not following how you arrived at this. In the U2F, the server holds on to a copy of the key handle. Then during authentication, sends the key handle and challenge (referred to as "message" in this openssh doc) to the client.
But SSH is defined with the _Client_ picking how to authenticate first, so they can't do this.
There isn't a step in the SSH Authentication protocol where the server can say "Oh, here's the FIDO cookie you need". The SSH design says that (for public keys) the client starts by proposing "Hi, I can prove I know the private key that goes with this public key K1" and then the server either says "OK prove it" or "No, what else?". You can see this corresponds to the authorized_keys file on the server.
So instead you'll see the document calls this value "key_handle" and you'll see it is in the "private key" stored on the client, not with the "public key" stored on servers.
Does anyone have insight into the auditing process at openssh?
Thanks for pointing that discussion.
Sorry for double posting.
It depends on what do you compare this with. PKCS/OpenPGP smartcard is protected by a PIN (6 digits min, 3 tries and it locks itself out) and then touch on each use (with Yubikey).
U2F on the other hand it just protected by touch so anyone having the token can authorize themselves. (Sites usually use it in conjunction with username/password that is "something you know").
On the yet another hand I didn't review the implementation and would welcome corrections here.
When I used a Yubikey as a Smartcard it did in fact prompt for a passphrase. But that was via PKCS/SmartCard method, not U2F.
Generically, the term “User Verification” may also refer to this “Test for User Presence”
from e.g.
https://fidoalliance.org/specs/fido-security-requirements-v1...
https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-cl...
U2F support would achieve this without the extra server PAM config unique to yubico and remove reliance on a separate auth server - not to mention remove reliance on these particular type of keys that support their OTP which are pricey.