private static void PointDouble(PointExt r) { uint[] B = X448Field.Create(); uint[] C = X448Field.Create(); uint[] D = X448Field.Create(); uint[] E = X448Field.Create(); uint[] H = X448Field.Create(); uint[] J = X448Field.Create(); X448Field.Add(r.x, r.y, B); X448Field.Sqr(B, B); X448Field.Sqr(r.x, C); X448Field.Sqr(r.y, D); X448Field.Add(C, D, E); X448Field.Carry(E); X448Field.Sqr(r.z, H); X448Field.Add(H, H, H); X448Field.Carry(H); X448Field.Sub(E, H, J); X448Field.Sub(B, E, B); X448Field.Sub(C, D, C); X448Field.Mul(B, J, r.x); X448Field.Mul(E, C, r.y); X448Field.Mul(E, J, r.z); }
private static void PointAddPrecomp(PointPrecomp p, PointExt r) { uint[] B = X448Field.Create(); uint[] C = X448Field.Create(); uint[] D = X448Field.Create(); uint[] E = X448Field.Create(); uint[] F = X448Field.Create(); uint[] G = X448Field.Create(); uint[] H = X448Field.Create(); X448Field.Sqr(r.z, B); X448Field.Mul(p.x, r.x, C); X448Field.Mul(p.y, r.y, D); X448Field.Mul(C, D, E); X448Field.Mul(E, -C_d, E); //X448Field.Apm(B, E, F, G); X448Field.Add(B, E, F); X448Field.Sub(B, E, G); X448Field.Add(p.x, p.y, B); X448Field.Add(r.x, r.y, E); X448Field.Mul(B, E, H); //X448Field.Apm(D, C, B, E); X448Field.Add(D, C, B); X448Field.Sub(D, C, E); X448Field.Carry(B); X448Field.Sub(H, B, H); X448Field.Mul(H, r.z, H); X448Field.Mul(E, r.z, E); X448Field.Mul(F, H, r.x); X448Field.Mul(E, G, r.y); X448Field.Mul(F, G, r.z); }
private static void EncodePoint(PointExt p, byte[] r, int rOff) { uint[] x = X448Field.Create(); uint[] y = X448Field.Create(); X448Field.Inv(p.z, y); X448Field.Mul(p.x, y, x); X448Field.Mul(p.y, y, y); X448Field.Normalize(x); X448Field.Normalize(y); X448Field.Encode(y, r, rOff); r[rOff + PointBytes - 1] = (byte)((x[0] & 1) << 7); }
private static int CheckPoint(uint[] x, uint[] y) { uint[] t = X448Field.Create(); uint[] u = X448Field.Create(); uint[] v = X448Field.Create(); X448Field.Sqr(x, u); X448Field.Sqr(y, v); X448Field.Mul(u, v, t); X448Field.Add(u, v, u); X448Field.Mul(t, -C_d, t); X448Field.SubOne(t); X448Field.Add(t, u, t); X448Field.Normalize(t); return(X448Field.IsZero(t)); }
private static void PointAddVar(bool negate, PointExt p, PointExt r) { uint[] A = X448Field.Create(); uint[] B = X448Field.Create(); uint[] C = X448Field.Create(); uint[] D = X448Field.Create(); uint[] E = X448Field.Create(); uint[] F = X448Field.Create(); uint[] G = X448Field.Create(); uint[] H = X448Field.Create(); uint[] b, e, f, g; if (negate) { b = E; e = B; f = G; g = F; X448Field.Sub(p.y, p.x, H); } else { b = B; e = E; f = F; g = G; X448Field.Add(p.y, p.x, H); } X448Field.Mul(p.z, r.z, A); X448Field.Sqr(A, B); X448Field.Mul(p.x, r.x, C); X448Field.Mul(p.y, r.y, D); X448Field.Mul(C, D, E); X448Field.Mul(E, -C_d, E); //X448Field.Apm(B, E, F, G); X448Field.Add(B, E, f); X448Field.Sub(B, E, g); X448Field.Add(r.x, r.y, E); X448Field.Mul(H, E, H); //X448Field.Apm(D, C, B, E); X448Field.Add(D, C, b); X448Field.Sub(D, C, e); X448Field.Carry(b); X448Field.Sub(H, B, H); X448Field.Mul(H, A, H); X448Field.Mul(E, A, E); X448Field.Mul(F, H, r.x); X448Field.Mul(E, G, r.y); X448Field.Mul(F, G, r.z); }
private static bool DecodePointVar(byte[] p, int pOff, bool negate, PointExt r) { byte[] py = Arrays.CopyOfRange(p, pOff, pOff + PointBytes); if (!CheckPointVar(py)) { return(false); } int x_0 = (py[PointBytes - 1] & 0x80) >> 7; py[PointBytes - 1] &= 0x7F; X448Field.Decode(py, 0, r.y); uint[] u = X448Field.Create(); uint[] v = X448Field.Create(); X448Field.Sqr(r.y, u); X448Field.Mul(u, (uint)-C_d, v); X448Field.Negate(u, u); X448Field.AddOne(u); X448Field.AddOne(v); if (!X448Field.SqrtRatioVar(u, v, r.x)) { return(false); } X448Field.Normalize(r.x); if (x_0 == 1 && X448Field.IsZeroVar(r.x)) { return(false); } if (negate ^ (x_0 != (r.x[0] & 1))) { X448Field.Negate(r.x, r.x); } PointExtendXY(r); return(true); }
public static void Precompute() { lock (precompLock) { if (precompBase != null) { return; } PointExt p = new PointExt(); X448Field.Copy(B_x, 0, p.x, 0); X448Field.Copy(B_y, 0, p.y, 0); PointExtendXY(p); precompBaseTable = PointPrecompVar(p, 1 << (WnafWidthBase - 2)); precompBase = new uint[PrecompBlocks * PrecompPoints * 2 * X448Field.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) { PointAddVar(true, p, 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) { points[k] = PointCopy(points[k - size]); PointAddVar(false, ds[t], points[k]); } } Debug.Assert(k == PrecompPoints); for (int i = 0; i < PrecompPoints; ++i) { PointExt q = points[i]; // TODO[ed448] Batch inversion X448Field.Inv(q.z, q.z); X448Field.Mul(q.x, q.z, q.x); X448Field.Mul(q.y, q.z, q.y); //X448Field.Normalize(q.x); //X448Field.Normalize(q.y); X448Field.Copy(q.x, 0, precompBase, off); off += X448Field.Size; X448Field.Copy(q.y, 0, precompBase, off); off += X448Field.Size; } } Debug.Assert(off == precompBase.Length); } }