1

I'm trying to get the public key with different JavaScript libraries: with elliptic and with libsodium-wrappers-sumo This is my code:

const BN = require('bn.js');
const EdDSA = require('elliptic').eddsa;
const ed25519 = new EdDSA('ed25519');
const _sodium = require('libsodium-wrappers-sumo');

(async() => {
  await _sodium.ready;
  const sodium = _sodium;
  
  const privKeyHex = "6220f3affaa568f554ca850f9374e7112c09af219976bb779f4fd8f297294900"
  const tmp1 = sodium.crypto_scalarmult_ed25519_base_noclamp(Buffer.from(privKeyHex, "hex"), "hex")
  const tmp2 = ed25519.curve.g.mul(new BN(privKeyHex, "hex", "le")).getY().toArrayLike(Buffer, "le", 32).toString("hex")

  console.log(tmp1)
  console.log(tmp2)
})()

I expect to get the same values ​​but I get different:

e96c5156a431383f12014f320e4bdeae441ad2d36e0364278a36d9b4e5f99ffa
e96c5156a431383f12014f320e4bdeae441ad2d36e0364278a36d9b4e5f99f7a

The last byte is different. Inexplicably.

Checking on this site gives the result:

e96c5156a431383f12014f320e4bdeae441ad2d36e0364278a36d9b4e5f99ffa

What could be the reason for the discrepancy between the results and what is the correct result?

1 Answer 1

2

See RFC8032 for an explanation of how the sign of a point is encoded into the most significant bit of the last byte. By doing getY() you're attempting to do your own encoding, and not setting this bit.

Instead, let the library do the encoding for you:

elliptic.utils.toHex(ed25519.encodePoint(ed25519.curve.g.mul(new BN(privKeyHex, "hex", "le"))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.