【发布时间】:2014-10-27 10:07:07
【问题描述】:
我正在尝试找出一种在微控制器项目上实现体面加密的方法。我有一个基于 ARMv4 的 MCU,它将控制我的车库门并通过 WiFi 模块接收命令。
MCU 将运行一个 TCP/IP 服务器,它将侦听来自可以从 Internet 上任何地方连接的 Android 客户端的命令,这就是我需要实现加密的原因。
我了解如何使用带有共享密钥的 AES 来正确加密流量,但我发现很难处理重放攻击。到目前为止,我看到的所有解决方案都有严重的缺陷。
有两个基本问题阻碍了我很好地使用 已建立的方法,如会话令牌、时间戳或随机数:
MCU没有可靠的熵源,所以无法生成 质量随机数。
攻击者可以通过切断车库电源来重置 MCU, 从而随意擦除任何存储的状态,并将时间计数器重置为 零(或等待 49 天直到它循环)。
考虑到这些限制,我只能看到一种方法似乎 对我来说没问题(即我还不知道如何打破它)。不幸的是,这 需要非易失性存储,这意味着写入外部闪存, 由于各种技术细节,这引入了一些严重的复杂性。
我很想就以下解决方案获得一些反馈。更好的是,我是否缺少不需要非易失性存储的解决方案?
请注意,此项目的主要目的是教育。我意识到我可以通过在我的防火墙内设置一个安全中继来简化这个问题,让它处理互联网流量,而不是直接暴露 MCU。但这有什么乐趣呢? ;)
= 建议的解决方案 =
将使用一对共享的 AES 密钥。一把钥匙将 Nonce 变成 CBC 阶段的 IV,另一把钥匙用于加密消息本身:
- 分享消息
Key - 分享
IV_Key
这是我在做什么的图片: https://www.youtube.com/watch?v=JNsUrOVQKpE#t=10m11s
1) Android 以毫秒为单位占用当前时间 (Ti)(64 位长)和
使用它作为 CBC 阶段的 nonce 输入来加密命令:
a) IV(i) = AES_ECB(IV_Key, Ti)
b) Ci = AES_CBC(Key, IV(i), COMMAND)
2) Android 利用/dev/random 生成IV_Response
MCU 将用于回答当前请求。
3) Android 发送[<Ti, IV_Response, Ci>, <== HMAC(K)]
4) MCU 使用 HMAC 接收并验证完整性,因此攻击者无法
修改纯文本Ti。
5) MCU 检查Ti > T(i-1) 是否存储在闪存中。这确保了
录制的消息无法重播。
6) MCU计算IV(i) = AES_ECB(IV_Key, Ti)并解密Ci。
7) MCU 使用AES_CBC(Key, IV_Response, RESPONSE) 响应
8) MCU 将Ti 存储在外部闪存中。
这行得通吗?有没有更简单的方法?
编辑: 在 cmets 中已经表明这种方法容易受到延迟播放攻击。如果攻击者记录并阻止消息到达MCU,那么消息可以在以后的任何时间回放,仍然被认为是有效的,所以这个算法不好。
正如@owlstead 所建议的,可能需要一个质询/响应系统。除非我能找到解决办法,否则我认为我需要执行以下操作:
- 移植或实施一个体面的 PRGA。 (有什么建议吗?)
- 为 PRGA 预先计算大量随机种子值。每次 MCU 重启都会使用一个新种子。假设 128 位种子,16K 的存储购买了 1000 个唯一种子,因此在 MCU 成功使用至少一个 PRGA 输出值并重新启动 1000 次之前,这些值不会循环。这似乎还不错。
- 使用 PRGA 的输出来生成挑战。
这听起来对吗?
【问题讨论】:
-
有些东西告诉我,对于质询响应协议,您应该首先从门发送质询,然后 - 在特定时间范围内 - 接受质询。现在攻击者可以在他们到达门之前捕获加密命令并随时打开门(通过转发捕获的消息)。
-
啊,在某个时间范围内,“接受(经过身份验证的)挑战响应”。
-
@owlstead 你是对的——我的算法似乎容易受到你描述的攻击。我正在考虑对每个请求使用挑战/响应方法,但这需要 MCU 能够选择唯一的 Nonce。这反过来又需要一个 PRGA,并且由于没有可用的随机性,它还需要一个预先计算的种子表,所以我们可以在每次重启时使用一个新的。我希望避免必须实施或移植 PRGA,但也许我毕竟必须这样做。我的想法是否正确?
-
您可以只使用随机数作为挑战 - 挑战不一定是随机的,尽管它需要写入 EEPROM 来更新计数器(总是提前更新计数器我>)。也许使用挑战响应的Kerberos method。
标签: security encryption cryptography aes