Damion Brown's Blog

D97A 07F3 DCB1 302D

YubiKey for SSH via Yubico OTP

  • Sun 28 April 2019
  • Tech

YubiKey ChallengeResponseAuthentication

YubiKey's and Yubico OTP

A YubiKey is comparable to a Trusted Platform Module, but wrapper up in a secure crush-resistant USB interface package.

Yubico One-Time Password (OTP) is a function of the Yubikey whereby a 128-bit (44-char) blob is produced via keyboard emulation.

Via the Pluggable Authentication Module (PAM) yubico-pam we can require an OTP as a Multi-Factor Authentication (MFA) scheme.


First, install the yubico PAM module - I advise using the system package manager.

sudo apt-get update
sudo apt-get install libpam-yubico

Head over to yubico.com/getapikey/ and generate yourself a Client ID.

Modify /etc/pam.d/sshd with the following line:

auth sufficient pam_yubico.so id=[Your API Client ID] debug

Check the pam_yubico.so file is located in /lib/security/ (or wherever PAM modules live in your system).

Now some technical trivia:

By default the OpenSSH daemon is configured to use the 'password' authentication scheme (defined in RFC-4252 § 8)

To use the yubico-pam module, we need to switch to the 'keyboard-interactive' authentication scheme (defined in RFC-4256)

Modify your /etc/ssh/sshd_config and:

  • set PasswordAuthentication to no
  • set ChallengeResponseAuthentication to yes

Without making this change, the yubico-pam module is unable to prompt the client to enter an OTP.

Authorization Mapping Files

The mapping file authorizes YubiKey(s) to provide OTP codes for authentication.

It is stored in a user's home directory under ~/.yubico/authorized_yubikeys and must contain a user name and a YubiKey token ID separated by colons.

The file must have only one line and should look like this:

<user name>:<YubiKey token ID1>:<YubiKey token ID2>
Obtaining the YubiKey token ID (a.k.a. public ID)

A YubiKey token ID is included as part of each 128-bit OTP blob, specifically the first 12 characters.

  1. Open a terminal
  2. Press the YubiKey's button, It will output an OTP into the shell:

$ cccccccgklgcvnkcvnnegrnhgrjkhlkfhdkclfncvlgj 
bash: cccccccgklgcvnkcvnnegrnhgrjkhlkfhdkclfncvlgj: command not found

The user's YubiKey token ID would be cccccccgklgc


If you're running into issues, add the debug directive to the end of your /etc/pam.d/ configuration line for the yubico-pam module.

Then create a world-writeable log file

touch /var/run/pam-debug.log
chmod go+w /var/run/pam-debug.log

yubico-pam debug


More documentation about yubico-pam and configurable directives

Modifying /etc/ssh/sshd_config will only require an OTP code for SSH authentication

  • If you modified instead /etc/pam.d/sudo or /etc/pam.d/common-password, then OTP codes would be required for those authentication methods.

The Yubico server ensures that OTP codes cannot be used in a replay attack

  • If you don't want to rely on an external service, or you have an offline system or network - you can host your own validation server.

For a more detailed explination about PasswordAuthentication and ChallengeResponseAuthentication

If you are using Public Key Infastructure (PKI) with SSH

  • Note that PAM modules are not used as PKI is performed within the OpenSSH daemon itself. I think this is doable but I havn't looked into it.

To disable SSH private key usage on a client

ssh -o PubkeyAuthentication=no example.com

For more information on PAM auth control flags

Can I use yubico-pam with google-authenticator-libpam?

  • Yes, you should set your PAM configuration like so:

auth [success=1 default=ignore] pam_yubico.so id=[Your API Client ID]
auth required pam_google_authenticator.so no_increment_hotp
  • The [success=1 default=ignore] means that on success, the next 1 line will be skipped. Any other result will cause the module's results to be ignored.

For more information on advanced PAM auth control flags