lib/tapyrus/secp256k1/ruby.rb in tapyrus-0.2.2 vs lib/tapyrus/secp256k1/ruby.rb in tapyrus-0.2.3

- old
+ new

@@ -29,11 +29,68 @@ # sign data. # @param [String] data a data to be signed with binary format # @param [String] privkey a private key using sign # @return [String] signature data with binary format - def sign_data(data, privkey, extra_entropy) + def sign_data(data, privkey, extra_entropy, algo: :ecdsa) + case algo + when :ecdsa + sign_ecdsa(data, privkey, extra_entropy) + when :schnorr + Schnorr.sign(data, privkey.to_i(16)).encode + else + nil + end + end + + # verify signature using public key + # @param [String] digest a SHA-256 message digest with binary format + # @param [String] sig a signature for +data+ with binary format + # @param [String] pubkey a public key corresponding to the private key used for sign + # @return [Boolean] verify result + def verify_sig(digest, sig, pubkey, algo: :ecdsa) + case algo + when :ecdsa + verify_ecdsa(digest, sig, pubkey) + when :schnorr + Schnorr.valid_sig?(digest, sig, pubkey.htb) + else + false + end + end + + alias :valid_sig? :verify_sig + + module_function :valid_sig? + + # validate whether this is a valid public key (more expensive than IsValid()) + # @param [String] pubkey public key with hex format. + # @param [Boolean] allow_hybrid whether support hybrid public key. + # @return [Boolean] If valid public key return true, otherwise false. + def parse_ec_pubkey?(pubkey, allow_hybrid = false) + begin + point = ECDSA::Format::PointOctetString.decode(pubkey.htb, ECDSA::Group::Secp256k1, allow_hybrid: allow_hybrid) + ECDSA::Group::Secp256k1.valid_public_key?(point) + rescue ECDSA::Format::DecodeError + false + end + end + + # if +pubkey+ is hybrid public key format, it convert uncompressed format. + # https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2012-June/001578.html + def repack_pubkey(pubkey) + p = pubkey.htb + case p[0] + when "\x06", "\x07" + p[0] = "\x04" + p + else + pubkey.htb + end + end + + def sign_ecdsa(data, privkey, extra_entropy) privkey = privkey.htb private_key = ECDSA::Format::IntegerOctetString.decode(privkey) extra_entropy ||= '' nonce = RFC6979.generate_rfc6979_nonce(privkey + data, extra_entropy) @@ -57,38 +114,16 @@ public_key = Tapyrus::Key.new(priv_key: privkey.bth).pubkey raise 'Creation of signature failed.' unless Tapyrus::Secp256k1::Ruby.verify_sig(data, signature, public_key) signature end - # verify signature using public key - # @param [String] digest a SHA-256 message digest with binary format - # @param [String] sig a signature for +data+ with binary format - # @param [String] pubkey a public key corresponding to the private key used for sign - # @return [Boolean] verify result - def verify_sig(digest, sig, pubkey) + def verify_ecdsa(digest, sig, pubkey) begin k = ECDSA::Format::PointOctetString.decode(repack_pubkey(pubkey), GROUP) signature = ECDSA::Format::SignatureDerString.decode(sig) ECDSA.valid_signature?(k, digest, signature) rescue Exception false - end - end - - alias :valid_sig? :verify_sig - - module_function :valid_sig? - - # if +pubkey+ is hybrid public key format, it convert uncompressed format. - # https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2012-June/001578.html - def repack_pubkey(pubkey) - p = pubkey.htb - case p[0] - when "\x06", "\x07" - p[0] = "\x04" - p - else - pubkey.htb end end end