bitcoin-secp256k1 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07e0b24c6a5eff2bebfa1287f30299e3e20516a9
4
- data.tar.gz: 64b92f4a1274272b62a2b4f8447f7f97b3726e05
3
+ metadata.gz: 35c4817fc53d1512f07b574c444ac2ff39d723b7
4
+ data.tar.gz: 2c0acf62b066d43caf45ba96530b330ef8db2927
5
5
  SHA512:
6
- metadata.gz: f4123386a3b2add1c25e711eae40013a418fad7d614f0283caa0f5f8e961889de623be103b023035d441d42d4823b964ea129218d857ad66c722560b29f910f1
7
- data.tar.gz: 45abd20b35e91cbf4ac5b33fa3b472a32383f140426edce77eabab58180f39ea9afc4e63b85f4cfc6a59f257e6e1dfe6ed8bca1ac3199e8239dedae860ada7bb
6
+ metadata.gz: 4f831335807714f0cbd888e0adf8846293a3187ab7bde70306d61dce530947ab192b01770f6cfd43a1185c35417493c951af5dd08eb69ab8d63efc769f73d44f
7
+ data.tar.gz: 9e9b0e898a4db87c076921fbc50a4614ed411e2505a218d28380d8afc2ba18a261faa20ec84186c010376d4c2c28e87eb833b9fdab0c33f4ff5a82e0f82472eb
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bitcoin-secp256k1 (0.1.1)
4
+ bitcoin-secp256k1 (0.2.0)
5
5
  ffi (>= 1.9.10)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -17,7 +17,7 @@ git submodule update --init --recursive
17
17
  gem i bitcoin-secp256k1
18
18
  ```
19
19
 
20
- Then require 'secp256k1' (without `bitcoin-` prefix) in your source code.
20
+ Then `require 'secp256k1'` (without `bitcoin-` prefix) in your source code.
21
21
 
22
22
  ## Usage
23
23
 
data/lib/secp256k1/c.rb CHANGED
@@ -36,6 +36,9 @@ module Secp256k1
36
36
  # int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey)
37
37
  attach_function :secp256k1_ec_pubkey_create, [:pointer, :pointer, :pointer], :int
38
38
 
39
+ # int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags)
40
+ attach_function :secp256k1_ec_pubkey_serialize, [:pointer, :pointer, :pointer, :pointer, :uint], :int
41
+
39
42
  # int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey)
40
43
  attach_function :secp256k1_ec_seckey_verify, [:pointer, :pointer], :int
41
44
 
@@ -54,8 +57,25 @@ module Secp256k1
54
57
  # int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata)
55
58
  attach_function :secp256k1_ecdsa_sign, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int
56
59
 
60
+ # int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata)
61
+ attach_function :secp256k1_ecdsa_sign_recoverable, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int
62
+
63
+ # int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *msg32)
64
+ attach_function :secp256k1_ecdsa_recover, [:pointer, :pointer, :pointer, :pointer], :int
65
+
57
66
  # int secp256k1_ecdsa_verify(const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey)
58
67
  attach_function :secp256k1_ecdsa_verify, [:pointer, :pointer, :pointer, :pointer], :int
59
68
 
69
+ # int secp256k1_ecdsa_signature_normalize(const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin)
70
+ attach_function :secp256k1_ecdsa_signature_normalize, [:pointer, :pointer, :pointer], :int
71
+
72
+ # int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context *ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature *sig)
73
+ attach_function :secp256k1_ecdsa_recoverable_signature_serialize_compact, [:pointer, :pointer, :pointer, :pointer], :int
74
+
75
+ # int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context *ctx, secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *input64, int recid)
76
+ attach_function :secp256k1_ecdsa_recoverable_signature_parse_compact, [:pointer, :pointer, :pointer, :int], :int
77
+
78
+ # int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, const secp256k1_ecdsa_recoverable_signature *sigin)
79
+ attach_function :secp256k1_ecdsa_recoverable_signature_convert, [:pointer, :pointer, :pointer], :int
60
80
  end
61
81
  end
@@ -43,5 +43,59 @@ module Secp256k1
43
43
  raw_sig
44
44
  end
45
45
 
46
+ ##
47
+ # Check and optionally convert a signature to a normalized lower-S form. If
48
+ # check_only is `true` then the normalized signature is not returned.
49
+ #
50
+ # This function always return a tuple containing a boolean (`true` if not
51
+ # previously normalized or `false` if signature was already normalized),
52
+ # and the normalized signature. When check_only is `true`, the normalized
53
+ # signature returned is always `nil`.
54
+ #
55
+ def ecdsa_signature_normalize(raw_sig, check_only: false)
56
+ sigout = check_only ? nil : C::ECDSASignature.new.pointer
57
+ res = C.secp256k1_ecdsa_signature_normalize(@ctx, sigout, raw_sig)
58
+ [res == 1, sigout]
59
+ end
60
+
61
+ def ecdsa_recover(msg, recover_sig, raw: false, digest: Digest::SHA256)
62
+ raise AssertError, 'instance not configured for ecdsa recover' if (@flags & ALL_FLAGS) != ALL_FLAGS
63
+
64
+ msg32 = hash32 msg, raw, digest
65
+ pubkey = C::Pubkey.new.pointer
66
+
67
+ res = C.secp256k1_ecdsa_recover(@ctx, pubkey, recover_sig, msg32)
68
+ raise AssertError, 'failed to recover ECDSA public key' unless res == 1
69
+
70
+ pubkey
71
+ end
72
+
73
+ def ecdsa_recoverable_serialize(recover_sig)
74
+ output = FFI::MemoryPointer.new :uchar, SIZE_COMPACT
75
+ recid = FFI::MemoryPointer.new :int
76
+
77
+ C.secp256k1_ecdsa_recoverable_signature_serialize_compact(@ctx, output, recid, recover_sig)
78
+
79
+ [output.read_bytes(SIZE_COMPACT), recid.read_int]
80
+ end
81
+
82
+ def ecdsa_recoverable_deserialize(ser_sig, rec_id)
83
+ raise ArgumentError, 'invalid rec_id' if rec_id < 0 || rec_id > 3
84
+ raise ArgumentError, 'invalid signature length' if ser_sig.size != 64
85
+
86
+ recover_sig = C::ECDSARecoverableSignature.new.pointer
87
+
88
+ res = C.secp256k1_ecdsa_recoverable_signature_parse_compact(@ctx, recover_sig, ser_sig, rec_id)
89
+ raise AssertError, 'failed to parse ECDSA compact sig' unless res == 1
90
+
91
+ recover_sig
92
+ end
93
+
94
+ def ecdsa_recoverable_convert(recover_sig)
95
+ normal_sig = C::ECDSASignature.new.pointer
96
+ C.secp256k1_ecdsa_recoverable_signature_convert(@ctx, normal_sig, recover_sig)
97
+ normal_sig
98
+ end
99
+
46
100
  end
47
101
  end
data/lib/secp256k1/key.rb CHANGED
@@ -175,7 +175,7 @@ module Secp256k1
175
175
 
176
176
  def ecdsa_sign_recoverable(msg, raw: false, digest: Digest::SHA256)
177
177
  msg32 = hash32 msg, raw, digest
178
- raw_sig = FFI::MemoryPointer.new :byte, C::ECDSARecoverableSignature, false
178
+ raw_sig = C::ECDSARecoverableSignature.new.pointer
179
179
 
180
180
  res = C.secp256k1_ecdsa_sign_recoverable @ctx, raw_sig, msg32, @private_key, nil, nil
181
181
  raise AssertError, "failed to sign" unless res == 1
@@ -1,3 +1,3 @@
1
1
  module Secp256k1
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -7,6 +7,14 @@ require 'secp256k1'
7
7
 
8
8
  require 'json'
9
9
 
10
+ class MyECDSA < Secp256k1::BaseKey
11
+ include Secp256k1::Utils, Secp256k1::ECDSA
12
+
13
+ def initialize
14
+ super(nil, Secp256k1::ALL_FLAGS)
15
+ end
16
+ end
17
+
10
18
  class Secp256k1Test < Minitest::Test
11
19
  include Secp256k1
12
20
 
@@ -42,6 +50,50 @@ class Secp256k1Test < Minitest::Test
42
50
  assert_equal true, pk.pubkey.ecdsa_verify('test', sig_raw)
43
51
  end
44
52
 
53
+ def test_ecdsa_normalize
54
+ pk = PrivateKey.new
55
+ raw_sig = pk.ecdsa_sign 'hi'
56
+
57
+ had_to_normalize, normsig = pk.ecdsa_signature_normalize raw_sig
58
+ assert_equal false, had_to_normalize
59
+ assert_equal pk.ecdsa_serialize(raw_sig), pk.ecdsa_serialize(normsig)
60
+ assert_equal pk.ecdsa_serialize_compact(raw_sig), pk.ecdsa_serialize_compact(normsig)
61
+
62
+ had_to_normalize, normsig = pk.ecdsa_signature_normalize(raw_sig, check_only: true)
63
+ assert_equal false, had_to_normalize
64
+ assert_equal nil, normsig
65
+
66
+ sig = "\xAA" + "\xFF"*31 + "\xAA" + "\xFF"*31
67
+ raw_sig = pk.ecdsa_deserialize_compact sig
68
+
69
+ normalized, normsig = pk.ecdsa_signature_normalize raw_sig
70
+ assert_equal true, normalized
71
+ assert pk.ecdsa_serialize(raw_sig) != pk.ecdsa_serialize(normsig)
72
+
73
+ normalized, normsig = pk.ecdsa_signature_normalize raw_sig, check_only: true
74
+ assert_equal true, normalized
75
+ assert_equal nil, normsig
76
+ end
77
+
78
+ def test_ecdsa_recover
79
+ pk = PrivateKey.new
80
+ unrelated = MyECDSA.new
81
+
82
+ recsig = pk.ecdsa_sign_recoverable 'hello'
83
+ pubkey = unrelated.ecdsa_recover 'hello', recsig
84
+ pubser = PublicKey.new(pubkey: pubkey).serialize
85
+ assert_equal pubser, pk.pubkey.serialize
86
+
87
+ recsig_ser = unrelated.ecdsa_recoverable_serialize recsig
88
+ recsig2 = unrelated.ecdsa_recoverable_deserialize *recsig_ser
89
+ pubkey2 = unrelated.ecdsa_recover 'hello', recsig2
90
+ pubser2 = PublicKey.new(pubkey: pubkey2).serialize
91
+ assert_equal pubser, pubser2
92
+
93
+ raw_sig = unrelated.ecdsa_recoverable_convert recsig2
94
+ unrelated.ecdsa_deserialize(unrelated.ecdsa_serialize(raw_sig))
95
+ end
96
+
45
97
  private
46
98
 
47
99
  def ecdsa_sig
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitcoin-secp256k1
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Xie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-24 00:00:00.000000000 Z
11
+ date: 2016-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi