WRT the selected answer here: Can curve25519 keys be used with ed25519 keys?

Is there any c# implementation of this or equivalent?



1 Answer 1


In a Ref10 based implementation, the conversion should look something like this:

public static void EdwardsToMontgomeryX(out FieldElement montgomeryX, ref FieldElement edwardsY, ref FieldElement edwardsZ)
    // montgomeryX = (edwardsZ + edwardsY) / (edwardsZ - edwardsY)
    FieldElement tempX, tempZ;
    FieldOperations.fe_add(out tempX, ref edwardsZ, ref edwardsY);
    FieldOperations.fe_sub(out tempZ, ref edwardsZ, ref edwardsY);
    FieldOperations.fe_invert(out tempZ, ref tempZ);
    FieldOperations.fe_mul(out montgomeryX, ref tempX, ref tempZ);

public static void MontgomeryXToEdwards(out FieldElement edwardsY, ref FieldElement montgomeryX, ref FieldElement montgomeryZ)
    // edwardsY = (montgomeryX - montgomeryZ) / (montgomeryX + montgomeryZ)
    FieldElement tempY, tempZ;
    FieldOperations.fe_sub(out tempY, ref montgomeryX, ref montgomeryZ);
    FieldOperations.fe_add(out tempZ, ref montgomeryX, ref montgomeryZ);
    FieldOperations.fe_invert(out tempZ, ref tempZ);
    FieldOperations.fe_mul(out edwardsY, ref tempY, ref tempZ);

public static void EdwardsToMontgomery(ArraySegment<byte> montgomery, ArraySegment<byte> edwards)
    FieldElement edwardsY, edwardsZ, montgomeryX;
    FieldOperations.fe_frombytes(out edwardsY, edwards.Array, edwards.Offset);
    FieldOperations.fe_1(out edwardsZ);
    EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
    FieldOperations.fe_tobytes(montgomery.Array, montgomery.Offset, ref montgomeryX);
    montgomery.Array[montgomery.Offset + 31] |= (byte)(edwards.Array[edwards.Offset + 31] & 0x80);// copy sign

public static void MontgomeryToEdwards(ArraySegment<byte> edwards, ArraySegment<byte> montgomery)
    FieldElement montgomeryX, montgomeryZ, edwardsY;
    FieldOperations.fe_frombytes(out montgomeryX, montgomery.Array, montgomery.Offset);
    FieldOperations.fe_1(out montgomeryZ);
    MontgomeryXToEdwards(out edwardsY, ref montgomeryX, ref montgomeryZ);
    FieldOperations.fe_tobytes(edwards.Array, edwards.Offset, ref edwardsY);
    edwards.Array[edwards.Offset + 31] |= (byte)(montgomery.Array[montgomery.Offset + 31] & 0x80);// copy sign

You should be able to use these together with my implementation at github.com/CodesInChaos/Chaos.NaCl. If all you need is crypto_box_beforenm except with a Ed25519 format key, you can simply use the existing Ed25519.KeyExchange method.

A few warnings:

  • I'm planning some breaking API changes
  • I'm not happy yet with the test coverage yet, so be careful
  • The Montogomery form Curve25519 functions don't ignore the last bit of the public key.

    This means that you must manually mask out that bit via publicKey[31] &= 0x7F before passing it to MontgomeryCurve25519.KeyExchange. I will change this property with the next update of the library.

  • The key exchange functions hash their output, matching crypto_box_beforenm.

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