SKEY 的一个应用

11 Mar 2014

利用 sleekxmpp 或其它 xmpp 协议的实现, 可以方便的搭建 Gtalk 聊天机器人。也有根据Webqq 开放的接口实现的机器人,如 pual_bot。 利用这些聊天服务器的消息转发, 可以使我们和内网的主机通信: 比如我们在公司的内网, 需要让在家里连网的树莓派启动一个wget http://abcde/xxxx.rmvb下载任务, 就可以通过 GTalk 发给树莓派运行的聊天机器人, 让它调用 shell 命令, 无需考虑穿越 NAT 的问题。

考虑这样一个场景:假如限定你的Gtalk账户与树莓派运行的聊天机器人的账户只能在一个群里通话,你和机器人的所有通信内容都可以被群里面的其他人看到,你希望只能自己操控机器人,而不希望群里的其他成员控制机器人,怎么做到呢?这类似于《应用密码学》里面说的阀下通道问题, 不过阀下通道要求更为严格,要求监听者无法获取通信双方发送消息的真实含义。

我之前想的一个实现是:与机器人约定一个密码, 每次执行一个指令之前, 机器人产生一个随机数, 发送到群里, 然后我把这个随机数与密码相连做一次md5, 再附送需要执行的指令, 发送到群里, 机器人接收到后, 通过验证这个md5值即可知道是否是掌握密码的主人发来的命令, 若是正确的,执行后同时发送下一个随机数到群里, 供下一次命令时用。其他人无法根据这个md5逆推出密码, 自然就无法构造一个可以通过验证的消息了。

上面的方法麻烦之处在于, 每执行一个命令, 需要机器人发送一次随机数, 增加了通信的次数。有没有办法既能减少通信次数又能达到不泄漏密码的要求呢?我回想起之前介绍过的 SKEY, 这不正好可以应用嘛。选择一个单向函数f(),只要一次性构造出一系列数 f(R), f(f(R)), f(f(f(R))), … 将这一系列数命名为 X[1], X[2], X[3],… 每次发送命令时, 附带最末尾未使用过的数X[i], 机器人收到后计算 f(X[i]), 并和存储在里面的 X[i+1]比较。如果匹配, 就执行, 然后机器人用X[i] 替换掉 X[i+1], 供下次验证用. 下一次命令只要附带X[i-1] 就可以了, 直到所有数都使用完。