Beispiel #1
0
    public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
    {
      if (pubkey.Length == 33 && (pubkey[0] == 0x02 || pubkey[0] == 0x03))
      {
        try
        {
          pubkey = ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1).EncodePoint(false).Skip(1).ToArray();
        }
        catch
        {
          return false;
        }
      }
      else if (pubkey.Length == 65 && pubkey[0] == 0x04)
      {
        pubkey = pubkey.Skip(1).ToArray();
      }
      else if (pubkey.Length != 64)
      {
        throw new ArgumentException();
      }

      BigInteger x = new BigInteger(1, pubkey.Take(32).ToArray());
      BigInteger y = new BigInteger(1, pubkey.Skip(32).ToArray());

      X9ECParameters ecParams = NistNamedCurves.GetByName("P-256");
      ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N,
        ecParams.H, ecParams.GetSeed());
      var G = ecParams.G;
      Org.BouncyCastle.Math.EC.ECCurve curve = ecParams.Curve;
      Org.BouncyCastle.Math.EC.ECPoint q = curve.CreatePoint(x, y);

      ECPublicKeyParameters pubkeyParam = new ECPublicKeyParameters(q, domainParameters);

      var verifier = SignerUtilities.GetSigner("SHA-256withECDSA");
      
      verifier.Init(false, pubkeyParam);
      verifier.BlockUpdate(message, 0, message.Length);
      // expected format is SEQUENCE {INTEGER r, INTEGER s}
      var derSignature = new DerSequence(
          // first 32 bytes is "r" number
          new DerInteger(new BigInteger(1, signature.Take(32).ToArray())),
          // last 32 bytes is "s" number
          new DerInteger(new BigInteger(1, signature.Skip(32).ToArray())))
          .GetDerEncoded();

      ///old verify method
      ///
      /*
      const int ECDSA_PUBLIC_P256_MAGIC = 0x31534345;
      pubkey = BitConverter.GetBytes(ECDSA_PUBLIC_P256_MAGIC).Concat(BitConverter.GetBytes(32)).Concat(pubkey).ToArray();
      using (CngKey key = CngKey.Import(pubkey, CngKeyBlobFormat.EccPublicBlob))
      using (ECDsaCng ecdsa = new ECDsaCng(key))
      {
        var result = ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
      }
      */
      ///////////////////
      return verifier.VerifySignature(derSignature);
    }
Beispiel #2
0
        /// <summary>
        /// Hashes a seed t into a point T on the curve. Returns null if t is unsuitable.
        /// </summary>
        /// <param name="curve">The elliptic curve in Weierstrass form</param>
        /// <param name="t">The seed</param>
        /// <returns>A random point T uniquely determined by seed t, otherwise null</returns>
        public static ECPoint?HashToWeierstrassCurve(ECCurve curve, byte[] t)
        {
            ECFieldElement x, ax, x3, y, y2;

            BigInteger P      = curve.Field.Characteristic;
            SHA256?    sha256 = SHA256.Create();
            BigInteger hash   = new BigInteger(sha256.ComputeHash(t));

            // Check that the hash is within valid range
            if (hash.CompareTo(BigInteger.One) < 0 || hash.CompareTo(P) >= 0)
            {
                return(null);
            }

            // A valid point (x,y) must satisfy: y^2 = x^3 + Ax + B mod P
            // Convert hash from BigInt to FieldElement x modulo P
            x  = curve.FromBigInteger(hash);        // x
            ax = x.Multiply(curve.A);               // Ax
            x3 = x.Square().Multiply(x);            // x^3 = x^2 * x
            y2 = x3.Add(ax).Add(curve.B);           // y^2 = x^3 + Ax + B
            y  = y2.Sqrt();                         // y = sqrt(x^3 + Ax + B)

            // y == null if square root mod P does not exist
            if (y == null)
            {
                return(null);
            }

            ECPoint T = curve.CreatePoint(x.ToBigInteger(), y.ToBigInteger());

            // Use the built-in point validator, which also checks for membership
            // in weak subgroups
            if (!T.IsValid())
            {
                return(null);
            }

            return(T);
        }