I'm trying to understand the implementation of the following function: Please note questions in comments.
int curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
limb bp[5], x[5], z[5], zmone[5]; // why 5 elements in each?
uint8_t e[32];
int i;
for (i = 0;i < 32;++i) e[i] = secret[i];
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
fexpand(bp, basepoint);
cmult(x, z, e, bp);
crecip(zmone, z);
fmul(z, x, zmone);
fcontract(mypublic, z);
return 0;
}
- Why do all the functions work on a polynomial form of a number? and thus require fexpand function? as I understand fcontract does the opposite.
- e[0] &= 248; e[31] &= 127; e[31] |= 64; - I've found this suggested in the whitepaper, is there any particular reason behind doing this?
- Why is cmult performed twice? what does crecip function achieve?
From what I read on curves in the Weierstrass form, in order to get a public key H, one needs to compute H = dG (where G is the base point of the subgroup). Then the situation is entirely different in case of Ed25519 (I know Montgomery Curve25519 is birationally equivalent to a twisted Edwards curve Ed25519), where generation of the public key involves hashing and results in a non-linear key-space.
- In contrast with Ed25519, Can private/public keys in Curve25519 be said to form a linear space? I was wondering whether it would be possible to generate public keys independently to the corresponding private keys using a common index in case of Curve25519.
Update: besides the excellent answer provided by Lery; those of you not familiar with projective coordinates might find this useful.