我正在开发一种用于两个微控制器之间无线通信的协议,使用433Mhz调制解调器,可以以原始格式发送串行数据(如果需要,可以发送纯文本)。 我知道这听起来更像是一个电子问题,但我的问题在于编码部分,让我解释一下自己。
假设单位1将此命令“0x001 / 0x010 / LIGHT1 / ON” (这是纯文本)发送到单元2,第一个是单元1名称,第二个是单元2名称,第三个是执行器,最后一个是行动。 一切都好,工作,但我想给系统一点安全性,因为如果有人用“中间人”这样的技术听这个频率可以很容易地复制命令并在任何时候重新发送它想。
我正在考虑加密通过空中传输的消息,但是再次这不会保护系统免受相同类型的攻击,假设我使用像MD5这样的东西加密消息,我会传输类似“767b79ebb8061054d3ad1eaef428b469”的内容 ,攻击者只是需要复制该字符串并重新发送它以获得相同的结果。
那我怎么解决这个问题呢? 考虑到我不是在控制核反应堆,所以我不需要非常高的安全性。
我假设,每个节点“知道”它应该从中接收命令的节点 - 在这种情况下,接收节点为它将从中获取命令的每个节点存储(简单)密钥,然后向协议添加三个字段:
发送方和接收方都存储了tx-> rx关系的最后使用的序列号,发送方使用每个命令增加它。
发送方和接收方都创建串联SequenceNumber+Command+SequenceNumber+salt+nodekey
的哈希值(SHA1?)
编辑: nodekey
是发送节点的密钥
发送方将此作为认证字段发送,接收方根据认证字段对其进行检查,并仅接受该命令,如果序列号高于LRU序列号并且认证字段检出OK。
这对于重放攻击是安全的,因为它涉及序列号重用。
编辑:
关于序列号中的同步丢失的评论存在担忧,但是所提出的解决方案具有弹性:只有发送方将增加SN,并且接收方将接受高于上次使用的所有SN。 丢失消息将使SN跳跃,但仍然会被接受为高于LRU。
假设我使用类似MD5的东西加密消息,我会发送类似“767b79ebb8061054d3ad1eaef428b469”的内容,
您不使用MD5进行加密。 您发送命令的哈希值。 这意味着在接收端,您需要有一个反向查找表来映射您发送到相应命令的消息摘要。
攻击者只需复制该字符串并重新发送即可获得相同的结果。
这是一个有效的问题,它属于重播攻击类别。 有很多方法可以解决这个问题,但需要相当多的努力来重新设计发射器和接收器
您应该考虑使用某种依赖于密钥的加密。 当然,关键可能必须以某种方式确定,两个控制器都可以保持同步 - 也许一些使用时间的方法就足够了。 类似PHP的time()
函数,四舍五入到最接近的百位。 每个控制器在获得信号时都可以检查当前的舍入时间戳和前一个时间戳,因此如果攻击者获得加密信号,则最多只能重复使用200秒。 根据传输每个信号所需的时间和所需的安全级别(以及可能的频率,您可以使用丢失的信号离开),您可能需要十到五秒钟。 使用一些伪代码(舍入到十):
发送:
signal=encrypt(outgoing, round(time, 10))
sendSignal(signal)
接收:
signal=decrypt(incoming, round(time, 10))
if (invalid(signal)) {signal=decrypt(incoming, round(time, 10)-10)}
interpretSignal(signal)
如第二行所示,您需要某种方式来确定解密信号是否有效。
这就是我想到的应该始终保持同步的通用密钥机制。 但是,基本思想是使用频繁变化的密钥加密信号,发送者和接收者都知道或可以确定。