Show Source


Often, you will want to log in to a computer you control from a less-than-fully-trusted device (i.e. one that may be keylogging). If you don’t have a Factotum in your pocket, or the ability to do RSA in your head, this can pose a challenge. One answer, developed by Bell Labs is S/Key, a one-time password protocol.


This page is not intended to be comprehensive; you will have to RTFM if you want more than to copy my setup. Every bit of software discussed here has many more options than shown.

How does S/Key work?

Wikipedia can answer this better than I can, but here’s a summary. The basic idea is that there (are assumed to) exist one-way hash functions (MD5 is pretty good): computing H(x) given x is easy, but x given H(x) is hard. This idea extends to chains: H(H(x)) is easy given either H(x) or x, but either of these are hard to recover from H(H(x)). Using this to get one-time passwords is pretty straightforward: the server to which you wish to authenticate knows a “seed” value, N, and H(H(H(...H(H(secret, seed))...))), where there are N applications of the hash. The server tells you the seed and N-1, and you must present the (N-1)th power of H applied to (seecret, seed). The server checks that H(your response) is the value it knows (disconnecting you if it isn’t), then replaces the value it knew with your just-provided input for the next session and decrements N. If N hits zero, subsequent authentications are refused and you must generate new passwords.

To make this go, first, you have a S/Key calculator program which takes four things:

  • A seed (something like En3829; by default it’s the first two letters of the host name and a pseudorandom number)
  • The index of the top of the chain
  • A secret passphrase
  • A count of number of passwords to generate

You then tell the server that you wish to set your password, and it, or you, provides

  • A seed
  • The index of the top of the chain

Then the server asks you for the password at the top of the chain, and you use your calculator (generating a secret passphrase for yourself) to find out and tell it. You also ask your calculator for M more keys for subsequent logins.

Setting it up

The OPIE system provides the essential tools for making one time passwords fly on a modern UNIX system:

  • opiekey, the calculator tool.
  • opiepasswd, the password management tool (similar to the already present passwd utility).
  • libpam-opie, a Pluggable Authentication Modules module for using one time passwords. OPIE represents passwords as a string of six words from a 2048-entry dictionary (for at most 66 bits of entropy; OPIE uses 64 bit secrets internally), as in SON OVAL FLOG ALIA SOAK JAM. OPIE also provides some other tools that need not be considered in the initial setup.

Install OPIE

On Debian systems, OPIE is shipped in three packages; install them as follows:

apt-get install opie-{server,client} libpam-opie

Set up PAM and SSH to use OPIE

As a first pass, I set up SSH and sudo to allow the use of OPIE. (sudo for those emergencies where you need to run commands as root; this is not recommended, as a truly compromised terminal may be altering what it actually sends to the server.) I wanted to go further and actually disable non-one-time-passwords when sshing, but allow them for sudo. So here’re the changes I made:

  1. Modify /etc/ssh/sshd_config. The important directives here are

    ChallengeResponseAuthentication yes
    PasswordAuthentication no
    UsePAM yes

    Note that I also have PubkeyAuthentication yes for when I am logging in from a machine with my keys.

  2. Modify /etc/pam.d/sshd. I have only one auth directive in this file now:

    auth    requisite
  3. Modify /etc/pam.d/sudo. This file now contains

    auth    sufficient
    @include common-auth

    which means the same thing, on my system, as

    auth    sufficient
    auth    requisite nullok_secure
    auth    optional migrate

So SSH will first try key-based login; if that fails, it will try contacting PAM in ChallengeResponse mode, which will in turn give me an opportunity to use OPIE to log in. If that fails, SSH will give up. Sudo, on the other hand, will first try OPIE and, if that fails, ask for my UNIX password.

Set up OPIE

This method works even over a remote login. For a somewhat simpler method when you are on a secure console, see below.

  1. Run opiepasswd; the initial output will be something like this:

    nwf@Enthare:~$ opiepasswd
    Adding nwf:
    You need the response from an OTP generator.
    New secret pass phrase:
            otp-md5 499 En9290
  2. Run opiekey (in another terminal or having backgrounded opiepasswd), giving it the index and seed from opiepasswd:

    nwf@Enthare:~$ opiekey 499 En9290
    Using the MD5 algorithm to compute response.
    Reminder: Don't use opiekey from telnet or dial-in sessions.
    Enter secret pass phrase:
  3. Provide opiekey with your secret passphrase (which, for some measure of security must be at least 10 characters (and for archaic reasons, less than 127 characters) long). This will not be echoed to the screen. Upon pressing enter, opiekey will say something like this:

  4. Tell this to opiepasswd which will then output

    ID nwf OTP key is 499 En9290

If instead you are on a secure console to the machine (which, incidentally, opiepasswd considers Xterm not to be), or you wish to force it with -c (and -f if it still doesn’t believe you), opiepasswd can do all of this in one step:

nwf@Enthare:~$ opiepasswd -c
Adding nwf:
Only use this method from the console; NEVER from remote. If you are using
telnet, xterm, or a dial-in, type ^C now or exit with no password.
Then run opiepasswd without the -c parameter.
Using MD5 to compute responses.
Enter new secret pass phrase:
Again new secret pass phrase:

ID nwf OTP key is 499 En9290

Generate One-Time Passwords

This is easy: ask opiekey to generate keys for you!

nwf@Enthare:~$ opiekey -n 5 498 En9290
Using the MD5 algorithm to compute response.
Reminder: Don't use opiekey from telnet or dial-in sessions.
Enter secret pass phrase:

You can, of course, change the -n 5 to your liking.

It is highly suggested that you do not run opiekey when you are logged in from an untrusted machine, as it requires typing in your passphrase and immediately gives the next several passwords.

Test the setup

If you try logging in via ssh (and either don’t have keys or disable key-based login – -o PreferredAuthentications=keyboard-interactive is good for testing), you should see:

otp-md5 498 En9209 ext, Response:

Entering your 498th password here should allow you to log in.

Similarly, for sudo:

nwf@Enthare:~$ sudo echo test
otp-md5 497 En9209 ext, Response:

If you enter your 497th password here, it should work. If you just press enter or Ctrl-D or botch typing your password, you should see a second, more familiar, prompt:

nwf@Enthare:~$ sudo echo test
otp-md5 497 En9209 ext, Response:
[sudo] password for nwf:

Changing Or Regenerating Passwords

Due to the design of S/Key, opiekey can only crank out up to the limit (499 in the examples) passwords before you must redo some part of this process. opiepasswd is again the right program here and will guide you through this. If it thinks you are logging in remotely, it will ask you to provide one more password using your current system and then ask for the new password top as it did before. If it thinks you are on a secure console, it can ask you for your old secret passphrase directly as when generating keys the second way, above.

OTP Calculators

Of course, the opiekey calculation doesn’t depend on anything that you don’t have: your secret you know, presumably, and the challenge from OPIE gives you the index and seed. Therefore, you can use another computer to generate your passwords, rather than writing them down, if you prefer. If you have a UNIX box, opiekey itself will do just fine. There are some other S/Key calculators out there, though do not consider these links endorsements:

And many more through Google (TM), to be sure. S/Key is an old protocol.