0
$\begingroup$

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

Is there any c# implementation of this or equivalent?

Thanks.

$\endgroup$
1
$\begingroup$

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.
| improve this answer | |
$\endgroup$

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