Module: Tapyrus::Secp256k1::Ruby

Defined in:
lib/tapyrus/secp256k1/ruby.rb

Overview

secp256 module using ecdsa gem github.com/DavidEGrayson/ruby_ecdsa

Class Method Summary collapse

Class Method Details

.generate_key(compressed: true) ⇒ Object

generate tapyrus key object



20
21
22
23
# File 'lib/tapyrus/secp256k1/ruby.rb', line 20

def generate_key(compressed: true)
  privkey, pubkey = generate_key_pair(compressed: compressed)
  Tapyrus::Key.new(priv_key: privkey, pubkey: pubkey, compressed: compressed)
end

.generate_key_pair(compressed: true) ⇒ Object

generate ec private key and public key



11
12
13
14
15
16
17
# File 'lib/tapyrus/secp256k1/ruby.rb', line 11

def generate_key_pair(compressed: true)
  private_key = 1 + SecureRandom.random_number(GROUP.order - 1)
  public_key = GROUP.generator.multiply_by_scalar(private_key)
  privkey = ECDSA::Format::IntegerOctetString.encode(private_key, 32)
  pubkey = public_key.to_hex(compressed)
  [privkey.bth, pubkey]
end

.generate_pubkey(privkey, compressed: true) ⇒ Object



25
26
27
28
# File 'lib/tapyrus/secp256k1/ruby.rb', line 25

def generate_pubkey(privkey, compressed: true)
  public_key = ECDSA::Group::Secp256k1.generator.multiply_by_scalar(privkey.to_i(16))
  public_key.to_hex(compressed)
end

.repack_pubkey(pubkey) ⇒ Object

if pubkey is hybrid public key format, it convert uncompressed format. lists.linuxfoundation.org/pipermail/bitcoin-dev/2012-June/001578.html



83
84
85
86
87
88
89
90
91
92
# File 'lib/tapyrus/secp256k1/ruby.rb', line 83

def repack_pubkey(pubkey)
  p = pubkey.htb
  case p[0]
    when "\x06", "\x07"
      p[0] = "\x04"
      p
    else
      pubkey.htb
  end
end

.sign_data(data, privkey, extra_entropy) ⇒ String

sign data.

Parameters:

  • data (String)

    a data to be signed with binary format

  • privkey (String)

    a private key using sign

Returns:

  • (String)

    signature data with binary format



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/tapyrus/secp256k1/ruby.rb', line 34

def sign_data(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)

  # port form ecdsa gem.
  r_point = GROUP.new_point(nonce)

  point_field = ECDSA::PrimeField.new(GROUP.order)
  r = point_field.mod(r_point.x)
  return nil if r.zero?

  e = ECDSA.normalize_digest(data, GROUP.bit_length)
  s = point_field.mod(point_field.inverse(nonce) * (e + r * private_key))

  if s > (GROUP.order / 2) # convert low-s
    s = GROUP.order - s
  end

  return nil if s.zero?

  signature = ECDSA::Signature.new(r, s).to_der
  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_sig(digest, sig, pubkey) ⇒ Boolean Also known as: valid_sig?

verify signature using public key

Parameters:

  • digest (String)

    a SHA-256 message digest with binary format

  • sig (String)

    a signature for data with binary format

  • pubkey (String)

    a public key corresponding to the private key used for sign

Returns:

  • (Boolean)

    verify result



67
68
69
70
71
72
73
74
75
# File 'lib/tapyrus/secp256k1/ruby.rb', line 67

def verify_sig(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