YKPERSONALIZE(1)

πŸŽ€ ykpersonalize(1) β€” YubiKey Personalization Tool πŸŽ€

okay bestie, sit down. this is ykpersonalize, straight out of the YubiKey Personalization Tool manual, and it is the tool for making a YubiKey yours. it's long so we're doing it in parts β€” this is part 1, so don't go anywhere. πŸ’…


🌸 NAME 🌸

ykpersonalize β€” personalize YubiKey OTP tokens ✨


✨ SYNOPSIS ✨

ykpersonalize [-Nkey] [-1 | -2] [-sfile] [-ifile] [-fformat] [-axxx]
[-cxxx] [-ooption] [-y] [-v] [-d] [-h] [-n] [-t] [-u] [-x] [-z] [-m]
[-S] [-V] [-Dxxx_]

πŸ’– DESCRIPTION πŸ’–

So what does this little icon do? It sets the AES key, the user ID and a whole bunch of other settings inside a YubiKey. it's giving "customize your key, but make it cryptographic". 🫢

and if you wanna know what every single parameter actually means, like, truly, the original authors are like: go read the reference manual, bestie. it lives here:

https://www.yubico.com/wp-content/uploads/2015/03/YubiKeyManual_v3.4.pdf

(it's called the YubiKey manual. yes that's the whole name. iconic.) πŸ“–


πŸ’… OPTIONS πŸ’…

  • -Nkey β€” use the nth YubiKey that gets found. key #1, key #2, whichever one you're feeling. πŸ”‘
  • -1 β€” change the first configuration. this is the default, and it's the one normally used for true OTP generation. fun fact: in this configuration, the option flag -oappend-cr is set by default. so it's already doing a thing for you. πŸ₯°
  • -2 β€” change the second configuration. this one is for YubiKey II only, and it's normally used for static key generation. and babes, it comes stacked with defaults: the option flags -oappend-cr, -ostatic-ticket, -ostrong-pw1, -ostrong-pw2 and -oman-update are all set by default. ✨
  • -z β€” delete the configuration in the selected slot. bye bye πŸ‘‹πŸ’€
  • -sfile β€” save the configuration to a file instead of to the key. (if the file is -, it goes to stdout.) πŸ’Ύ
  • -ifile β€” read the configuration from a file (if the file is -, it reads from stdin). heads up: configuration import is only valid for the ycfg format. no exceptions, no cap. πŸ“₯
  • -fformat β€” the format used with -s and -i. valid options are ycfg and legacy. pick your fighter. πŸ₯Š
  • -a[xxx] β€” the AES secret key, as a 32 char hex value (or 40 for OATH-HOTP/HMAC CHAL-RESP). and listen β€” it's hex, not modhex. leave the argument off (just -a) and it'll prompt you for the key on stdin. and if you don't use -a at all, a random key gets generated for you. cute, right? 🎲
  • -c[xxx] β€” a 12 char hex value (again, not modhex) to use as the access code for programming. ⚠️ NOTE: this does NOT SET the access code. that's what -oaccess= is for. if you don't give it an argument, it prompts for the code on stdin. don't mix these two up, i'm begging. 😭
  • -ooption β€” change a configuration option. here's the menu of possible option arguments, and yes we're going through all of them:
    • fixed=fffffffffff β€” the modhex public identity of the YubiKey, 0-32 characters long (that's encoding up to 16 bytes). you can also hand it over in hex β€” just prepend the value with h:. the fixed part gets emitted before the OTP when the button on the YubiKey is pressed, and it can be used as an identifier for the user, for example. 🏷️
    • uid[=uuuuuu] β€” the uid part of the generated OTP, also known as the private identity, in hex. must be 12 characters long. the uid is 6 bytes of static data included (encrypted) in every OTP, and it's what validates that an OTP was actually encrypted with the AES key shared between the YubiKey and the validation service. 🫒 and no, you cannot use it to identify the YubiKey β€” it's only readable by the people who know the AES key. if you leave the argument off, the uid is prompted for on stdin. πŸ”
    • access[=fffffffffff] β€” the new hex access code to set. must be 12 characters long. once an access code is set, it'll be required for all subsequent reprogramming of the YubiKey β€” so like, remember it, bestie. 🫠 if you give no argument, the code is prompted for on stdin.
    • oath-imf=xxx β€” set the OATH Initial Moving Factor. this is the initial counter value for the YubiKey. it should be a value between 0 and 1048560, and it must be evenly dividable by 16. math is math. πŸ”’
    • ticket-flag β€” set/clear a ticket flag. see the TICKET FLAGS section. 🎟️
    • configuration-flag β€” set/clear a configuration flag. see the Configuration flags section. βš™οΈ
  • -y β€” always commit without prompting. no questions, just vibes. βœ…
  • -d β€” dry-run: run it all without actually writing to a YubiKey. rehearsal era. 🎭
  • -v β€” be more verbose. tell me everything. πŸ—£οΈ
  • -h β€” display help. πŸ†˜
  • -V β€” display version. 🏷️

πŸ¦‹ YubiKey Neo only πŸ¦‹

  • -n URI β€” program an NFC NDEF URI. πŸ“‘
  • -t text β€” program NFC NDEF text. ✍️

πŸ”₯ YubiKey 3 and 4 only πŸ”₯

  • -m mode β€” set the device configuration for the YubiKey. it gets parsed in the form mode:cr_timeout:autoeject_timeout, where mode is:
    • 0 β€” OTP device only.
    • 1 β€” CCID device only.
    • 2 β€” OTP/CCID composite device.
    • 3 β€” U2F device only.
    • 4 β€” OTP/U2F composite device.
    • 5 β€” U2F/CCID composite device.
    • 6 β€” OTP/U2F/CCID composite device.

add 80 to set MODE_FLAG_EJECT, for example: 81 πŸ‘‘

  • cr_timeout is the timeout in seconds for the YubiKey to wait on button press for challenge response (default is 15).
  • autoeject_timeout is the timeout in seconds before the card is automatically ejected in mode 81.
⚠️ bestie, listen carefully: removing OTP mode also disables communication between ykpersonalize and the YubiKey. after that, any further mode changes will have to be done with ykneomgr (for CCID mode) or u2f-host (for U2F mode). so like, don't do it casually. 😭

🌈 YubiKey 3 and above 🌈

  • -S0605... β€” set the scanmap to be used with the YubiKey. it must be 45 unique bytes as 90 characters. leave the argument empty to reset to the YubiKey's default. πŸ—ΊοΈ

the scanmap must be sent in the order:

cbdefghijklnrtuvCBDEFGHIJKLNRTUV0123456789!\t\r

the default scanmap in the YubiKey is:

06050708090a0b0c0d0e0f111517181986858788898a8b8c8d8e8f9195979899271e1f202122232425269e2b28

an example for simplified U.S. Dvorak would be:

0c110b071c180d0a0619130f120e09378c918b879c988d8a8699938f928e89b7271e1f202122232425269e2b28

or for a French azerty keyboard (digits are shifted):

06050708090a0b0c0d0e0f111517181986858788898a8b8c8d8e8f9195979899a79e9fa0a1a2a3a4a5a6382b28

or for a French BÉPO keyboard (French Dvorak):

0b140c0938363707130512330f0d16188b948c89b8b6b787938592b38f8d9698a79e9fa0a1a2a3a4a5a69c2b28

and a Turkish example (has a dotless i instead of the usual i):

06050708090a0b340d0e0f111517181986858788898a8b8c8d8e8f9195979899271e1f202122232425269e2b28
πŸ’€ note: you must remove any whitespace present in these examples before using the values. every space. gone. periodt.

πŸ‘‘ YubiKey 5 and above πŸ‘‘

  • -D0403... β€” set the deviceinfo to use with this YubiKey. 🧬

πŸ’œ YubiKey 2.3 and above πŸ’œ

  • -u β€” update the existing configuration, rather than overwriting. only possible if the slot is configured as updatable. ♻️
  • -x β€” swap configuration slot 1 and 2 inside the YubiKey. only possible if both slots are configured as updatable. πŸ”„

🎟️ TICKET FLAGS 🎟️

  • tab-first β€” send a tab character as the first character. this is usually used to move to the next input field. ➑️
  • append-tab1 β€” send a tab character between the fixed part and the one-time password part. super useful if you have the fixed portion equal to the user name and two input fields that you navigate between using tab. 🧠
  • append-tab2 β€” send a tab character as the last character. ⏭️
  • append-delay1 β€” add a half-second delay before sending the one-time password part. ⚠️ this option is only valid for firmware 1.x and 2.x.
  • append-delay2 β€” add a half-second delay after sending the one-time password part. ⚠️ this option is only valid for firmware 1.x and 2.x.
  • append-cr β€” add a carriage return after sending the one-time password part. ↩️

🧚 YubiKey 2.0 firmware and above 🧚

  • protect-cfg2 β€” when written to configuration 1, block later updates to configuration 2. when written to configuration 2, prevent configuration 1 from having the lock bit set. πŸ”’

🌸 YubiKey 2.1 firmware and above 🌸

  • oath-hotp β€” set OATH-HOTP mode rather than YubiKey mode. in this mode, the token functions according to the OATH-HOTP standard. πŸ“

πŸ“ YubiKey 2.2 firmware and above πŸ“

  • chal-resp β€” set challenge-response mode. 🎯

✨ CONFIGURATION FLAGS ✨

okay bestie, these are the personality flags β€” the ones that decide how your YubiKey actually behaves when you poke it. buckle up πŸ’–

  • send-ref β€” sends out a reference string made of all 16 modhex characters before the fixed part shows up. and listen: if you pair this with -ostrong-pw2, it also throws a ! in there before the rest of the string. cute, right? πŸŽ€
  • pacing-10ms β€” chills for 10ms between each key press. slow down, queen ✨
  • pacing-20ms β€” same vibe but 20ms between key presses. extra leisurely πŸ’…
  • static-ticket β€” outputs a fixed string instead of a one-time password. lowkey important: the password is still based on the AES key, and it should be hard to guess and, fr fr, impossible to remember. so don't try to memorise it, babe 😭

YubiKey 1.x firmware only

these ones are giving vintage. only for the OGs πŸ¦‹

  • ticket-first β€” sends the one-time password instead of the fixed part first. flip the order, periodt.
  • allow-hidtrig β€” lets the key be triggered through HID/keyboard by pressing caps-, num or scroll-lock twice.
ngl this one is not recommended for security reasons. it's giving risky behaviour, bestie πŸ’€

YubiKey 2.0 firmware and above

  • short-ticket β€” caps the static string length at max 16 digits. heads up: this flag only makes sense alongside -ostatic-ticket. and when you use -oshort-ticket without -ostatic-ticket, it programs the YubiKey in "scan-code mode", where the key sends the contents of fixed, uid and key as raw keyboard scancodes. for example, using the fixed string h:8b080f0f122c9a12150f079e in this mode will send Hello World! on a qwerty keyboard πŸŽ‰ and because it sends raw scan codes, the output will differ between keyboard layouts. no cap!
  • strong-pw1 β€” upper-cases the two first letters of the output string. it's for compatibility with legacy systems that enforce both uppercase and lowercase characters in a password, and it does not add any security. aesthetics only, bestie πŸ’…
  • strong-pw2 β€” replaces the first eight characters of the modhex alphabet with the numbers 0 to 7. just like -ostrong-pw1, this is intended to support legacy systems. again: legacy support, not a glow-up ✨
  • man-update β€” enables user-initiated update of the static password. only makes sense with the -ostatic-ticket option, and it is only valid for firmware 2.x. so if you're on something newer... she doesn't apply 🫢

YubiKey 2.1 firmware and above

  • oath-hotp8 β€” generates an 8-digit HOTP instead of a 6-digit one. more digits, more drama πŸ‘‘
  • oath-fixed-modhex1 β€” sends the first byte of the fixed part as modhex.
  • oath-fixed-modhex2 β€” sends the first two bytes of the fixed part as modhex.
  • oath-fixed-modhex β€” sends the fixed part as modhex. all of it. the whole thing πŸ’œ
  • oath-id=m:OOTTUUUUUUUU β€” configures the OATH token id with a value you provide. see the description of this option in the 2.2 section below for the details, but heads up: a YubiKey 2.1 key can't report its serial number, so you must specify a token identifier value yourself. no autopilot here πŸ™ˆ

YubiKey 2.2 firmware and above

  • chal-yubico β€” Yubico OTP challenge-response mode.
  • chal-hmac β€” generates HMAC-SHA1 challenge responses.
  • hmac-lt64 β€” calculates the HMAC on less than 64 bytes of input. whatever is sitting in the last byte of the challenge gets used as the end-of-input marker (backtracking from the end of the payload). tiny detail, big consequences ✨
  • chal-btn-trig β€” the YubiKey will wait for the user to press the key (within 15 seconds) before answering the challenge. she's patient, she's polite πŸŽ€
  • serial-btn-visible β€” the YubiKey will emit its serial number if the button is pressed during power-up. this option is only valid for the 2.x firmware line.
  • serial-usb-visible β€” the YubiKey will indicate its serial number in the USB iSerial field. this option is not available in the 3.0 and 3.1 firmwares. sad, I know 😭
  • serial-api-visible β€” the YubiKey will allow its serial number to be read using an API call. nerdy and iconic πŸ”₯
  • oath-id[=m:OOTTUUUUUUUU] β€” configures the OATH token id with a value you provide, or if you use it without a value, it just uses the standard YubiKey token identifier. slay πŸ¦‹

so the standard OATH token id for a Yubico YubiKey is (modhex) OO=ub, TT=he, and (decimal) UUUUUUUU=serial number.

the reason the serial number is decimal is so humans can easily correlate the serial number printed on the back of the YubiKey with an entry in a list of associated tokens, for example. other encodings can be done using the appropriate oath-fixed-modhex options. iykyk πŸ’–

note that the YubiKey must be programmed to allow reading its serial number, otherwise automatic token id creation is not possible. no serial, no auto-id, bestie.

for further details, see section "5.3.4 - OATH-HOTP Token Identifier" of the YubiKey manual at http://yubico.com/files/YubiKey_manual-2.0.pdf πŸ“–

YubiKey 2.3 firmware and above

  • use-numeric-keypad β€” sends scancodes for numeric keypad keypresses when sending digits β€” this helps with some keyboard layouts. this option is only valid for the 2.x firmware line. numbers, but make it keypad πŸ’…
  • fast-trig β€” faster triggering when only configuration 1 is available. and note: this option is always in effect on firmware versions 3.0 and above. it's automatic, she's always on ⚑
  • allow-update β€” allows updating (or swapping) of certain parameters in a configuration at a later time. future-proofing, periodt.
  • dormant β€” hides/unhides a configuration stored in a YubiKey. peekaboo πŸ™ˆ

YubiKey 2.4/3.1 firmware and above

  • led-inv β€” inverts the behaviour of the led on the YubiKey. dark mode but for a tiny light ✨

OATH-HOTP Mode

when you're in OATH-HOTP mode, you can supply a HMAC key of 160 bits (20 bytes, 40 chars of hex) with -a. that's the tea β˜•

Challenge-response Mode

in CHAL-RESP mode, the token will NOT generate any keypresses when the button is pressed. (although β€” plot twist β€” it is perfectly possible to have one slot with a keypress-generating configuration, and the other in challenge-response mode πŸ’–). instead, you need a program capable of sending USB HID feature reports to the token to send it a challenge, and then read the response. no keypresses, just vibes πŸ¦‹

Modhex

Modhex is a way of writing hex digits where the "digits" are chosen for being in the same place on most keyboard layouts. so your muscle memory never gets betrayed πŸ’…

to convert from hex to modhex, you can use:

tr "[0123456789abcdef]" "[cbdefghijklnrtuv]"

to convert the other way, use:

tr "[cbdefghijklnrtuv]" "[0123456789abcdef]"

🌸 EXAMPLES 🌸

programming for YubiCloud:

ouid=`dd if=/dev/urandom 2>/dev/null | tr -d '[:upper:]' | tr -cd '[:xdigit:]' | fold -w12 | head -1`
ofixed=ff`dd if=/dev/urandom 2>/dev/null | tr -d '[:upper:]' | tr -cd '[:xdigit:]' | fold -w10 | head -1`
ykpersonalize -1 -ouid=h:$ouid -ofixed=h:$ofixed

this will program a key with a random 6 byte uid and a 12 character fixed string starting with vv. and that is suitable for upload to YubiCloud at https://upload.yubico.com/ πŸŽ‰ iconic behaviour, honestly.


🫢 BUGS 🫢

report ykpersonalize bugs in the issue tracker at https://github.com/Yubico/yubikey-personalization/issues β€” the devs wanna hear it, bestie πŸ’œ


πŸ‘‘ SEE ALSO πŸ‘‘


and that's the whole page, babe πŸ’– this was ykpersonalize from Version 1.20.0, dated with the YKPERSONALIZE(1) manual page footer β€” so if you're reading the source, that's the version and date sitting right at the bottom, slay 🌈✨ go personalize something, you got this πŸ¦‹πŸŽ€