static void fsquare(limb *output, limb *input) { Long19 t = new Long19(); fsquare_inner(t.Items, input); freduce_degree(t.Items); freduce_coefficients(t.Items); memcpy(output, t.Items, sizeof(limb) * 10); }
/* A helpful wrapper around fproduct: output = in * in2. * * output must be distinct to both inputs. The output is reduced degree and * reduced coefficient. */ static void fmul(limb *output, limb *input, limb *in2) { Long19 t = new Long19(); fproduct(t.Items, input, in2); freduce_degree(t.Items); freduce_coefficients(t.Items); memcpy(output, t.Items, sizeof(limb) * 10); }
/* Input: Q, Q', Q-Q' * Output: 2Q, Q+Q' * * x2 z3: long form * x3 z3: long form * x z: short form, destroyed * xprime zprime: short form, destroyed * qmqp: short form, preserved */ static void fmonty(limb *x2, limb *z2, /* output 2Q */ limb *x3, limb *z3, /* output Q + Q' */ limb *x, limb *z, /* input Q */ limb *xprime, limb *zprime, /* input Q' */ limb *qmqp /* input Q - Q' */) { Long19 origx = new Long19(); Long19 origxprime = new Long19(); Long19 zzz = new Long19(); Long19 xx = new Long19(); Long19 zz = new Long19(); Long19 xxprime = new Long19(); Long19 zzprime = new Long19(); Long19 zzzprime = new Long19(); Long19 xxxprime = new Long19(); memcpy(origx.Items, x, 10 * sizeof(limb)); fsum(x, z); fdifference(z, origx.Items); // does x - z memcpy(origxprime.Items, xprime, sizeof(limb) * 10); fsum(xprime, zprime); fdifference(zprime, origxprime.Items); fproduct(xxprime.Items, xprime, z); fproduct(zzprime.Items, x, zprime); freduce_degree(xxprime.Items); freduce_coefficients(xxprime.Items); freduce_degree(zzprime.Items); freduce_coefficients(zzprime.Items); memcpy(origxprime.Items, xxprime.Items, sizeof(limb) * 10); fsum(xxprime.Items, zzprime.Items); fdifference(zzprime.Items, origxprime.Items); fsquare(xxxprime.Items, xxprime.Items); fsquare(zzzprime.Items, zzprime.Items); fproduct(zzprime.Items, zzzprime.Items, qmqp); freduce_degree(zzprime.Items); freduce_coefficients(zzprime.Items); memcpy(x3, xxxprime.Items, sizeof(limb) * 10); memcpy(z3, zzprime.Items, sizeof(limb) * 10); fsquare(xx.Items, x); fsquare(zz.Items, z); fproduct(x2, xx.Items, zz.Items); freduce_degree(x2); freduce_coefficients(x2); fdifference(zz.Items, xx.Items); // does zz = xx - zz fscalar_product(zzz.Items, zz.Items, 121665); /* No need to call freduce_degree here: * fscalar_product doesn't increase the degree of its input. */ freduce_coefficients(zzz.Items); fsum(zzz.Items, xx.Items); fproduct(z2, zz.Items, zzz.Items); freduce_degree(z2); freduce_coefficients(z2); }
public static unsafe void curve25519_donna(byte *mypublic, byte *secret, byte *basepoint) { Long19 bp = new Long19(); Long19 x = new Long19(); Long19 z = new Long19(); Long19 zmone = new Long19(); Byte32 e = new Byte32(); int i; for (i = 0; i < 32; ++i) { e.Items[i] = secret[i]; } e.Items[0] &= 248; e.Items[31] &= 127; e.Items[31] |= 64; fexpand(bp.Items, basepoint); cmult(x.Items, z.Items, e.Items, bp.Items); crecip(zmone.Items, z.Items); fmul(z.Items, x.Items, zmone.Items); freduce_coefficients(z.Items); fcontract(mypublic, z.Items); }
private static void fsquare(limb* output, limb* input) { var t = new Long19(); fsquare_inner(t.Items, input); freduce_degree(t.Items); freduce_coefficients(t.Items); memcpy10(output, t.Items); }
/* A helpful wrapper around fproduct: output = in * in2. * * output must be distinct to both inputs. The output is reduced degree and * reduced coefficient. */ private static void fmul(limb* output, limb* input, limb* in2) { Long19 t = new Long19(); fproduct(t.Items, input, in2); freduce_degree(t.Items); freduce_coefficients(t.Items); memcpy10(output, t.Items); }
/* Input: Q, Q', Q-Q' * Output: 2Q, Q+Q' * * x2 z3: long form * x3 z3: long form * x z: short form, destroyed * xprime zprime: short form, destroyed * qmqp: short form, preserved */ static void fmonty(limb* x2, limb* z2, /* output 2Q */ limb* x3, limb* z3, /* output Q + Q' */ limb* x, limb* z, /* input Q */ limb* xprime, limb* zprime, /* input Q' */ limb* qmqp /* input Q - Q' */) { var origx = new Long19(); var origxprime = new Long19(); var zzz = new Long19(); var xx = new Long19(); var zz = new Long19(); var xxprime = new Long19(); var zzprime = new Long19(); var zzzprime = new Long19(); var xxxprime = new Long19(); memcpy10(origx.Items, x); fsum(x, z); fdifference(z, origx.Items); // does x - z memcpy10(origxprime.Items, xprime); fsum(xprime, zprime); fdifference(zprime, origxprime.Items); fproduct(xxprime.Items, xprime, z); fproduct(zzprime.Items, x, zprime); freduce_degree(xxprime.Items); freduce_coefficients(xxprime.Items); freduce_degree(zzprime.Items); freduce_coefficients(zzprime.Items); memcpy10(origxprime.Items, xxprime.Items); fsum(xxprime.Items, zzprime.Items); fdifference(zzprime.Items, origxprime.Items); fsquare(xxxprime.Items, xxprime.Items); fsquare(zzzprime.Items, zzprime.Items); fproduct(zzprime.Items, zzzprime.Items, qmqp); freduce_degree(zzprime.Items); freduce_coefficients(zzprime.Items); memcpy10(x3, xxxprime.Items); memcpy10(z3, zzprime.Items); fsquare(xx.Items, x); fsquare(zz.Items, z); fproduct(x2, xx.Items, zz.Items); freduce_degree(x2); freduce_coefficients(x2); fdifference(zz.Items, xx.Items); // does zz = xx - zz fscalar_product(zzz.Items, zz.Items, 121665); /* No need to call freduce_degree here: fscalar_product doesn't increase the degree of its input. */ freduce_coefficients(zzz.Items); fsum(zzz.Items, xx.Items); fproduct(z2, zz.Items, zzz.Items); freduce_degree(z2); freduce_coefficients(z2); }
// ----------------------------------------------------------------------------- // Shamelessly copied from djb's code // ----------------------------------------------------------------------------- private static void crecip(limb* output, limb* z) { Long19 z2 = new Long19(); Long19 z9 = new Long19(); Long19 z11 = new Long19(); Long19 z2_5_0 = new Long19(); Long19 z2_10_0 = new Long19(); Long19 z2_20_0 = new Long19(); Long19 z2_50_0 = new Long19(); Long19 z2_100_0 = new Long19(); Long19 t0 = new Long19(); Long19 t1 = new Long19(); int i; /* 2 */ fsquare(z2.Items, z); /* 4 */ fsquare(t1.Items, z2.Items); /* 8 */ fsquare(t0.Items, t1.Items); /* 9 */ fmul(z9.Items, t0.Items, z); /* 11 */ fmul(z11.Items, z9.Items, z2.Items); /* 22 */ fsquare(t0.Items, z11.Items); /* 2^5 - 2^0 = 31 */ fmul(z2_5_0.Items, t0.Items, z9.Items); /* 2^6 - 2^1 */ fsquare(t0.Items, z2_5_0.Items); /* 2^7 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^8 - 2^3 */ fsquare(t0.Items, t1.Items); /* 2^9 - 2^4 */ fsquare(t1.Items, t0.Items); /* 2^10 - 2^5 */ fsquare(t0.Items, t1.Items); /* 2^10 - 2^0 */ fmul(z2_10_0.Items, t0.Items, z2_5_0.Items); /* 2^11 - 2^1 */ fsquare(t0.Items, z2_10_0.Items); /* 2^12 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^20 - 2^0 */ fmul(z2_20_0.Items, t1.Items, z2_10_0.Items); /* 2^21 - 2^1 */ fsquare(t0.Items, z2_20_0.Items); /* 2^22 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^40 - 2^0 */ fmul(t0.Items, t1.Items, z2_20_0.Items); /* 2^41 - 2^1 */ fsquare(t1.Items, t0.Items); /* 2^42 - 2^2 */ fsquare(t0.Items, t1.Items); /* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2) { fsquare(t1.Items, t0.Items); fsquare(t0.Items, t1.Items); } /* 2^50 - 2^0 */ fmul(z2_50_0.Items, t0.Items, z2_10_0.Items); /* 2^51 - 2^1 */ fsquare(t0.Items, z2_50_0.Items); /* 2^52 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^100 - 2^0 */ fmul(z2_100_0.Items, t1.Items, z2_50_0.Items); /* 2^101 - 2^1 */ fsquare(t1.Items, z2_100_0.Items); /* 2^102 - 2^2 */ fsquare(t0.Items, t1.Items); /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) { fsquare(t1.Items, t0.Items); fsquare(t0.Items, t1.Items); } /* 2^200 - 2^0 */ fmul(t1.Items, t0.Items, z2_100_0.Items); /* 2^201 - 2^1 */ fsquare(t0.Items, t1.Items); /* 2^202 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^250 - 2^0 */ fmul(t0.Items, t1.Items, z2_50_0.Items); /* 2^251 - 2^1 */ fsquare(t1.Items, t0.Items); /* 2^252 - 2^2 */ fsquare(t0.Items, t1.Items); /* 2^253 - 2^3 */ fsquare(t1.Items, t0.Items); /* 2^254 - 2^4 */ fsquare(t0.Items, t1.Items); /* 2^255 - 2^5 */ fsquare(t1.Items, t0.Items); /* 2^255 - 21 */ fmul(output, t1.Items, z11.Items); }
/* Calculates nQ where Q is the x-coordinate of a point on the curve * * resultx/resultz: the x coordinate of the resulting curve point (short form) * n: a little endian, 32-byte number * q: a point of the curve (short form) */ private static void cmult(limb* resultx, limb* resultz, byte* n, limb* q) { Long19 a = new Long19(); Long19 b = new Long19(); Long19 c = new Long19(); Long19 d = new Long19(); b.Items[0] = 1; c.Items[0] = 1; limb* nqpqx = a.Items, nqpqz = b.Items, nqx = c.Items, nqz = d.Items, t; Long19 e = new Long19(); Long19 f = new Long19(); Long19 g = new Long19(); Long19 h = new Long19(); f.Items[0] = 1; h.Items[0] = 1; limb* nqpqx2 = e.Items, nqpqz2 = f.Items, nqx2 = g.Items, nqz2 = h.Items; memcpy10(nqpqx, q); for (int i = 0; i < 32; ++i) { byte @byte = n[31 - i]; for (int j = 0; j < 8; ++j) { limb bit = @byte >> 7; swap_conditional(nqx, nqpqx, bit); swap_conditional(nqz, nqpqz, bit); fmonty(nqx2, nqz2, nqpqx2, nqpqz2, nqx, nqz, nqpqx, nqpqz, q); swap_conditional(nqx2, nqpqx2, bit); swap_conditional(nqz2, nqpqz2, bit); t = nqx; nqx = nqx2; nqx2 = t; t = nqz; nqz = nqz2; nqz2 = t; t = nqpqx; nqpqx = nqpqx2; nqpqx2 = t; t = nqpqz; nqpqz = nqpqz2; nqpqz2 = t; @byte <<= 1; } } memcpy10(resultx, nqx); memcpy10(resultz, nqz); }
internal static void curve25519_donna(byte* mypublic, byte* secret, byte* basepoint) { Long19 bp = new Long19(); Long19 x = new Long19(); Long19 z = new Long19(); Long19 zmone = new Long19(); Byte32 e = new Byte32(); int i; for (i = 0; i < 32; ++i) e.Items[i] = secret[i]; e.Items[0] &= 248; e.Items[31] &= 127; e.Items[31] |= 64; fexpand(bp.Items, basepoint); cmult(x.Items, z.Items, e.Items, bp.Items); crecip(zmone.Items, z.Items); fmul(z.Items, x.Items, zmone.Items); freduce_coefficients(z.Items); fcontract(mypublic, z.Items); }
crecip(limb *output, limb *z) { Long19 z2 = new Long19(); Long19 z9 = new Long19(); Long19 z11 = new Long19(); Long19 z2_5_0 = new Long19(); Long19 z2_10_0 = new Long19(); Long19 z2_20_0 = new Long19(); Long19 z2_50_0 = new Long19(); Long19 z2_100_0 = new Long19(); Long19 t0 = new Long19(); Long19 t1 = new Long19(); int i; /* 2 */ fsquare(z2.Items, z); /* 4 */ fsquare(t1.Items, z2.Items); /* 8 */ fsquare(t0.Items, t1.Items); /* 9 */ fmul(z9.Items, t0.Items, z); /* 11 */ fmul(z11.Items, z9.Items, z2.Items); /* 22 */ fsquare(t0.Items, z11.Items); /* 2^5 - 2^0 = 31 */ fmul(z2_5_0.Items, t0.Items, z9.Items); /* 2^6 - 2^1 */ fsquare(t0.Items, z2_5_0.Items); /* 2^7 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^8 - 2^3 */ fsquare(t0.Items, t1.Items); /* 2^9 - 2^4 */ fsquare(t1.Items, t0.Items); /* 2^10 - 2^5 */ fsquare(t0.Items, t1.Items); /* 2^10 - 2^0 */ fmul(z2_10_0.Items, t0.Items, z2_5_0.Items); /* 2^11 - 2^1 */ fsquare(t0.Items, z2_10_0.Items); /* 2^12 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^20 - 2^0 */ fmul(z2_20_0.Items, t1.Items, z2_10_0.Items); /* 2^21 - 2^1 */ fsquare(t0.Items, z2_20_0.Items); /* 2^22 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^40 - 2^0 */ fmul(t0.Items, t1.Items, z2_20_0.Items); /* 2^41 - 2^1 */ fsquare(t1.Items, t0.Items); /* 2^42 - 2^2 */ fsquare(t0.Items, t1.Items); /* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2) { fsquare(t1.Items, t0.Items); fsquare(t0.Items, t1.Items); } /* 2^50 - 2^0 */ fmul(z2_50_0.Items, t0.Items, z2_10_0.Items); /* 2^51 - 2^1 */ fsquare(t0.Items, z2_50_0.Items); /* 2^52 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^100 - 2^0 */ fmul(z2_100_0.Items, t1.Items, z2_50_0.Items); /* 2^101 - 2^1 */ fsquare(t1.Items, z2_100_0.Items); /* 2^102 - 2^2 */ fsquare(t0.Items, t1.Items); /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) { fsquare(t1.Items, t0.Items); fsquare(t0.Items, t1.Items); } /* 2^200 - 2^0 */ fmul(t1.Items, t0.Items, z2_100_0.Items); /* 2^201 - 2^1 */ fsquare(t0.Items, t1.Items); /* 2^202 - 2^2 */ fsquare(t1.Items, t0.Items); /* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2) { fsquare(t0.Items, t1.Items); fsquare(t1.Items, t0.Items); } /* 2^250 - 2^0 */ fmul(t0.Items, t1.Items, z2_50_0.Items); /* 2^251 - 2^1 */ fsquare(t1.Items, t0.Items); /* 2^252 - 2^2 */ fsquare(t0.Items, t1.Items); /* 2^253 - 2^3 */ fsquare(t1.Items, t0.Items); /* 2^254 - 2^4 */ fsquare(t0.Items, t1.Items); /* 2^255 - 2^5 */ fsquare(t1.Items, t0.Items); /* 2^255 - 21 */ fmul(output, t1.Items, z11.Items); }
cmult(limb *resultx, limb *resultz, byte *n, limb *q) { Long19 a = new Long19(); Long19 b = new Long19(); Long19 c = new Long19(); Long19 d = new Long19(); b.Items[0] = 1; c.Items[0] = 1; limb *nqpqx = a.Items, nqpqz = b.Items, nqx = c.Items, nqz = d.Items, t; Long19 e = new Long19(); Long19 f = new Long19(); Long19 g = new Long19(); Long19 h = new Long19(); f.Items[0] = 1; h.Items[0] = 1; limb *nqpqx2 = e.Items, nqpqz2 = f.Items, nqx2 = g.Items, nqz2 = h.Items; memcpy(nqpqx, q, sizeof(limb) * 10); for (int i = 0; i < 32; ++i) { byte @byte = n[31 - i]; for (int j = 0; j < 8; ++j) { limb bit = @byte >> 7; swap_conditional(nqx, nqpqx, bit); swap_conditional(nqz, nqpqz, bit); fmonty(nqx2, nqz2, nqpqx2, nqpqz2, nqx, nqz, nqpqx, nqpqz, q); swap_conditional(nqx2, nqpqx2, bit); swap_conditional(nqz2, nqpqz2, bit); t = nqx; nqx = nqx2; nqx2 = t; t = nqz; nqz = nqz2; nqz2 = t; t = nqpqx; nqpqx = nqpqx2; nqpqx2 = t; t = nqpqz; nqpqz = nqpqz2; nqpqz2 = t; @byte <<= 1; } } memcpy(resultx, nqx, sizeof(limb) * 10); memcpy(resultz, nqz, sizeof(limb) * 10); }