我想不可逆地将小文本字符串转换为固定大小的二进制字符串。
输入字符串是任意计算机程序中的标识符,该程序正在以多种不相关的方式进行转换。此特定操作部分的目标是通过删除有意义的标识符来使程序更难以进行逆向工程。
在某些情况下(例如序列化),执行系统仍然需要形成与任何给定程序元素相对应的稳定且唯一的文本字符串,这将通过以某种方式将二进制字符串转换为文本来获得。
通过使用顺序标识符重新分配标识符来混淆标识符的方案(a
..z
、aa
..az
,...) 在这里遇到一个弱点,即标识符的分配本质上不是稳定。对于许多程序来说这并不重要,但在这种情况下,各种程序和各种程序版本可能需要互操作。因此,在这样的方案中,我们需要一个包含先前分配的持久数据库。
在此应用程序中,我决定可以通过根据以下内容选择输出标识符(其中 x 是原始标识符),以牺牲因碰撞而导致的天文数字般小的失败概率,以大大提高便利性:
f(x) = hash( x )
这将满足功能要求,但无论使用什么哈希函数都不会安全;由于熵低,原始标识符可以很容易地恢复。
我认为这可以通过使用以下方法来纠正:
f(x) = 哈希( secret + x)
“ secret ”将是一个固定的、任意长的随机数,我们可以假设攻击者没有有先验。
我想使用 MD5 进行哈希,因为 f(x) 将为 16 字节,这是一个相当方便的大小。其他更安全的哈希值将产生更大的标识符,如果它们太过杀伤力,我希望避免这种情况。
我本以为考虑到这个大 secret ,即使在这里使用 MD5 也可以,但我在很多地方都读到过 MD5 已被破坏。
对 MD5 的任何已知攻击是否会使得攻击者人为地容易[1]猜测 x 仅知道 f(x) 的值,并且 x 可能是由相当大的小词典? (我猜不是,但我不是安全专家。)
我意识到,如果攻击者确实对一个程序进行逆向工程,她可以使用相同的“ secret ”更轻松地理解其他程序,即使她没有“ secret ”;这是可以接受的。用户将根据互操作性与安全问题来决定何时更改“ secret ”。
[1]:我非常清楚,即使没有任何程序标识符,任何程序都可以进行逆向工程,因为我已经做到了。不过,我不想让机械获取标识符比手动对程序进行逆向工程更容易。
最佳答案
对于给定的“工作”值,您描述的方案将起作用。
首先,MD5 中的已知弱点不会影响您的应用程序。然而,也就是说,使用已知的弱加密原语通常是一个坏主意,因此使用更强大的哈希可能更有意义。输出长度无关紧要:您可以将其截断为您想要的任何长度。
然而,我相信您知道,这充其量只是混淆:即使没有有用的标识符,坚定的攻击者也能够对代码进行逆向工程,这不仅适用于您的工具生成的代码,还适用于工具本身。如果您依靠嵌入在工具代码中的 secret 来防止字典攻击,则必须接受攻击者将能够提取该 secret - 此时他们可以构建字典来生成原始标识符以及您的混淆变得完全无用。您说由于互操作性而担心标识符的稳定性,但这里通常的解决方案很简单:不要混淆属于代码公共(public)接口(interface)一部分的标识符,而只混淆内部细节。
关于security - MD5 在程序代码中混淆标识符的安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20015754/