I've found recently in the I2P sources (Java) the following fragment:
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;
}
As I understand, the first 256 bits of buf[]
are copied directly to the session key, and no SHA256 digest is ever run on it. I'm not cryptography specialist (neither java), could anyone explain me, isn't it security hole here? I mean, in the standard Diffie-Hellman wiki page the SHA hash is also run over the key.
If it really is, could you also give an example how it can be exploit?
There is no "leak" in the sense that an attacker can tap into the key exchange, but there is certainly a loss of entropy. Because the key seems to be 32 bytes in size this may not be catastrophic, but I personally would have a lot of trouble to accept this implementation.
The Diffie-Hellman protocol in clearly specifies in RFC 2631 that
Leading zeros MUST be preserved, so that ZZ occupies as many octets as p.
This preservation of leading zero's is not present in the implementation of the protocol.
Finally, because the designer decided not to pad, there is be an overlap of values: 70
, 7000
and 700000
would for instance be thought of as the same value, while they clearly aren't.
Furthermore, the BigInteger.toByteArray()
will return the two-complement encoding of the signed value. This means that it is often left padded with 00
valued bytes, even if the value already has the same size as p in octets. So there is a really big chance that the first byte of the key is 00
. And even if it isn't, the first byte is bounded by the modulus, so the first byte will never have a value higher than the first byte of an encoded p.
UPDATE: I've asked on crypto.stackexchange.com to see if the rest of the key bytes can be thought of as being generated by a Random Oracle (a deterministic function that seems to generate random bytes to the outside world) and fortunately they seem to do. This means that there is enough entropy left in the AES key to be safe against (brute force) attacks on the AES block cipher.
As explained, because of the large key size, it is likely that even the summation of all these defects cannot be exploited easily. But it is absolutely certain that the keys won't carry 256 bits of entropy as expected. This would be enough for a crypto-analyst to declare this implementation broken. It would be much worse of course with a smaller key size.
Note: all values in hexadecimals.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With