private static void Precompute() { PointAccum p = new PointAccum(); X25519Field.Copy(B_x, 0, p.x, 0); X25519Field.Copy(B_y, 0, p.y, 0); PointExtendXY(p); precompBase = new int[PrecompBlocks * PrecompPoints * 3 * X25519Field.Size]; int off = 0; for (int b = 0; b < PrecompBlocks; ++b) { PointExt[] ds = new PointExt[PrecompTeeth]; PointExt sum = new PointExt(); PointSetNeutral(sum); for (int t = 0; t < PrecompTeeth; ++t) { PointExt q = PointCopy(p); PointAddVar(true, sum, q, sum); PointDouble(p); ds[t] = PointCopy(p); if (b + t != PrecompBlocks + PrecompTeeth - 2) { for (int s = 1; s < PrecompSpacing; ++s) { PointDouble(p); } } } PointExt[] points = new PointExt[PrecompPoints]; int k = 0; points[k++] = sum; for (int t = 0; t < (PrecompTeeth - 1); ++t) { int size = 1 << t; for (int j = 0; j < size; ++j, ++k) { PointAddVar(false, points[k - size], ds[t], points[k] = new PointExt()); } } for (int i = 0; i < PrecompPoints; ++i) { PointExt q = points[i]; int[] x = new int[X25519Field.Size]; int[] y = new int[X25519Field.Size]; X25519Field.Add(q.z, q.z, x); X25519Field.Inv(x, y); X25519Field.Mul(q.x, y, x); X25519Field.Mul(q.y, y, y); PointPrecomp r = new PointPrecomp(); X25519Field.Apm(y, x, r.ypx_h, r.ymx_h); X25519Field.Mul(x, y, r.xyd); X25519Field.Mul(r.xyd, C_d4, r.xyd); X25519Field.Normalize(r.ypx_h); X25519Field.Normalize(r.ymx_h); X25519Field.Copy(r.ypx_h, 0, precompBase, off); off += X25519Field.Size; X25519Field.Copy(r.ymx_h, 0, precompBase, off); off += X25519Field.Size; X25519Field.Copy(r.xyd, 0, precompBase, off); off += X25519Field.Size; } } }
private static void ScalarMult(ReadOnlySpan <byte> k, int kOff, ReadOnlySpan <byte> u, int uOff, Span <byte> r, int rOff) { Span <uint> n = stackalloc uint[8]; DecodeScalar(k, kOff, n); Span <int> x1 = stackalloc int[X25519Field.Size]; X25519Field.Decode(u, uOff, x1); Span <int> x2 = stackalloc int[X25519Field.Size]; X25519Field.Copy(x1, 0, x2, 0); Span <int> z2 = stackalloc int[X25519Field.Size]; z2[0] = 1; Span <int> x3 = stackalloc int[X25519Field.Size]; x3[0] = 1; Span <int> z3 = stackalloc int[X25519Field.Size]; Span <int> t1 = stackalloc int[X25519Field.Size]; Span <int> t2 = stackalloc int[X25519Field.Size]; int bit = 254, swap = 1; do { X25519Field.Apm(x3, z3, t1, x3); X25519Field.Apm(x2, z2, z3, x2); X25519Field.Mul(t1, x2, t1); X25519Field.Mul(x3, z3, x3); X25519Field.Sqr(z3, z3); X25519Field.Sqr(x2, x2); X25519Field.Sub(z3, x2, t2); X25519Field.Mul(t2, C_A24, z2); X25519Field.Add(z2, x2, z2); X25519Field.Mul(z2, t2, z2); X25519Field.Mul(x2, z3, x2); X25519Field.Apm(t1, x3, x3, z3); X25519Field.Sqr(x3, x3); X25519Field.Sqr(z3, z3); X25519Field.Mul(z3, x1, z3); --bit; int word = bit >> 5, shift = bit & 0x1F; int kt = (int)(n[word] >> shift) & 1; swap ^= kt; X25519Field.CSwap(swap, x2, x3); X25519Field.CSwap(swap, z2, z3); swap = kt; }while (bit >= 3); for (int i = 0; i < 3; ++i) { PointDouble(x2, z2); } X25519Field.Inv(z2, z2); X25519Field.Mul(x2, z2, x2); X25519Field.Normalize(x2); X25519Field.Encode(x2, r, rOff); }