Example #1
0
 private bool CheckPubkeys(Autarkysoft.Bitcoin.Cryptography.Asymmetric.EllipticCurve.Signature sig, byte[] toSign, string address, Address.AddressType addrType)
 {
     if (calc.TryRecoverPublicKeys(toSign, sig, out EllipticCurvePoint[] pubkeys))
Example #2
0
 /// <summary>
 /// Verifies if the given signature is a valid ECDSA signature based on Standards for Efficient Cryptography
 /// (SEC 1: Elliptic Curve Cryptography) 4.1.4 Verifying Operation (page 46).
 /// </summary>
 /// <param name="hash">Hash(m) used in signing</param>
 /// <param name="sig">Signature</param>
 /// <param name="pubK">Public key</param>
 /// <param name="lowS">If true s values bigger than <see cref="IECurveFp.N"/>/2 are rejected.</param>
 /// <returns>True if the signature was valid, otherwise false.</returns>
 public bool Verify(byte[] hash, Signature sig, PublicKey pubK, bool lowS = true)
 {
     return(Verify(hash, sig, pubK.ToPoint(), lowS));
 }
Example #3
0
 /// <summary>
 /// Verifies if the given signature is a valid ECSDSA signature based on BIP-340.
 /// </summary>
 /// <param name="hash">Hash(m) used in signing</param>
 /// <param name="sig">Signature</param>
 /// <param name="pubK">Public key</param>
 /// <returns>True if the signature was valid, otherwise false.</returns>
 public bool VerifySchnorr(byte[] hash, Signature sig, PublicKey pubK)
 {
     return(VerifySchnorr(hash, sig, pubK.ToPoint()));
 }
Example #4
0
        // Note: in all the following methods, we assume inputs are valid hence skip checkking.
        // It is because all these methods are used internally by other classes that perform the checks.
        // for example Sign() is used by PrivateKey so the keyBytes and hash are both valid

        /// <summary>
        /// Creates a signature using ECDSA based on Standards for Efficient Cryptography (SEC 1: Elliptic Curve Cryptography)
        /// section 4.1.3 Signing Operation (page 44).
        /// Return value indicates success.
        /// </summary>
        /// <param name="hash">Hash(m) to use for signing</param>
        /// <param name="key">Private key bytes (must be padded to 32 bytes)</param>
        /// <param name="k">
        /// The ephemeral elliptic curve key used for signing
        /// (k should be smaller than <see cref="IECurveFp.N"/>, it is always smaller if <see cref="Rfc6979"/> is used).
        /// </param>
        /// <param name="lowS">If true s values bigger than <see cref="IECurveFp.N"/>/2 will be converted.</param>
        /// <param name="lowR">If true the process fails if R.X had its highest bit set</param>
        /// <param name="sig">Signature (null if process fails)</param>
        /// <returns>True if successful, otherwise false.</returns>
        public bool TrySign(byte[] hash, byte[] key, BigInteger k, bool lowS, bool lowR, out Signature sig)
        {
            // TODO: research what happens if e value is zero. does it reveal private key?
            // https://bitcointalk.org/index.php?topic=260595.msg4928224#msg4928224
            BigInteger e = hash.ToBigInt(true, true);

            EllipticCurvePoint rp = MultiplyChecked(k, curve.G);
            byte v = (byte)(((rp.X > curve.N) ? 2 : 0) | (rp.Y.IsEven ? 0 : 1));

            BigInteger r = rp.X % curve.N;

            // Note about r:
            // R.X is at most 32 bytes, if the highest bit is set then in DER encoding 0 is appended to indicate
            // it is a positive integer.
            // Here if low r is requested, we only check the length and reject cases where R.X is 32 bytes and needs the
            // additional 0 and if R.X was smaller than 32 bytes it passes even if the higest bit was set.
            // In other words 0<31 bytes> or 0<30 byte>,... are accepted

            // TODO: when BigInteger is replaced by ModularUInt256 in the future, this should be replaced by a simple
            // test of the highest bit instead of ToByteArray and length check.
            if (r == 0 || (lowR && r.ToByteArray(isBigEndian: true).Length > 32))
            {
                sig = null;
                return(false);
            }

            BigInteger s = k.ModInverse(curve.N) * (e + (r * key.ToBigInt(true, true))) % curve.N;

            if (s == 0)
            {
                sig = null;
                return(false);
            }
            if (lowS && s > curve.N / 2)
            {
                v ^= 1;
                s  = curve.N - s;
            }

            sig = new Signature(r, s, v);
            return(true);
        }