private static int[] PointPrecompute(PointAffine p, int count) { Debug.Assert(count > 0); PointExt q = PointCopy(p); PointExt d = PointCopy(q); PointAdd(q, d); int[] table = X25519Field.CreateTable(count * 4); int off = 0; int i = 0; for (;;) { X25519Field.Copy(q.x, 0, table, off); off += X25519Field.Size; X25519Field.Copy(q.y, 0, table, off); off += X25519Field.Size; X25519Field.Copy(q.z, 0, table, off); off += X25519Field.Size; X25519Field.Copy(q.t, 0, table, off); off += X25519Field.Size; if (++i == count) { break; } PointAdd(d, q); } return(table); }
private static void ScalarMultOrderVar(PointAffine p, PointAccum r) { int width = 5; sbyte[] ws_p = GetWnafVar(L, width); PointExt[] tp = PointPrecomputeVar(PointCopy(p), 1 << (width - 2)); PointSetNeutral(r); for (int bit = 252; ;) { int wp = ws_p[bit]; if (wp != 0) { int sign = wp >> 31; int index = (wp ^ sign) >> 1; PointAddVar((sign != 0), tp[index], r); } if (--bit < 0) { break; } PointDouble(r); } }
public static bool ValidatePublicKeyFull(byte[] pk, int pkOff) { PointAffine p = new PointAffine(); if (!DecodePointVar(pk, pkOff, false, p)) { return(false); } F.Normalize(p.x); F.Normalize(p.y); if (IsNeutralElementVar(p.x, p.y)) { return(false); } PointAccum r = new PointAccum(); ScalarMultOrderVar(p, r); F.Normalize(r.x); F.Normalize(r.y); F.Normalize(r.z); return(IsNeutralElementVar(r.x, r.y, r.z)); }
public static EllipticCurveEdwards GenerateCurve12(BigInteger n, out BigInteger x, out BigInteger y)// Z/12Z { var E = new EllipticCurveWeierstrass(-12, 0, n); PointAffine P; BigInteger d; while (true) { P = new PointAffine(6, -12, E); BigInteger k = new Random().Next() % n; P = k * P; if ((P.x == 0 && P.y == 0) || (P.x == -2 && BigInteger.Abs(P.y) == 4) || (P.x == 6 && BigInteger.Abs(P.y) == 12)) { continue; } BigInteger temp = (1024 * P.x * P.x * P.y * P.y) % n; BigInteger inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } temp = (-BigInteger.ModPow(P.x - 2, 3, n) * BigInteger.ModPow(P.x + 6, 3, n) * (P.x * P.x - 12 * P.x - 12)) % n; if (temp < 0) { temp += n; } d = (temp * inv) % n; temp = ((P.x - 2) * (P.x + 6) * (P.x * P.x + 12 * P.x - 12)) % n; if (temp < 0) { temp += n; } inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } x = (8 * P.y * (P.x * P.x + 12) * inv) % n; temp = ((P.x - 2) * (P.x + 6) * (P.x * P.x - 12)) % n; if (temp < 0) { temp += n; } inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } y = (-4 * P.x * (P.x * P.x - 12 * P.x - 12) * inv) % n; break; } return(new EllipticCurveEdwards(1, d, n)); }
private static PointExt PointCopy(PointAffine p) { PointExt r = new PointExt(); F.Copy(p.x, 0, r.x, 0); F.Copy(p.y, 0, r.y, 0); PointExtendXY(r); return(r); }
private static bool ImplVerify(byte[] sig, int sigOff, byte[] pk, int pkOff, byte[] ctx, byte phflag, byte[] m, int mOff, int mLen) { if (!CheckContextVar(ctx, phflag)) { throw new ArgumentException("ctx"); } byte[] R = Arrays.CopyOfRange(sig, sigOff, sigOff + PointBytes); byte[] S = Arrays.CopyOfRange(sig, sigOff + PointBytes, sigOff + SignatureSize); if (!CheckPointVar(R)) { return(false); } if (!CheckScalarVar(S)) { return(false); } PointAffine pA = new PointAffine(); if (!DecodePointVar(pk, pkOff, true, pA)) { return(false); } IDigest d = CreateDigest(); byte[] h = new byte[d.GetDigestSize()]; Dom2(d, phflag, ctx); d.BlockUpdate(R, 0, PointBytes); d.BlockUpdate(pk, pkOff, PointBytes); d.BlockUpdate(m, mOff, mLen); d.DoFinal(h, 0); byte[] k = ReduceScalar(h); uint[] nS = new uint[ScalarUints]; DecodeScalar(S, 0, nS); uint[] nA = new uint[ScalarUints]; DecodeScalar(k, 0, nA); PointAccum pR = new PointAccum(); ScalarMultStrausVar(nS, nA, pA, pR); byte[] check = new byte[PointBytes]; return(0 != EncodePoint(pR, check, 0) && Arrays.AreEqual(check, R)); }
private static void ScalarMult(byte[] k, PointAffine p, PointAccum r) { uint[] n = new uint[ScalarUints]; DecodeScalar(k, 0, n); Debug.Assert(0U == (n[0] & 7)); Debug.Assert(1U == n[ScalarUints - 1] >> 30); Nat.ShiftDownBits(ScalarUints, n, 3, 1U); // Recode the scalar into signed-digit form { uint c1 = Nat.CAdd(ScalarUints, ~(int)n[0] & 1, n, L, n); Debug.Assert(c1 == 0U); uint c2 = Nat.ShiftDownBit(ScalarUints, n, 0U); Debug.Assert(c2 == (1U << 31)); } Debug.Assert(1U == n[ScalarUints - 1] >> 28); int[] table = PointPrecompute(p, 8); PointExt q = new PointExt(); // Replace first 4 doublings (2^4 * P) with 1 addition (P + 15 * P) PointCopy(p, r); PointLookup(table, 7, q); PointAdd(q, r); int w = 62; for (;;) { PointLookup(n, w, table, q); PointAdd(q, r); PointDouble(r); PointDouble(r); PointDouble(r); if (--w < 0) { break; } PointDouble(r); } }
private static void ScalarMultStrausVar(uint[] nb, uint[] np, PointAffine p, PointAccum r) { Precompute(); int width = 5; sbyte[] ws_b = GetWnafVar(nb, WnafWidthBase); sbyte[] ws_p = GetWnafVar(np, width); PointExt[] tp = PointPrecomputeVar(PointCopy(p), 1 << (width - 2)); PointSetNeutral(r); for (int bit = 252;;) { int wb = ws_b[bit]; if (wb != 0) { int sign = wb >> 31; int index = (wb ^ sign) >> 1; PointAddVar((sign != 0), precompBaseTable[index], r); } int wp = ws_p[bit]; if (wp != 0) { int sign = wp >> 31; int index = (wp ^ sign) >> 1; PointAddVar((sign != 0), tp[index], r); } if (--bit < 0) { break; } PointDouble(r); } }
private static bool DecodePointVar(byte[] p, int pOff, bool negate, PointAffine r) { byte[] py = Copy(p, pOff, PointBytes); if (!CheckPointVar(py)) { return(false); } int x_0 = (py[PointBytes - 1] & 0x80) >> 7; py[PointBytes - 1] &= 0x7F; F.Decode(py, 0, r.y); int[] u = F.Create(); int[] v = F.Create(); F.Sqr(r.y, u); F.Mul(C_d, u, v); F.SubOne(u); F.AddOne(v); if (!F.SqrtRatioVar(u, v, r.x)) { return(false); } F.Normalize(r.x); if (x_0 == 1 && F.IsZeroVar(r.x)) { return(false); } if (negate ^ (x_0 != (r.x[0] & 1))) { F.Negate(r.x, r.x); } return(true); }
private static void PointCopy(PointAffine p, PointAccum r) { F.Copy(p.x, 0, r.x, 0); F.Copy(p.y, 0, r.y, 0); PointExtendXY(r); }
public static bool ValidatePublicKeyPartial(byte[] pk, int pkOff) { PointAffine p = new PointAffine(); return(DecodePointVar(pk, pkOff, false, p)); }
public static EllipticCurveEdwards GenerateCurve2x8(BigInteger n, out BigInteger x, out BigInteger y)// Z/2Z x Z/8Z { var E = new EllipticCurveWeierstrass(-8, -32, n); PointAffine P; BigInteger d; while (true) { P = new PointAffine(12, 40, E); BigInteger k = new Random().Next() % n; P = k * P; BigInteger temp = (P.x - 9) % n; if (temp < 0) { temp += n; } BigInteger inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } temp = ((P.y + 25) * inv + 1) % n; if (temp < 0) { temp += n; } BigInteger a = Algorithms.Invert(temp, n); if (temp * a % n != 1) { continue; } temp = (8 * a * a - 1) % n; if (temp < 0) { temp += n; } inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } BigInteger b = (2 * a * (4 * a + 1) * inv) % n; temp = BigInteger.ModPow(2 * b - 1, 4, n); if (temp < 0) { temp += n; } inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } d = ((2 * (2 * b - 1) * (2 * b - 1) - 1) * inv) % n; temp = (6 * b - 5) % n; if (temp < 0) { temp += n; } inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } x = ((2 * b - 1) * (4 * b - 3) * inv) % n; temp = ((P.y + 3 * P.x - 2) * (P.y + P.x + 16)) % n; if (temp < 0) { temp += n; } inv = Algorithms.Invert(temp, n); if (temp * inv % n != 1) { continue; } y = ((2 * b - 1) * (P.y * P.y + 50 * P.y - 2 * P.x * P.x * P.x + 27 * P.x * P.x - 104) * inv) % n; break; } return(new EllipticCurveEdwards(1, d, n)); }