/// <summary>
        /// Verifies the given signature against the message and for the given address.
        /// </summary>
        /// <exception cref="ArgumentException"/>
        /// <exception cref="ArgumentNullException"/>
        /// <exception cref="FormatException"/>
        /// <param name="message">UTF-8 encoded message to sign</param>
        /// <param name="address">Address of the key used to create the given signature</param>
        /// <param name="signature">Fixed length (65 byte) signature with a starting recovery ID encoded using Base-64</param>
        /// <param name="ignoreSegwit">
        /// [Default value = false]
        /// If true and address type is a SegWit address, accepts both correct recovery ID (as defined by this BIP)
        /// and the incorrect one.
        /// This is useful to verify signature produced by popular Bitcoin implementations such as Electrum.
        /// </param>
        /// <returns>True if the verification succeeds; otherwise false.</returns>
        public bool Verify(string message, string address, string signature, bool ignoreSegwit = false)
        {
            byte[] toSign = GetBytesToSign(message);

            byte[] sigBa = Convert.FromBase64String(signature);
            if (!Signature.TryReadWithRecId(sigBa, out Signature sig, out string error))
            {
                throw new FormatException(error);
            }

            Address     addr     = new Address();
            AddressType addrType = AddressType.P2PKH_Compressed;

            if (sig.RecoveryId < 27 || sig.RecoveryId > 43)
            {
                return(false);
            }
            else if (sig.RecoveryId >= 27 && sig.RecoveryId < 35)
            {
                if (!addr.VerifyType(address, Blockchain.Scripts.PubkeyScriptType.P2PKH, out _))
                {
                    // Special case where this BIP is not used to create the signature
                    if (ignoreSegwit && addr.VerifyType(address, Blockchain.Scripts.PubkeyScriptType.P2SH, out _))
                    {
                        addrType = AddressType.P2SH_P2WPKH;
                    }
                    else if (ignoreSegwit && addr.VerifyType(address, Blockchain.Scripts.PubkeyScriptType.P2WPKH, out _))
                    {
                        addrType = AddressType.P2WPKH;
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    addrType = sig.RecoveryId < 31 ? AddressType.P2PKH_Uncompressed : AddressType.P2PKH_Compressed;
                }
            }
            else if (sig.RecoveryId >= 35 && sig.RecoveryId < 39)
            {
                if (!addr.VerifyType(address, Blockchain.Scripts.PubkeyScriptType.P2SH, out _))
                {
                    return(false);
                }
                addrType = AddressType.P2SH_P2WPKH;
            }
            else if (sig.RecoveryId >= 39 && sig.RecoveryId < 43)
            {
                if (!addr.VerifyType(address, Blockchain.Scripts.PubkeyScriptType.P2WPKH, out _))
                {
                    return(false);
                }
                addrType = AddressType.P2WPKH;
            }

            EllipticCurveCalculator calc = new EllipticCurveCalculator();

            if (!calc.TryRecoverPublicKeys(toSign, sig, out EllipticCurvePoint[] points))
 private bool CheckPubkeys(Signature sig, byte[] toSign, string address, AddressType addrType)
 {
     if (calc.TryRecoverPublicKeys(toSign, sig, out EllipticCurvePoint[] pubkeys))
Пример #3
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))