CodesInChaos / Chaos.NaCl

Chaos.NaCl cryptography library
Other
131 stars 54 forks source link

Ed25519.KeyExchange does not generate equalling shared keys #4

Closed AdhemarVandamme closed 10 years ago

AdhemarVandamme commented 10 years ago

Consider this test:

using System.Security.Cryptography;

RNGCryptoServiceProvider rngCryptoServiceProvider
     = new RNGCryptoServiceProvider();
byte[] publicKey0, expandedPrivateKey0;
byte[] seed1 = new byte[32];
rngCryptoServiceProvider.GetBytes(seed1);
Ed25519.KeyPairFromSeed(out publicKey0, out expandedPrivateKey0, seed1);
byte[] publicKey1, expandedPrivateKey1;
byte[] seed2 = new byte[32];
rngCryptoServiceProvider.GetBytes(seed2);
Ed25519.KeyPairFromSeed(out publicKey1, out expandedPrivateKey1, seed2);
byte[] sharedKey0 = Ed25519.KeyExchange(publicKey1, expandedPrivateKey0);
byte[] sharedKey1 = Ed25519.KeyExchange(publicKey0, expandedPrivateKey1);
var theSame = CryptoBytes.ConstantTimeEquals(sharedKey0, sharedKey1);
Console.Out.WriteLine(theSame);

One would expect the output to be true: the generated shared keys should be the same. That's why they are called shared keys. Unfortunately, the output is false.

The reason is that the wrong private key is used. The expanded private key in Ed25519.cs, given as argument, is not the same private key that is used in the MontgomeryCurve25519 implementation. There the unmultiplied a (private scalar) is used. The unmultiplied a (private scalar) = left 32 bytes of SHA512 of seed, with some bits set and unset, where seed = left 32 bytes of the expanded private key.

(This diagram can be helpful.)

CodesInChaos commented 10 years ago

Thanks for the bug report. Should be fixed with commit: https://github.com/CodesInChaos/Chaos.NaCl/commit/5d67d2a0b7e2da2b9495ee992feb20dff33fa9f1

But as a warning: This part of the API will almost certainly change a lot. I'll probably split it in two: