paulmillr / noble-ed25519

Fastest 4KB JS implementation of ed25519 signatures
https://paulmillr.com/noble
MIT License
414 stars 50 forks source link

replacement for getSharedSecret #81

Closed mo22 closed 1 year ago

mo22 commented 1 year ago

I have been using the function getSharedSecret from @noble/ed25519 which now seems to be deprecated.

Looking for a replacement in @noble/curves/ed25519 I found it is only supported in the x25519 curve.

This library used to convert the ed25519 curve internally to an x25519 curve, which I cannot reproduce using @noble/curves.

Maybe you can add an example in the Upgrading section?

paulmillr commented 1 year ago

Reason for removing was that it's non-standard and it's unclear whether the algorithm was optimal. The function was as follows:

import { ed25519, x25519 } from '@noble/curves/ed25519'
const { Fp } = ed25519.CURVE; // Use field over 2n**255n-19n
/**
  * Converts to Montgomery; aka x coordinate of curve25519.
  * We don't have fromX25519, because we don't know sign.
  *
  * ```
  * u, v: curve25519 coordinates
  * x, y: ed25519 coordinates
  * (u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
  * (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
  * ```
  * https://blog.filippo.io/using-ed25519-keys-for-encryption
  * @returns u coordinate of curve25519 point
  * @example 
  */
function toX25519(y: bigint) {
  const _1n = BigInt(1);
  const u = Fp.create((_1n + y) * Fp.inv(_1n - y)); // (1+y) / (1-y) == (1+y) * inv(1-y)
  return Fp.toBytes(u);
}
export function getSharedSecret(privateKey, publicKey) {
  const { head } = ed25519.utils.getExtendedPublicKey(privateKey);
  const u = toX25519(ed25519.ExtendedPoint.fromHex(publicKey).y);
  return x25519.scalarMult(head, u);
}

You can keep using it

mo22 commented 1 year ago

Yes, thank you very much, I was trying this but found that the definitions I found in curve does not contain the same math functions (mod, invert, numberTo32BytesLE, Point etc)

As I might not be the only one using that method, do you think it might find a place in ed25519.utils? (at least the conversion from ed25519 to x25519)

paulmillr commented 1 year ago

Just tested this one:

import { ed25519, x25519 } from '@noble/curves/ed25519'
const { Fp } = ed25519.CURVE; // Use field over 2n**255n-19n
function toX25519(y) {
  const _1n = BigInt(1);
  const u = Fp.create((_1n + y) * Fp.inv(_1n - y)); // (1+y) / (1-y) == (1+y) * inv(1-y)
  return Fp.toBytes(u);
}
export function getSharedSecret(privateKey, publicKey) {
  const { head } = ed25519.utils.getExtendedPublicKey(privateKey);
  const u = toX25519(ed25519.ExtendedPoint.fromHex(publicKey).y);
  return x25519.scalarMult(head, u);
}

I don't want to add it to utils because of the same reason: it's non-standard, so I don't want to popularize it.

mo22 commented 1 year ago

Thank you very much, that works (had to change ExtendedPoint.y to ExtendedPoint.ey), highly appreciated!

paulmillr commented 1 year ago

@mo22 no, .ey is wrong - you need to use y, which also exists at ExtendedPoint.

paulmillr commented 1 year ago

added to curves, edwardsToMontgomery