14.5. 一次性口令

S/Key 是基于单向 hash 功能的一次性密码管理方式。 为了考虑兼容性而使用了 MD4 散列, 而其他系统则使用了 MD5 和 DES-MAC。 S/Key 从 1.1.5 版之后就一直是 FreeBSD 基本系统的一部分, 包含这一特性的操作系统也日益增多。 S/Key 是 Bell Communications Research, Inc. 的注册商标。

从 FreeBSD 的 5.0 版开始, S/Key 被功能相同的 OPIE (One-time Passwords In Everything) 取代了。 OPIE 默认使用 MD5 散列。

下面将介绍三种不同的口令。 第一种是您常用的 UNIX® 风格或 Kerberos 口令; 我们在后面的章节中将称其为 “UNIX 口令”。 第二种是使用 S/Key key 程序或 OPIE opiekey(1) 程序生成, 并为 keyinitopiepasswd(1) 以及登录提示所接受的一次性口令,我们称其为 “一次性口令”。 最后一类口令是您输入给 key/opiekey 程序 (有些时候是 keyinit/opiepasswd 程序) 用以产生一次性口令的秘密口令,我们称其为 “秘密口令” 或简称为 “秘密口令”。

秘密口令和您的 UNIX 口令毫无关系, 尽管可以设置为相同的, 但不推荐这么做。 S/Key 和 OPIE 秘密口令并不像旧式的 UNIX 口令那样只能限于8位以内[1]。 您想要用多长的口令都可以。 有六、七个词的短句是很常见的选择。 在绝大多数时候, S/Key 或 OPIE 系统和 UNIX 口令系统完全相互独立地工作。

除了口令之外, 对于 S/Key 和 OPIE 还有两组至关重要的数据。 其一被称作 “种子” 或 “key”, 它包括两个字符和五个数字。 另一个被称作 “迭代轮数”, 这是一个 1 到 100 之间的数字。 S/Key 通过将种子加到秘密口令后面, 并执行迭代轮数那么多次的 MD4/MD5 散列运算来得到结果, 并将结果表示为 6 个短的英文单词。 这 6 个英文单词就是您的一次性口令。 验证系统 (主要是 PAM) 会记录上次使用的一次性口令, 如果用户提供的口令的散列值与上次一致, 则可以通过身份验证。 由于使用了单向的散列函数, 因此即使截获了上次使用的口令, 也没有办法恢复出下次将要使用的口令; 每次成功登录都将导致迭代轮数递减, 这样用户和登录程序将保持同步。 每当迭代轮数减少到 1 时, 都必须重新初始化 S/Key 和 OPIE。

接下来将讨论和每个系统有关的三个程序。 keyopiekey 程序能够接收带迭代计数, 种子和秘密口令, 并生成一个一次性口令, 或一张包含所有有关口令的表格。 keyinitopiepasswd 程序分别用于初始化 S/Key 和 OPIE, 并修改口令、 迭代次数、种子和一次性口令。 keyinfoopieinfo 程序可以用于检查相应的验证数据文件 (/etc/skeykeys/etc/opiekeys) 并显示执行命令的用户当前的迭代轮数和种子。

我们将介绍四种不同的操作。 在安全的连接上通过 keyinitopiepasswd 来第一次设置一次性口令, 或修改口令及种子。 第二类操作是在不安全的连接上使用 keyinitopiepasswd 辅以在安全连接上执行的 keyopiekey 来完成同样的工作。 第三类操作是在不安全的连接上使用 key/opiekey 来登录。 最后一类操作是采用 keyopiekey 来生成大批的密码, 以便抄下来或打印出来,在没有安全连接的地方使用。

14.5.1. 安全连接的初始化

第一次初始化 S/Key, 修改口令或种子需要在安全的连接 (例如, 在那台机器的控制台上或者通过 ssh) 登录来完成。 以自己的身份登录并执行不带参数的 keyinit 命令:

% keyinit
Adding unfurl:
Reminder - Only use this method if you are directly connected.
If you are using telnet or rlogin exit with no password and use keyinit -s.
Enter secret password:
Again secret password:

ID unfurl s/key is 99 to17757
DEFY CLUB PRO NASH LACE SOFT

对于 OPIE, 则使用 opiepasswd

% opiepasswd -c
[grimreaper] ~ $ opiepasswd -f -c
Adding unfurl:
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 unfurl OTP key is 499 to4268
MOS MALL GOAT ARM AVID COED

Enter new secret pass phrase:Enter secret password: 提示之后, 应输入一个密码或口令字。 请留意, 这并不是您用于登录的口令, 它用于生成一次性的登录密钥。 “ID” 这一行给出了所需的参数: 您的登录名, 迭代轮数, 以及种子。 登录系统时, 它能够记住这些参数并呈现给您, 因此无需记忆它们。 最后一行给出了与您的秘密口令对应的、用于登录的一个一次性口令; 如果您立即重新登录, 则它将是您需要使用的那个口令。

14.5.2. 不安全连接初始化

如果您需要通过一个不安全的连接来初始化, 则应首先在安全连接上执行过一次 keyopiekey; 这可以在 Macintosh® 的桌面附件, 或是在可信的机器的 shell 上面完成。 此外还需要指定一个迭代轮数 (100 也许是一个较好的选择) 也可以选择一个自己的种子, 或让计算机随机生成一个。 在不安全的连接上 (当然是连到您希望初始化的机器上),使用 keyinit -s 命令:

% keyinit -s
Updating unfurl:
Old key: to17758
Reminder you need the 6 English words from the key command.
Enter sequence count from 1 to 9999: 100
Enter new key [default to17759]:
s/key 100 to 17759
s/key access password:
s/key access password:CURE MIKE BANE HIM RACY GORE

对于 OPIE, 则需要使用 opiepasswd

% opiepasswd

Updating unfurl:
You need the response from an OTP generator.
Old secret pass phrase:
        otp-md5 498 to4268 ext
        Response: GAME GAG WELT OUT DOWN CHAT
New secret pass phrase:
        otp-md5 499 to4269
        Response: LINE PAP MILK NELL BUOY TROY

ID mark OTP key is 499 gr4269
LINE PAP MILK NELL BUOY TROY

为了接受默认的种子 ( keyinit 程序令人困惑地将其称作 key), 按下 Return。 在输入访问口令之前, 到一个有安全连接或 S/Key 桌面附件的机器上, 并给它同样的参数:

% key 100 to17759
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password: <secret password>
CURE MIKE BANE HIM RACY GORE

对于 OPIE:

% opiekey 498 to4268
Using the MD5 algorithm to compute response.
Reminder: Don't use opiekey from telnet or dial-in sessions.
Enter secret pass phrase:
GAME GAG WELT OUT DOWN CHAT

现在回到不安全的连接, 并将生成的一次性口令粘贴到相应的应用程序中。

14.5.3. 产生一个一次性密码

一旦初始化过 S/Key 或 OPIE, 当您登录时将看到类似这样的提示:

% telnet example.com
Trying 10.0.0.1...
Connected to example.com
Escape character is '^]'.

FreeBSD/i386 (example.com) (ttypa)

login: <username>
s/key 97 fw13894
Password:

对于 OPIE 则是:

% telnet example.com
Trying 10.0.0.1...
Connected to example.com
Escape character is '^]'.

FreeBSD/i386 (example.com) (ttypa)

login: <username>
otp-md5 498 gr4269 ext
Password:

另外, S/Key 和 OPIE 提示有一个很有用的特性 (这里没有表现出来): 如果您在口令提示的地方按下 Return 则将开启提示返显, 您可以藉此看到自己所键入的内容。 如果试图手工键入一个一次性密码, 这会非常有用。

此时您需要生成一个一次性密码来回答这一提示。 这项工作必须在一个可信的系统上执行 keyopiekey 来完成。 (也可以找到 DOS、 Windows® 以及 Mac OS® 等操作系统上运行的版本)。 这个程序需要将迭代轮数和种子提供给它。 您可以从登录提示那里复制和粘贴它们。

在可信的系统上:

% key 97 fw13894
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password:
WELD LIP ACTS ENDS ME HAAG

对于 OPIE:

% opiekey 498 to4268
Using the MD5 algorithm to compute response.
Reminder: Don't use opiekey from telnet or dial-in sessions.
Enter secret pass phrase:
GAME GAG WELT OUT DOWN CHAT

现在使用刚刚生成的一次性口令登录:

login: <username>
s/key 97 fw13894
Password: <return to enable echo>
s/key 97 fw13894
Password [echo on]: WELD LIP ACTS ENDS ME HAAG
Last login: Tue Mar 21 11:56:41 from 10.0.0.2 ...

14.5.4. 产生多个一次性口令

有时,会需要到不能访问可信的机器或安全连接的地方。 这中情形下, 可以使用 keyopiekey 命令来一次生成许多一次性口令。 例如:

% key -n 5 30 zz99999
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password: <secret password>
26: SODA RUDE LEA LIND BUDD SILT
27: JILT SPY DUTY GLOW COWL ROT
28: THEM OW COLA RUNT BONG SCOT
29: COT MASH BARR BRIM NAN FLAG
30: CAN KNEE CAST NAME FOLK BILK

对于 OPIE:

% opiekey -n 5 30 zz99999
Using the MD5 algorithm to compute response.
Reminder: Don't use opiekey from telnet or dial-in sessions.
Enter secret pass phrase: <secret password>
26: JOAN BORE FOSS DES NAY QUIT
27: LATE BIAS SLAY FOLK MUCH TRIG
28: SALT TIN ANTI LOON NEAL USE
29: RIO ODIN GO BYE FURY TIC
30: GREW JIVE SAN GIRD BOIL PHI

-n 5 按顺序请求 5 个口令, 30 则指定了最后一个迭代轮数应该是多少。 注意这些将按按与使用相反的顺序显示。 如果您比较偏执, 可以手工写下这些结果; 一般来说把它粘贴到 lpr 就可以了。 注意,每一行都显示迭代轮数机器对应的一次性的密码; 一些人建议用完一个就划掉一个。

14.5.5. 限制使用 UNIX® 口令

S/Key 可以对 UNIX 口令的使用实施基于主机名、 用户名、 终端端口或登录会话的 IP 地址的各种限制。 这些限制可以在配置文件 /etc/skey.access 中找到。 skey.access(5) 联机帮助提供了关于文件格式的详细资料, 并给出了更详细的使用这一配置文件时在安全方面需要注意的事项。

如果没有 /etc/skey.access 这个文件 (在 FreeBSD 4.X 系统上这是默认的), 那么所有的用户都可以使用 UNIX 口令。 然而如果它存在, 所有的用户将被要求使用 S/Key, 除非明确地在 skey.access 中配置允许这样做。 无论如何, UNIX 在控制台上总是可用的。

下面是一个示例的 skey.access 配置文件, 它展示了最常用的三类配置语句:

permit internet 192.168.0.0 255.255.0.0
permit user fnord
permit port ttyd0

第一行 (permit internet) 允许来自这些 IP 的用户 (这类 IP 很容易伪造) 使用 UNIX 口令。 这不应被认为是一种安全的机制, 因为使用不安全的网络的用户需要使用 S/Key 验证。

第二行 (permit user) 允许指定的用户, 在本例中是 fnord, 在任何时候使用 UNIX 口令。 一般说来, 只应为无法使用 key 程序, 例如使用哑终端的那些人, 或无法学会如何使用它的人来使用。

第三行 (permit port) 允许通过指定终端线的用户使用 UNIX 口令; 这可以被用于拨号用户。

OPIE 可以像 S/Key 一样对 UNIX 口令的使用进行基于 IP 的登录限制。 对应的文件是 /etc/opieaccess, 在 FreeBSD 5.0 以及更新一些的系统中它是缺省存在的。 请参阅 opieaccess(5) 以了解关于这个文件进一步的情况, 以及安全方面需要进行的一些考虑。

这是一个示范的 opieaccess 文件:

permit 192.168.0.0 255.255.0.0

这行允许指定 IP 地址的用户 (再次强调这种地址容易被伪造) 在任何时有使用 UNIX 口令登录。

如果 opieaccess 中没有匹配的规则, 则将默认拒绝任何非 OPIE 登录。

Notes

[1]

在 FreeBSD 中标准的登录口令最长可达 128 个字符那么长。