curve255js icon indicating copy to clipboard operation
curve255js copied to clipboard

Question: cannot match public key with that from Whisper and Donna

Open franslundberg opened this issue 9 years ago • 3 comments

As an example, I use the private key

a0e7cb1a31ef588cf7c0a7d537a1a02d72d47667a7964f1d8e35f904e95f3d65 (hex)

With the Whisper implementation (curve25519-java at https://github.com/WhisperSystems/curve25519-java) and the Donna implementation (https://github.com/agl/curve25519-donna) of Curve 25519 I get the same result when computing the corresponding public key. The result (public key) is:

8b61c39e39eed90fc4c1cec39a4bea0db61dfbaa3753c1cd38df8a570a67a241 (hex)

However, I am unable to reproduce this result with curve255.js. I am a beginner at JavaScript. Here is the JavaScript code I thought would reproduce the results of Whisper and Donna implementations:

var privHex = "a0e7cb1a31ef588cf7c0a7d537a1a02d72d47667a7964f1d8e35f904e95f3d65";
var priv = c255lhexdecode(privHex);
var pub = curve25519(priv);
var pubHex = c255lhexencode(pub);
console.log("pubHex: " + pubHex);

The output I get is

pubHex: 04a4b47444f345546698dcfc885a3f087ac979f53a1eb7fc55e9164105f37c13

Not the expected 8b61.. How come? I am probably doing something wrong? I tried several variants of the above with no success.

franslundberg avatar Sep 21 '15 11:09 franslundberg

It might be worth looking at this repo instead, if you're interested in Curve25519 implementations: https://github.com/meganz/jodid25519

Michele, Ron and I have put things together there to make a bit more comprehensive implementation available with a bit nicer API and documentation. So the code in jodid25519 is based on this curve255js code.

Having said that, I've recently switched towards using TweetNaCl.js: https://github.com/dchest/tweetnacl-js

It's had more eyes on it, the implementation is faster, and it's also more constant time in execution (which is important for cryptography implementations).

Hope that helps.

pohutukawa avatar Sep 21 '15 23:09 pohutukawa

Thank you very much! I will try jodid25519.

/ Frans On Sep 22, 2015 1:24 AM, "Guy Kloss" [email protected] wrote:

It might be worth looking at this repo instead, if you're interested in Curve25519 implementations: https://github.com/meganz/jodid25519

Michele, Ron and I have put things together there to make a bit more comprehensive implementation available with a bit nicer API and documentation. So the code in jodid25519 is based on this curve255js code.

Having said that, I've recently switched towards using TweetNaCl.js: https://github.com/dchest/tweetnacl-js

It's had more eyes on it, the implementation is faster, and it's also more constant time in execution (which is important for cryptography implementations).

Hope that helps.

— Reply to this email directly or view it on GitHub https://github.com/rev22/curve255js/issues/4#issuecomment-142136477.

franslundberg avatar Sep 22 '15 06:09 franslundberg

I know this is years old but in case anyone else is wondering how to use this library to talk to other libraries the trick is in the byte order.

Private and public keys are represented by arrays of 16-bit values, starting from the least significant ones:

Code is from curve255js/test/test-curve25519-quick.js and comments from curve255js/test/test-curve25519.coffee

hex2ibh = function(x) {
  x = new Array(64 + 1 - x.length).join("0") + x; // # Pad with '0' at the front
  return x.split(/(..)/).reverse().join("");      // Invert bytes
};

I was playing with an hta in a VM and I had to replace .split(/(..)/) with .match(/..?/g) but the concept is the same. Reverse the pairs of hex bytes before making the array.

Use hex2ibh to reverse the byte order, then c255lhexdecode to convert the hex string to an array of 16-bit integers for curve25519 to consume. Use c255lhexencode to convert back to hex and hex2ibh once more to reverse the byte order for displaying.

> console.log(hex2ibh(c255lhexencode(curve25519(c255lhexdecode(hex2ibh("a0e7cb1a31ef588cf7c0a7d537a1a02d72d47667a7964f1d8e35f904e95f3d65"))))));
8b61c39e39eed90fc4c1cec39a4bea0db61dfbaa3753c1cd38df8a570a67a241

That worked for the example provided. It also works for the test vectors in rfc7748.

Alice's private key, a: 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a Alice's public key, X25519(a, 9): 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a Bob's private key, b: 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb Bob's public key, X25519(b, 9): de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f Their shared secret, K: 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742

> console.log(hex2ibh(c255lhexencode(curve25519(c255lhexdecode(hex2ibh("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a")),c255lhexdecode(hex2ibh("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"))))));
4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742

JackZielke avatar Jul 20 '19 11:07 JackZielke