我最近在I2P源代码(Java)中发现了以下片段:
private final SessionKey calculateSessionKey(BigInteger myPrivateValue, BigInteger publicPeerValue) {
SessionKey key = new SessionKey();
BigInteger exchangedKey = publicPeerValue.modPow(myPrivateValue, CryptoConstants.elgp);
byte buf[] = exchangedKey.toByteArray();
byte val[] = new byte[32];
if (buf.length < val.length) {
System.arraycopy(buf, 0, val, 0, buf.length);
... //irrelevant details
} else { // (buf.length >= val.length)
System.arraycopy(buf, 0, val, 0, val.length);
... //irrelevant details
}
key.setData(val);
return key;
}据我所知,buf[]的前256个位被直接复制到会话密钥,并且从未在其上运行任何SHA256摘要。我不是密码学专家(也不是java),有人能解释一下吗,这里不是安全漏洞吗?我的意思是,在标准Diffie-Hellman wiki页面中,SHA散列也运行在密钥上。如果是的话,你还能举个例子说明它如何被利用吗?
发布于 2013-07-24 23:31:01
在攻击者可以利用密钥交换的意义上,不存在“泄漏”,但当然存在熵损失。因为关键似乎是32字节大小,这可能不会是灾难性的,但我个人会有很大的困难,以接受这个实现。
Diffie-Hellman协议在RFC 2631中明确规定:
必须保留前导零,这样ZZ所占的八位数与p一样多。
在协议的实现中,不存在对前导零的保留。
最后,由于设计人员决定不使用pad,因此存在着值的重叠:例如,70、7000和700000将被认为是相同的值,而它们显然不是。
此外,BigInteger.toByteArray()将返回有符号值的两个补编码。这意味着它通常用00值字节填充,即使该值已经与p的八进制大小相同。所以很有可能密钥的第一个字节是00。即使不是,第一个字节也是以模数为界的,所以第一个字节的值永远不会高于编码p的第一个字节。
UPDATE:我要看看是否可以将其余的关键字节看作是由随机Oracle (一种向外界生成随机字节的确定性函数)和幸运的他们似乎生成的。这意味着在AES密钥中保留了足够的熵,以避免对AES分组密码的(蛮力)攻击。
正如所解释的那样,由于密钥大小很大,很可能所有这些缺陷的总和都不容易被利用。但绝对可以肯定的是,密钥不会像预期的那样携带256位熵。这足以让密码分析人员宣布这个实现被破坏了。当然,如果密钥尺寸较小,情况会更糟。
注:所有十六进制值。
发布于 2014-02-17 00:23:31
正如奥斯特德所解释的,这不是一个安全漏洞。但是是,一个从I2P开始就一直存在的bug,我们将修复它。不幸的是,修复这个问题所需的更改并不是向后兼容的--与我们现有的传输兼容,因此这将被合并到我们传输的下一个版本中。
有兴趣的人可以跟踪这个bug 这里的进展。
https://stackoverflow.com/questions/17841662
复制相似问题