简单(编码)安全散列函数
Posted
技术标签:
【中文标题】简单(编码)安全散列函数【英文标题】:Simple (to code) secure hash function 【发布时间】:2010-11-16 05:54:57 【问题描述】:我需要一个具有以下属性的安全(加密)哈希函数:
-
可以用尽可能少的行进行编码(在 R5RS 方案中)。希望不到 50 岁。
内存和 CPU 性能在密码长度数据的范围内。 (例如,它不必非常高效或为数百万字节的数据创建哈希)
我能找到的最安全的哈希函数在设计时考虑了速度/内存效率,因此编码起来很复杂。
当前候选者是 Mash-1(或 Mash-2): Handbook of applied cryptography. Google Books
谢谢。
编辑: 到目前为止,谢谢大家的回答。如果以下内容粗鲁,请原谅我,我只想说清楚。请相信我,我已经完成了作业并考虑了“标准”选项。我知道最简单的方法是使用其中之一,但这不是我想要的。
我想回答的一个问题是: 什么加密安全的哈希算法可以用最少的“可读”代码实现?
我已经发布了我能找到的最佳候选人。任何关于更简单的建议或关于 Mash-1/2 的评论都会非常有帮助。
【问题讨论】:
你只是把它当作一个学习练习吗,因为坦率地说,除了众所周知的算法之外,我不会相信任何东西。 您遇到的问题是,当 X 是一个鲜为人知的加密原语时,没有人愿意把手放在心上说“X 是安全的”。这是因为“安全”通常意味着“尽管受到极大关注,但尚未被破坏”。 您确实需要澄清您的安全要求:如果您不选择最常见的哈希算法之一,您就是在进行安全权衡,因为它更有可能具有未知的弱点. “安全”不是二进制值。您不愿意使用 SHA-512,因为它实现起来太复杂了。因此,请帮助我们了解您愿意为更容易实施而牺牲多少安全性。您是否只是在寻找可以在 50 行 Scheme 中实现的最安全哈希?即使该算法很可能在 10 年内被破坏? 我正在整理一个用作教学工具的 Web 堆栈。我不想省略任何必要的东西(密码散列),但我想确保一切都尽可能简单,以便任何研究它的人都希望完全理解每个组件。一些加密算法(RSA、Feistel 密码)对它们有某种简单的优雅,我希望在安全哈希中也有类似的东西。我必须使用可用的东西,这个线程的目的是发现我的选择是什么。 scheme真的没有sha1的实现吗? 【参考方案1】:如果您想要一个安全的散列函数来实际保护某些东西(例如,作为加密算法的一部分),最好使用 SHA-512(或者可能是 RIPEMD-160 或一些其他)。
如果您希望它用于散列密码,我会说像 MASH 这样的散列函数将符合抵抗蛮力(与盐一起使用时)和彩虹表的要求。除非我有严格的要求禁止或阻止我使用库实现,否则我仍然不会使用它 - 但听起来你可能只有这些。
如果您希望它用于不太安全的事情,比如文件完整性检查,除非您明确担心恶意用户会产生冲突,否则几乎任何事情都可以做到。在这种情况下,根据您要保护的内容的价值,我的范围从简单的 MASH 到更具抵抗力的 SHA-512 或 RIPEMD-320。
【讨论】:
【参考方案2】:如果您更喜欢简单性和教学价值而不是效率,那么VSH 哈希函数可能是一种选择。它带有强烈的论据,即 VSH 是一种抗碰撞哈希函数,尽管该函数缺少其他哈希函数所具有的一些其他属性(例如伪随机性)。
【讨论】:
这似乎是我一直在寻找的。我已经略读了这篇论文并接受了你的回答。谢谢。【参考方案3】:对于您的要求,我会查看SHA-3 finalists。
如果您为加密实现了 AES 原语,您可以重复使用它来相对简单地实现几个功能。
否则,我想我会选择 Daniel Bernstein 的 Cubehash。那个看起来有一些你正在寻找的“简单优雅”。
【讨论】:
谢谢。这看起来是一个有趣的可能性。【参考方案4】:根据 Bruce Schneier 的“应用密码学”第 18.12 节: “可以在区块链模式中使用公钥加密算法作为单向哈希函数。”
RSA(私钥被丢弃)作为示例列出。安全性与 RSA 一样强大。
RSA 加密步骤实现起来相当简单。特别是在具有任意大小整数的语言中。
两个注意事项是: 1. 比大多数(所有)其他安全哈希函数慢得多。这对我来说很好。 2. 如果你将你的公钥硬编码到代码中,世界将不得不相信你丢弃了你的私钥数据。或者创建他们自己的公钥私钥。
一有工作示例,我就会发布代码。
编辑:在这里。 30行。简单的。安全的。 编辑 2:我实际包含的是一个变体,可能不起作用。请参阅此帖子下方的 cmets 并注意更新。
; compute a^d mod n
(define powmod
(lambda (a d n)
(cond
((= 0 d) 1)
((= 1 d) (modulo a n))
((= 0 (modulo d 2)) (modulo (expt (powmod a (/ d 2) n) 2) n))
(else
(modulo (* (powmod a 1 n) (powmod a (- d 1) n)) n)))))
(define foldr
(lambda (func end lst)
(if (null? lst)
end
(func (car lst) (foldr func end (cdr lst))))))
; something to turn a string into a number
(define any-string->number
(lambda (s)
(foldr
(lambda (a b) (+ a (* 256 b)))
0
(map char->integer (string->list s)))))
; some big primes
(define p 325981479175658910158495167696993467513669112200235950741366213684181287869366665231)
(define q 930416184994449450269535709442344346507738432154879695027334802205487824589832585453)
; hash turns a string into a number
; see discrete logarithms. the inverse of this is *hard* to compute
; http://en.wikipedia.org/wiki/Discrete_logarithm
(define hash
(lambda (s)
(powmod (any-string->number s) p q)))
【讨论】:
我实际上考虑过推荐那个,但决定不这样做。另一个缺点是输出相当大:如果使用 1024 位模数,则为 128 字节。另外:请记住,您必须将输入分成块并将结果链接起来(或者如果输入大于模数则失败)。 另外:您实现的既不是 RSA 也不是 Diffie-Hellman。实际上,这是相当容易破解的。找到给定的 (a^p mod q)、p 和 q 很容易。离散对数问题是求给定的 (p^a mod q)、p 和 q。 谢谢拉斯穆斯。你在这个线程中很有帮助。在解释 RSA 使用的“应用密码学”的同一部分中,提到了这种方法。我现在没有这本书,但我相当确定这一点。我回家后会仔细检查。我明白这不完全是离散对数问题。但是在 RSA 中,我们仍然有 message^e mod n,其中对于某些素数 p q,n 是 (p-1)(q-1),并且 e 与 n 互素。这很容易被破解,这看起来似乎 RSA 也是如此。你能指出打破这一点的算法的方向吗? 在 RSA 中,模不是素数,这意味着我们不能应用费马小定理:a^(q-1)=a (mod q)。要从 a^p mod q 中找到 a,首先使用中国剩余定理找到 x 和 y,使得 xp+y(q-1)=1。那么 (a^p)^x = a^px = a^(1-y(q-1)) = a*(a^(q-1)^-y) = a (mod q)。 不客气。顺便提一句。费马小定理说 a^(q-1)=1 (mod q),不是我上面写的。【参考方案5】:查看TrueCrypt source。他们实现了几个强大的哈希函数。只是标准警告,修改现有实现或更糟糕的是,使用您自己的实现是不明智的。它几乎肯定会注入弱点。我意识到你不是在这里这样做,而只是一个免责声明。 :)
【讨论】:
以上是关于简单(编码)安全散列函数的主要内容,如果未能解决你的问题,请参考以下文章