好的,既然你已经澄清了你想要做什么,我重写了我的答案。
总结一下:使用真正的加密算法。
首先,让我回顾一下为什么您的散列系统是一个坏主意。
无论如何,您的哈希系统是什么?
据我了解,您提出的系统是这样的:
您的嵌入式系统(我将其称为 C)正在发送某种值空间为 10^11 的数据。这些数据在传输到某种服务器(我将其称为 S)时需要保密。
您的建议是将值发送hash(salt + data)
给 S。然后 S 将使用彩虹表来反转此哈希并恢复数据。salt
是 C 和 S 都知道的共享值。
这是一个加密算法
加密算法,当你归结为它是任何给你保密的算法。由于您的目标是机密性,因此任何满足您目标的算法都是加密算法,包括这个。
这是一个很差的加密算法
首先,有不可避免的碰撞机会。此外,冲突值的集合每天都不同。
其次,即使对于合法服务器 S,解密也是极其耗费 CPU 和内存的。更改盐的成本更高。
第三,虽然您声明的目标是避免密钥管理,但您的盐是关键!您根本没有解决密钥管理问题;任何有盐的人都可以像你一样破解信息。
第四,它只能从 C 到 S 使用。你的嵌入式系统 C 将没有足够的计算资源来反转哈希,只能发送数据。
这并不比嵌入式设备上的真正加密算法快
大多数安全散列算法在计算上与合理的分组密码一样昂贵,如果不是更糟的话。例如,SHA-1 要求对每个 512 位块执行以下操作:
- 分配 12 个 32 位变量。
- 为扩展消息分配 80 个 32 位字
- 64 次:执行三个数组查找、三个 32 位异或和一个循环操作
- 80 次:最多执行 5 次 32 位二进制运算(xor、and、or、not 和 and 的某种组合,具体取决于轮次);然后是旋转、数组查找、四个添加、另一个旋转和几个内存加载/存储。
- 执行五个 32 位二进制补码相加
每 512 位消息有一个块,最后可能还有一个额外的块。这是每个块 1136 次二进制操作(不包括内存操作),或者每个字节大约 16 次操作。
为了比较,RC4 加密算法每个字节需要四个操作(三个加法,加上消息的异或),加上两次数组读取和两次数组写入。它还只需要 258 字节的工作内存,而 SHA-1 的峰值为 368 字节。
密钥管理是基础
对于任何保密系统,您都必须拥有某种秘密。如果你没有秘密,那么其他任何人都可以实现相同的解码算法,你的数据就会暴露给全世界。
所以,你有两个选择来把秘密放在哪里。一种选择是将加密/解密算法保密。但是,如果算法的代码(或二进制文件)被泄露,你就输了——很难替换这样的算法。
因此,秘密通常很容易替换——这就是我们所说的密钥。
您提议的哈希算法的使用将需要一个盐 - 这是系统中唯一的秘密,因此是一个密钥。不管你喜不喜欢,你都必须小心管理这个密钥。并且如果泄漏比其他密钥更难替换 - 每次更改时您都必须花费大量 CPU 小时生成一个新的彩虹表!
你该怎么办?
使用真正的加密算法,并花一些时间实际考虑密钥管理。这些问题之前已经解决了。
首先,使用真正的加密算法。AES专为高性能和低 RAM 要求而设计。正如我之前提到的,您还可以使用像 RC4 这样的流密码 - 但是,使用 RC4 需要注意的是,您必须丢弃密码输出的前 4 KB 左右,否则您将很容易受到同样的攻击困扰 WEP 的攻击。
其次,考虑密钥管理。一种选择是简单地将密钥刻录到每个客户端中,如果客户端受到威胁,则物理上出去并更换它。如果您可以轻松地物理访问所有客户端,这是合理的。
否则,如果您不关心中间人攻击,您可以简单地使用Diffie-Hellman 密钥交换来协商 S 和 C 之间的共享密钥。如果您担心中间人攻击,那么您需要开始查看ECDSA或其他东西来验证从 DH 交换获得的密钥 - 但请注意,当您开始走这条路时,很容易出错。我建议在那时实施 TLS。它并没有超出嵌入式系统的能力——事实上,已经有许多 嵌入式 商业(和开源) 库 可用。如果您不实施 TLS,那么在实施之前至少让专业的密码学家检查您的算法。