IPsec 预共享密钥:你输入的那串字符背后的字节
两端可能持有看起来相同、却派生出不同密钥的字符串。在削弱任何东西之前,先检查字段类型、任何编码以及末尾字节。
两位管理员在屏幕上比对密钥,都认为它一致,隧道却仍然认证失败。他们比对的那串字符,并不是任何一端送入密钥派生的值。在你看到的字符和协议哈希的字节之间,还有字段类型、文本编码、编辑器和剪贴板,这四者中的任何一个都能在不改变外观的情况下改变输入。比对字节,分歧通常几秒内就会显现。
网关如何处理这串字符
预共享密钥并不会在网络上传输再作比对。每一端都把自己的本地副本送入 IKE 交换的密钥派生,得到的认证载荷要么通过验证,要么不通过。这种设计意味着两份副本必须逐字节相同,而不能只是看起来相似;这也意味着失败会在认证阶段报告,而不是以密码错误的形式出现。
所以真正有用的问题从来不是“它们看起来一样吗”,而是“每个实现到底哈希了哪一串确切的字节”。
多余的字节从哪里来
行尾换行是经典元凶,而且它藏在明处,因为大多数编辑器保存文件时会悄悄加上一个。从聊天窗口粘贴进来的首尾空格也会这样,文字处理软件把直引号换成弯引号同样如此。这些都不会改变人眼所做的比对。
用显示字节而不是字形的工具来比对。printf '%s' "$PSK" | xxd | tail -2 会以十六进制打印该值的尾部,多余的 0a 或 20 一目了然。在两端都做一次,把两份转储并排比对。请在生成的测试材料上做,不要拿生产密钥来做,之后又把它留在 shell 历史里。
编码不等于加密
配置导出经常以某种基础编码携带密钥,有时每六十或七十六个字符换行,有时带填充。如果一端期待解码后的字节,而你粘贴的是编码后的文本,你发送的就不是另一个密码,而是一个由可打印字符组成的、长得多的密码。Base64 完全不提供保密性,这也是为什么编码后的密钥绝不能贴到论坛上求第二意见。
Apple 的 IPSec 字典是说明类型很重要的一个有用例子:它把 SharedSecret 记录为 L2TP 和 Cisco IPsec 载荷中共享密钥认证方法的数据。那是特定载荷中的特定属性,不是一个可以拿去复用于另一个恰好要求密钥的协议的通用文本字段。
所谓上限只属于某一种组合
关于某个 Apple 客户端有三十二字符上限的旧报告,是关于某一个客户端版本、协议和配置形状的真实报告。它们不是适用于每个 Apple 平台、每个提供商和每种协议的普遍限制。把版本、载荷类型和网关要求放在一起核对,然后在经过批准的配置上测试,而不是从帖子里推断。把测试过的组合写进变更记录,否则下一个人会引用同一个帖子,而且比它应得的更自信。
如果某项限制确实适用,答案应当是符合它的、受支持的凭据设计,而不是把强密钥截短。为了满足一个猜测出来的上限而截断生产密钥,会永久降低其强度,并产生一个文档与安全性不再匹配的系统。
修正表示形式,而不是强度
在确认表示形式之后认证仍然失败时,去读认证阶段实际生效的策略:正在协商哪种方法、期望哪个对端身份,以及网关是否匹配你认为的那条连接。逐步降低猜测不是诊断,而是附带着支持工单的缓慢降级。
如果所需的凭据无法满足组织标准,就改成能满足的设计。一个具有足够熵的共享密钥,生成一次、存放在受管字段中、从不公开,就是完全正确的答案;把它缩短则不是。