A quick note on static password mode
YubiKey supports static password mode. You configure a text (maximum 64 chars), then when you plug the YubiKey, it sends this text (using a HID). Maybe this is acceptable for some usages but remember that if someone steals the YubiKey, the password is compromised.I wanted something different, with the password divided between the machine and the token, so I designed YubiText.
YubiText, briefly
You configure YubiText with a text you want to input (e.g. a password). The token and the machine are configured with some magic (explained after). Then, you run YubiText in the background and whenever you plug the same YubiKey on this specific machine, another magic happens to get back your text and send it to the keyboard.The text is split between the token and the machine. If only the token is stolen, it does not reveal the text. Likewise, if only the machine is stolen, it does not reveal the text.
Details
The YubiKey is configured in HMAC-SHA1 challenge-response with a random, not saved secret. The challenge is of lengthblock_size-1=63
bytes, the response is of length digest_size=20
bytes.Then the user chooses the
text
to input. The text
is transformed into a key
, which is just a structure containing the length and some padding (to have a length multiple of the digest_size
).The
key
is then divided into N subkeys
, each of size the digest_size
. Now for each subkey[i]
, we do the following:- generate a random challenge, call it
machine_challenge[i]
- challenge the token with
machine_challenge[i]
and call the responsetoken_half-key[i]
- XOR
token_half-key[i]
withsubkey[i]
in order to getmachine_half-key[i]
- save
machine_challenge[i]
andmachine half-key[i]
on the machine, forget the rest.
This splits
subkey[i]
between the token and the machine.Finally, a predefined challenge is sent and response is stored in order to authenticate the YubiKey.
Now the program runs, it uses python-gudev bindings to the GUDev udev helper library in order to receive events when a YubiKey is plugged. After authentication of the YubiKey, the program is able to reconstruct the key and therefore the text simply with:
subkey[i] = ChallengeResponse(machine_challenge[i]) XOR machine_half-key[i] \-------- token_half-key[i] --------/
The text is finally sent to the display using xvkbd - Virtual Keyboard for X window system.
Source is on my github: StalkR/misc/yubikey/yubitext.py.
Multiple texts with one token
You can have multiple texts (not necessarily the same) with one token, but it has to be on different machines. First configure a token with--program yes
to have challenge-response and a random secret, then for subsequent configurations on different machines use --program no
not to reconfigure the token.If you want multiple texts on the same machine, you need multiple tokens.
3-factor password authentication
Consider the following: the workstation is in a protected safe, with only screen and USB cables allowed out. Typing the password on the keyboard is insecure: an attacker can put a USB keylogger, a camera in the room to record the keystrokes, or simply replace the machine with another one and log everything.Using YubiText, you can securely type your password (the virtual keyboard does not go over USB).
But if only this, all an attacker has to do is to steal the token. Even though the token itself will not reveal the text, the attacker can use it on the machine to reveals the text (for instance, go on "leave a note" and plug the token).
So, I choose to add another layer of protection and divide my password in two parts: the first part is like a regular password (only in my head and typed on the keyboard, with associated risks), the second part is using YubiText. It gives a somewhat 3-factor authentication:
- The first part, something I know.
- The second part, the token, something I have.
- The third part, the machine I want to authenticate on; while this is not listed as an authentication factor, I like it because it provides machine authentication (think SSL server certificate or SSH server fingerprint), if the machine is replaced it will not have the secret and so no text.
Limitations
Current limitations of the program and this design:- it does not work at boot (when asking for disk encryption password) or at login (gdm/kdm), because the virtual keyboard requires X - maybe this can be fixed?
- an attacker can man-in-the-middle USB to record all the challenge and responses, which is enough to fake the YubiKey later
- it is still broken because passwords are broken (I want PKI everywhere!)
Any comments on the design or the code are welcome.
Thanks for your writings on this new security token StalkR.
ReplyDeleteIsn't it possible to have the yubikey contain an SSH/GPG fingerprint, and the software that runs on plugging that verifies fingerprint- and verifies that the user can enter the code for this private key (on his computer) .. To enable user-space functionality ?
And for the boot password- I think it would be cool to make a "pandora's" box token. You would be able to program each key yourself- (some chars multiply characters, some does other operations) .. So you can remember the pattern- but not the actual code yourself, which is VERY long, because of the multiplying keys ..
I'm very excited to hear more about how you go about securing your yubikey ..
How does the one-time-passwords work ?
1. You implement the one-time-password with API.
2. Your yubikey ID is found @ yubi servers and OTP can be verified with this specific device-ID against all OTPs where one needs to match?
SSH/GPG: yes it would be possible. But in this case I would go for SmartCard to store key and use pkcs11 so that the key never goes out.
ReplyDeleteBoot password: yes it would work, it's a good idea but you need to buy as many tokens.
OTP: in this program I am not using the token in OTP mode, so it's not 1) nor 2). I use it directly for hmac in challenge-response mode.
If you want, you can also catch me on IRC to talk more about it.