private BigInteger Sqrt(BigInteger x, AnyRng rng) { if (!IsQuadraticResidue(x)) { throw new InvalidOperationException(); } BigInteger z; do { z = rng.NextBigInt(BigInteger.One, P); } while (IsQuadraticResidue(z)); var q = _eulerPower; ulong s = 1; while (q.IsEven) { s++; q /= 2; } var m = s; var c = BigInteger.ModPow(z, q, P); var t = BigInteger.ModPow(x, q, P); var r = BigInteger.ModPow(x, q / 2 + 1, P); while (true) { if (t.IsZero) { return(BigInteger.Zero); } if (t.IsOne) { return(r); } ulong i = 1; while (i < m) { if (BigInteger.ModPow(t, BigInteger.ModPow(2, i, P), P).IsOne) { break; } i++; } if (i == m) { throw new InvalidOperationException(); } var b = BigInteger.ModPow(c, BigInteger.ModPow(2, m - i - 1, P), P); m = i; c = b * b % P; t = t * b * b % P; r = r * b % P; } }
internal SM2KeyExchange(AnyRng rng, HashAlgorithm hash, byte[] zValue, BigInteger privateKey, bool responder, EcKeyPair ephemeralKey) { _rng = rng; _ephemeralKey = ephemeralKey; _hash = hash; _privateKey = privateKey; _zValue = zValue; _responder = responder; }
private SM2(IEcParameter param, HashAlgorithm hash, AnyRng rng) { #if NETSTANDARD2_0 || NETSTANDARD2_1 if (!hash.CanReuseTransform || !hash.CanTransformMultipleBlocks || hash.InputBlockSize != 1) { throw new ArgumentException(nameof(hash)); } #endif _rng = rng; _hash = hash; _param = param; _ident = Array.Empty <byte>(); }
public BigInteger SolveY(BigInteger x, bool lsbSet, AnyRng rng) { var rhs = x * x * x + A * x + B; rhs %= P; var r = Sqrt(rhs, rng); if (r.IsZero) { return(r); } if (lsbSet == r.IsEven) { r = P - r; } return(r); }
public static SM2 Create(HashAlgorithm hash, AnyRng rng) => new SM2(FpParameter.SM2StandardParam, hash, rng);
public static SM2 Create(AnyRng rng) => Create(new SM3(), rng);
public JacobianEcPoint Multiply(BigInteger k, JacobianEcPoint p, AnyRng rng) { if (k.Sign < 0) { k = -k; p = Negate(p); } if (k.IsZero) { return(JacobianEcPoint.Infinity); } if (k.IsOne) { return(p); } var ks = rng.NextBigInt(BigInteger.One, k); // return MultiplyAndAdd(ks, p, k - ks, p, rng); var(k1, k2) = ToNafBytes(k - ks, ks); var i = 0; while (i < k1.Length - 1) { var c = k1[i].NafValue() + k2[i].NafValue(); if (c != 0) { i++; continue; } if (k2[i + 1].NafValue() > 0) { k2[i + 1] = (byte)((k2[i + 1].H() << 4) | ((k2[i + 1].L() - 1) & 0xF)); k2[i] = (byte)(((k2[i].H() + 2) << 4) | (k2[i].L() & 0xF)); } else { k2[i + 1] = (byte)((k2[i + 1].H() << 4) | ((k2[i + 1].L() + 1) & 0xF)); k2[i] = (byte)(((k2[i].H() - 2) << 4) | (k2[i].L() & 0xF)); } } var lut = new [] { JacobianEcPoint.Infinity, p, Double(p), Add(Double(p), p), Double(Double(p)) }; var r = lut[k1.Back().NafValue() + k2.Back().NafValue()]; for (i = k1.Length - 2; i >= 0; i--) { var c = k1[i].NafValue() + k2[i].NafValue(); r = Add(Double(Double(r)), c < 0 ? Negate(lut[-c]) : lut[c]); } return(r); }
public JacobianEcPoint MultiplyAndAdd(BigInteger k, JacobianEcPoint p, BigInteger m, JacobianEcPoint s, AnyRng rng) { if (k.Sign < 0) { k = -k; p = Negate(p); } if (m.Sign < 0) { m = -m; s = Negate(s); } if (k.IsZero) { return(Multiply(m, s, rng)); } if (m.IsZero) { return(Multiply(k, p, rng)); } if (k.IsOne) { return(Add(p, Multiply(m, s, rng))); } if (m.IsOne) { return(Add(s, Multiply(k, p, rng))); } var(kk, mm) = ToNafBytes(k, m); var i = 0; while (i < kk.Length - 1) { if (kk[i] != 0 || mm[i] != 0) { i++; continue; } switch (mm[i + 1]) { case 0: mm[i + 1] = 0x01; mm[i] = 0xE0; break; case 0x0F: mm[i + 1] = 0xF0; mm[i] = 0x20; break; case 0x01: mm[i + 1] = 0x10; mm[i] = 0xE0; break; case 0xF0: mm[i + 1] = 0x0F; mm[i] = 0xE0; break; case 0x10: mm[i + 1] = 0x01; mm[i] = 0x20; break; default: throw new Exception(); } } var lut = new [] { // T[x,y] = lut[7x+y-1] s, Double(s), JacobianEcPoint.Infinity, Double(Double(s)), Add(p, Negate(Double(s))), Add(p, Negate(s)), p, Add(p, s), Add(p, Double(s)), JacobianEcPoint.Infinity, JacobianEcPoint.Infinity, Add(Double(p), Negate(Double(s))), Add(Double(p), Negate(s)), Double(p), Add(Double(p), s), Add(Double(p), Double(s)) }; var r = lut[kk.Back().NafValue() * 7 + mm.Back().NafValue() - 1]; for (i = kk.Length - 2; i >= 0; i--) { r = Double(Double(r)); if (kk[i] == 0) { if (mm[i].NafValue() < 0) { r = Add(r, Negate(lut[-mm[i].NafValue() - 1])); } else { r = Add(r, lut[mm[i].NafValue() - 1]); } } else if (kk[i].NafValue() < 0) { r = Add(r, Negate(lut[-kk[i].NafValue() * 7 - mm[i].NafValue() - 1])); } else { r = Add(r, lut[kk[i].NafValue() * 7 + mm[i].NafValue() - 1]); } } return(r); }