A quick note on static password modeYubiKey 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, brieflyYou 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.
DetailsThe YubiKey is configured in HMAC-SHA1 challenge-response with a random, not saved secret. The challenge is of length
block_size-1=63bytes, the response is of length
Then the user chooses the
textto input. The
textis transformed into a
key, which is just a structure containing the length and some padding (to have a length multiple of the
keyis 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
- challenge the token with
machine_challenge[i]and call the response
subkey[i]in order to get
machine half-key[i]on the machine, forget the rest.
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 tokenYou 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 yesto have challenge-response and a random secret, then for subsequent configurations on different machines use
--program nonot to reconfigure the token.
If you want multiple texts on the same machine, you need multiple tokens.
3-factor password authenticationConsider 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.
LimitationsCurrent 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.