/// <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))
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))