Introduction

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.

Note

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:

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

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:

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       pam_opie.so
    
  3. Modify /etc/pam.d/sudo. This file now contains

    auth    sufficient      pam_opie.so
    @include common-auth
    

    which means the same thing, on my system, as

    auth    sufficient      pam_opie.so
    auth    requisite       pam_unix.so nullok_secure
    auth    optional        pam_smbpass.so 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
            Response:
    
  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:

    SON OVAL FLOG ALIA SOAK JAM
    
  4. Tell this to opiepasswd which will then output

    ID nwf OTP key is 499 En9290
    SON OVAL FLOG ALIA SOAK JAM
    

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
SON OVAL FLOG ALIA SOAK JAM

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:
494: CUT MEAN FLY SILT LILA THIN
495: HUNT ALUM COAL QUIT SEEK FUEL
496: BAH GLAD ED HIND SINE MOST
497: CARR MAD VET HAD BARD ACTS
498: TIE DAVY SLOW TED LOU WORE

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.