static ECDomainParameters Create(Number a, Number b, Number gX, Number gY, Number order, uint h, IFiniteField ff, Uri uri) { ECGroup group = new ECGroup(ff.ToElement(a), ff.ToElement(b), ff.Modulus, ff); ECPoint basePoint = new ECPoint(group, ff.ToElement(gX), ff.ToElement(gY), ff.ToElement(Number.One)); return(new ECDomainParameters(group, basePoint, order, h, (uint)ff.Modulus.BitCount(), new Classical(order), uri)); }
/// <summary>バイト配列より点を作成する (SEC1, 2.3.4)</summary> public ECPoint(ECGroup group, byte[] data) { _group = group; _field = group.FiniteField; switch (data[0]) { case 0: { // 無限遠点 ECPoint tmp = _field.GetInfinityPoint(_group); _x = tmp._x; _y = tmp._y; _z = tmp._z; return; } case 2: case 3: { // 点圧縮済みデータ int keyBits = group.P.BitCount(); int keyBytes = (keyBits >> 3) + ((keyBits & 7) == 0 ? 0 : 1); if (data.Length != keyBytes + 1) { throw new ArgumentException(); } Number x = _field.ToElement(new Number(data, 1, keyBytes, false)); Number y2 = _field.Add(_field.Multiply(_field.Add(_field.Multiply(x, x), _group.A), x), _group.B); // (x^2 + a)*x + b Number y = _field.Sqrt(y2); if (_field.ToNormal(y).GetBit(0) != data[0] - 2) { y = _field.Modulus - y; } _x = x; _y = y; _z = _field.ToElement(Number.One); return; } case 4: { // 非圧縮データ int keyBits = group.P.BitCount(); int keyBytes = (keyBits >> 3) + ((keyBits & 7) == 0 ? 0 : 1); _x = _field.ToElement(new Number(data, 1, keyBytes, false)); _y = _field.ToElement(new Number(data, 1 + keyBytes, keyBytes, false)); _z = _field.ToElement(Number.One); return; } default: throw new ArgumentException(); } }
/// <summary>バイト配列より点を作成する (SEC1, 2.3.4)</summary> public ECPoint (ECGroup group, byte[] data) { _group = group; _field = group.FiniteField; switch (data[0]) { case 0: { // 無限遠点 ECPoint tmp = _field.GetInfinityPoint (_group); _x = tmp._x; _y = tmp._y; _z = tmp._z; return; } case 2: case 3: { // 点圧縮済みデータ int keyBits = group.P.BitCount (); int keyBytes = (keyBits >> 3) + ((keyBits & 7) == 0 ? 0 : 1); if (data.Length != keyBytes + 1) throw new ArgumentException (); Number x = _field.ToElement (new Number (data, 1, keyBytes, false)); Number y2 = _field.Add (_field.Multiply (_field.Add (_field.Multiply (x, x), _group.A), x), _group.B); // (x^2 + a)*x + b Number y = _field.Sqrt (y2); if (_field.ToNormal (y).GetBit (0) != data[0] - 2) y = _field.Modulus - y; _x = x; _y = y; _z = _field.ToElement (Number.One); return; } case 4: { // 非圧縮データ int keyBits = group.P.BitCount (); int keyBytes = (keyBits >> 3) + ((keyBits & 7) == 0 ? 0 : 1); _x = _field.ToElement (new Number (data, 1, keyBytes, false)); _y = _field.ToElement (new Number (data, 1 + keyBytes, keyBytes, false)); _z = _field.ToElement (Number.One); return; } default: throw new ArgumentException (); } }
/// <summary> /// TODO: 未実装のValidationステップを実装する /// </summary> public bool Validate() { IFiniteField ff = _group.FiniteField; // Step1: Check that p is an odd prime // Step2: Check that a,b,Gx and Gy are integers in the interval [0, p - 1] ECPoint ExportedG = _G.Export(); Number Gx = ff.ToElement(ExportedG.X); Number Gy = ff.ToElement(ExportedG.Y); if (A > P || B > P || Gx > P || Gy > P) { return(false); } // Step3: Check that 4*a^3 + 27*b^2 != 0 (mod p) Number Apow3 = ff.Multiply(A, ff.Multiply(A, A)); Number Bpow2 = ff.Multiply(B, B); Number ret = ff.Add(ff.Multiply(ff.ToElement(Number.Four), ff.ToElement(Apow3)), ff.Multiply(ff.ToElement(Number.TwentySeven), Bpow2)); if (ret.IsZero()) { return(false); } // Step4: Gy^2 = Gx^3 + a*Gx + b Number aGx = ff.Multiply(A, Gx); Number Xpow3 = ff.Multiply(Gx, ff.Multiply(Gx, Gx)); Number Ypow2 = ff.Multiply(Gy, Gy); ret = ff.Add(Xpow3, ff.Add(aGx, B)); if (ret.CompareTo(Ypow2) != 0) { return(false); } // Step5: Check that n is prime. // Step6: Check that h <= 4, and that h = (sqrt(p)+1)^2 / n // Step7: Check that nG = O ECPoint nG = _G.Multiply(N).Export(); if (!nG.IsInifinity()) { return(false); } // Step8: Check that q^B != 1 (mod n) for any 1 <= B <= 20, and that nh != p Number p = Number.One; Classical c = new Classical(N); for (int i = 0; i <= 20; i++) { p = c.Multiply(p, P); if (p.IsOne()) { return(false); } } if (c.Multiply(N, new Number(new uint[] { H }, 1)).CompareTo(P) == 0) { return(false); } return(true); }
internal byte[] SignHash(byte[] hash, byte[] randomK) #endif { if (hash == null) { throw new ArgumentNullException(); } if (hash.Length == 0) { throw new ArgumentException(); } if (_params.D == null && _params.Q == null) { _params.CreateNewPrivateKey(); } if (_params.D == null) { throw new CryptographicException(); } Number r, s, k; IFiniteField field = _params.Domain.FieldN; int keyBytes = (int)((_params.Domain.Bits >> 3) + ((_params.Domain.Bits & 7) == 0 ? 0U : 1U)); byte[] raw = new byte[keyBytes << 1]; Number e = HashToNumber(hash); do { do { // Step.1 #if TEST k = randomK == null ? k = Number.CreateRandomElement(_params.Domain.N) : new Number(randomK, false); #else k = Number.CreateRandomElement(_params.Domain.N); #endif // Step.2 ECPoint tmp = _params.Domain.G.Multiply(k).Export(); // Step.3 r = tmp.X % _params.Domain.N; if (!r.IsZero()) { r.CopyToBigEndian(raw, 0, keyBytes); break; } } while (true); // Step.4 k = field.Invert(field.ToElement(k)); // Step.6 r = field.ToElement(r); e = field.ToElement(e); s = field.Multiply(k, field.Add(e, field.Multiply(r, field.ToElement(_params.D)))); if (!s.IsZero()) { s = field.ToNormal(s); s.CopyToBigEndian(raw, raw.Length >> 1, keyBytes); break; } } while (true); return(raw); }
public bool VerifyHash(byte[] hash, byte[] sig) { if (sig.Length != (_params.Domain.Bits >> 2) + ((_params.Domain.Bits & 7) == 0 ? 0 : 2)) { throw new ArgumentException(); } if (hash.Length == 0) { throw new ArgumentException(); } if (_params.Q == null && _params.D != null) { _params.CreatePublicKeyFromPrivateKey(); } if (_params.Q == null) { throw new CryptographicException(); } int halfLen = sig.Length >> 1; Number r = new Number(sig, 0, halfLen, false); Number s = new Number(sig, halfLen, halfLen, false); Number e = HashToNumber(hash); IFiniteField field = _params.Domain.FieldN; if (r >= _params.Domain.N || s >= _params.Domain.N) { return(false); } // Step.1 e = field.ToElement(e); s = field.ToElement(s); Number r2 = field.ToElement(r); // Step.2 Number w = field.Invert(s); // Step.3 Number u1 = field.ToNormal(field.Multiply(e, w)); Number u2 = field.ToNormal(field.Multiply(r2, w)); // Step.4 //ECPoint X = _params.Domain.G.Multiply (u1).Add (_params.Q.Multiply (u2)); ECPoint X; if (u1.IsZero()) { X = _params.Domain.FieldN.GetInfinityPoint(_params.Domain.Group).Add(_params.Q.Multiply(u2)); } else { X = ECPoint.MultiplyAndAdd(_params.Domain.G, u1, _params.Q, u2); } // Step.5 if (X.IsInifinity()) { return(false); } X = X.Export(); // Step.6 Number v = X.X % _params.Domain.N; return(r.CompareTo(v) == 0); }