rbsecp256k1 3.0.1 → 4.0.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 +4 -4
- data/documentation/context.md +66 -0
- data/documentation/index.md +319 -0
- data/documentation/key_pair.md +28 -0
- data/documentation/private_key.md +25 -0
- data/documentation/public_key.md +32 -0
- data/documentation/recoverable_signature.md +30 -0
- data/documentation/secp256k1.md +19 -0
- data/documentation/shared_secret.md +16 -0
- data/documentation/signature.md +42 -0
- data/documentation/util.md +17 -0
- data/ext/rbsecp256k1/rbsecp256k1.c +160 -178
- data/lib/rbsecp256k1/version.rb +1 -1
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0bda0a3b5513e2716322c5bd47668b1fe17493ee6a542848d4d3add50cabd67
|
4
|
+
data.tar.gz: 45d1d8dccfa8303b5d750f270dd65331ae6c72948982863e430628cfe9ce2b9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 980d07a3fb920d7c873aca6969dc7102896379005e5a30741f637387fd43c06efdfddb09905e5c24a1dd1bb780211ebe9d46e3a8d16f02f95bf0a180cc6a7652
|
7
|
+
data.tar.gz: acb8d3284c484d946a5e22ebb4f4f2fb2c72f4e0e1e3b9bdb5b8beed2890283c361a14eda2453817401c0a8d98ace34219208f10d8997d98d21ef49766843d0c
|
@@ -0,0 +1,66 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::Context
|
4
|
+
==================
|
5
|
+
|
6
|
+
Secp256k1::Context represents a libsecp256k1 context object. Contexts are
|
7
|
+
thread-safe and initialization is expensive, so a single context should be used
|
8
|
+
for multiple operations as much as possible.
|
9
|
+
|
10
|
+
Initializers
|
11
|
+
------------
|
12
|
+
|
13
|
+
#### new
|
14
|
+
|
15
|
+
Returns a newly initialized libsecp256k1 context. The context is randomized at
|
16
|
+
initialization.
|
17
|
+
|
18
|
+
Instance Methods
|
19
|
+
----------------
|
20
|
+
|
21
|
+
#### ecdh(point, scalar)
|
22
|
+
|
23
|
+
**Requires:** libsecp256k1 was built with the experimental ECDH module.
|
24
|
+
|
25
|
+
Takes a `point` ([PublicKey](public_key.md)) and a `scalar` ([PrivateKey](private_key.md)) and returns a new
|
26
|
+
[SharedSecret](shared_secret.md) containing the 32-byte shared secret. Raises a `RuntimeError` if
|
27
|
+
the `scalar` is invalid (zero or causes an overflow).
|
28
|
+
|
29
|
+
#### generate_key_pair
|
30
|
+
|
31
|
+
Generates and returns a new [KeyPair](key_pair.md) using a cryptographically
|
32
|
+
secure random number generator (CSRNG) provided by OpenSSL.
|
33
|
+
|
34
|
+
#### key_pair_from_private_key(private_key_data)
|
35
|
+
|
36
|
+
Returns a new [KeyPair](key_pair.md) from the given `private_key_data`. The
|
37
|
+
`private_key_data` is expected to be a binary string. Raises a `RuntimeError`
|
38
|
+
if the private key is invalid or key derivation fails.
|
39
|
+
|
40
|
+
#### recoverable_signature_from_compact(compact_signature, recovery_id)
|
41
|
+
|
42
|
+
**Requires:** libsecp256k1 was build with recovery module.
|
43
|
+
|
44
|
+
Attempts to load a [RecoverableSignature](recoverable_signature.md) from the given `compact_signature`
|
45
|
+
and `recovery_id`. Raises a RuntimeError if the signature data or recovery ID are invalid.
|
46
|
+
|
47
|
+
#### sign(private_key, hash32)
|
48
|
+
|
49
|
+
Signs the SHA-256 hash given by `hash32` using `private_key` and returns a new
|
50
|
+
[Signature](signature.md). The `private_key` is expected to be a [PrivateKey](private_key.md)
|
51
|
+
object and `data` can be either a binary string or text.
|
52
|
+
|
53
|
+
#### sign_recoverable(private_key, hash32)
|
54
|
+
|
55
|
+
**Requires:** libsecp256k1 was build with recovery module.
|
56
|
+
|
57
|
+
Signs the data represented by the SHA-256 hash `hash32` using `private_key` and returns a
|
58
|
+
new [RecoverableSignature](recoverable_signature.md). The `private_key` is expected to be a [PrivateKey](private_key.md) and
|
59
|
+
`data` can be either a binary string or text.
|
60
|
+
|
61
|
+
#### verify(signature, public_key, hash32)
|
62
|
+
|
63
|
+
Verifies the given `signature` ([Signature](signature.md)) was signed by
|
64
|
+
the private key corresponding to `public_key` ([PublicKey](public_key.md)) and signed `hash32`. Returns `true`
|
65
|
+
if `signature` is valid or `false` otherwise. Note that `data` can be either a
|
66
|
+
text or binary string.
|
@@ -0,0 +1,319 @@
|
|
1
|
+
rbsecp256k1 Reference
|
2
|
+
=====================
|
3
|
+
|
4
|
+
Find your topic in the index, or refer to one of the examples below.
|
5
|
+
|
6
|
+
Classes and Modules
|
7
|
+
-------------------
|
8
|
+
|
9
|
+
| Module | Classes | Utilities
|
10
|
+
|----------------------------|:-------------------------------------------------|:--------------------------------
|
11
|
+
| [Secp256k1](secp256k1.md) | [Context](context.md) | [Util](util.md)
|
12
|
+
| | [KeyPair](key_pair.md) |
|
13
|
+
| | [PublicKey](public_key.md) |
|
14
|
+
| | [PrivateKey](private_key.md) |
|
15
|
+
| | [SharedSecret](shared_secret.md) |
|
16
|
+
| | [Signature](signature.md) |
|
17
|
+
| | [RecoverableSignature](recoverable_signature.md) |
|
18
|
+
|
19
|
+
Glossary
|
20
|
+
--------
|
21
|
+
|
22
|
+
**[Context](context.md)** is a libsecp256k1 library context. It contains
|
23
|
+
pre-computed tables and values to make ECDSA signing and verification more
|
24
|
+
efficient.
|
25
|
+
|
26
|
+
**[KeyPair](key_pair.md)** is a Secp256k1 elliptic-curve key pair.
|
27
|
+
|
28
|
+
**[PublicKey](public_key.md)** is a Secp256k1 public key. It can come in either
|
29
|
+
compressed or uncompressed format.
|
30
|
+
|
31
|
+
**[PrivateKey](private_key.md)** is a 64-byte Secp256k1 private key.
|
32
|
+
|
33
|
+
**[SharedSecret](shared_secret.md)** A 32-byte shared secret computed from a
|
34
|
+
public key (point) and private key (scalar).
|
35
|
+
|
36
|
+
**[Signature](signature.md)** is an ECDSA signature of the SHA-256 message hash
|
37
|
+
of a piece of data.
|
38
|
+
|
39
|
+
**[RecoverableSignature](recoverable_signature.md)** is a recoverable ECDSA signature of the SHA-256 message
|
40
|
+
hash of a piece of data.
|
41
|
+
|
42
|
+
Examples
|
43
|
+
--------
|
44
|
+
|
45
|
+
### 1. Creating a libsecp256k1 context
|
46
|
+
|
47
|
+
This example demonstrates how to create a new libsecp256k1 context. This is the
|
48
|
+
first step of using this library:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
context = Secp256k1::Context.new
|
52
|
+
# => #<Secp256k1::Context:0x0000559b0bd8f5d0>
|
53
|
+
```
|
54
|
+
|
55
|
+
### 2. Generating a key pair
|
56
|
+
|
57
|
+
This example shows how to generate a new public-private key pair:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
context = Secp256k1::Context.new
|
61
|
+
key_pair = context.generate_key_pair
|
62
|
+
# => #<Secp256k1::KeyPair:0x0000559b0bc876b0 @public_key=#<Secp256k1::PublicKey:0x0000559b0bc876d8>, @private_key=#<Secp256k1::PrivateKey:0x0000559b0bc87700 @data="\r\xA7\xB3<\x92\xCDw\xC1\xDB\xEB[BB;=\x80\xB83\xA8]\x06\xD9\x90\xF8v\xFFi\xF0/\x1E\x96\xF9">>
|
63
|
+
```
|
64
|
+
|
65
|
+
### 3. Getting compressed and uncompressed public key representations
|
66
|
+
|
67
|
+
This example shows how to generate compressed and uncompressed public keys:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
context = Secp256k1::Context.new
|
71
|
+
key_pair = context.generate_key_pair
|
72
|
+
|
73
|
+
# 1. Get the binary representation of compressed public key
|
74
|
+
key_pair.public_key.compressed
|
75
|
+
# => "\x03D\x88\xD6 3|3\x836\xCB(\x9CW%\xF4T\xB7\xCD\x8AF T\xE7\xE8\xCE\xB0\xC7c{\xE2:\xFE"
|
76
|
+
|
77
|
+
# 2. Show hex representation of compressed public key
|
78
|
+
Secp256k1::Util.bin_to_hex(key_pair.public_key.compressed)
|
79
|
+
# => "034488d620337c338336cb289c5725f454b7cd8a462054e7e8ceb0c7637be23afe"
|
80
|
+
|
81
|
+
# 3. Get the binary representation of uncompressed public key
|
82
|
+
key_pair.public_key.uncompressed
|
83
|
+
# => "\x04D\x88\xD6 3|3\x836\xCB(\x9CW%\xF4T\xB7\xCD\x8AF T\xE7\xE8\xCE\xB0\xC7c{\xE2:\xFE XRew\x1F\e\x05\xC8\xDC\xA7\xE3\x8C\xBD\x91s?\xFCW\xD5\xB3\xA8aaCCG\xD4\x94m\xA5c"
|
84
|
+
|
85
|
+
# 4. Show hex representation of uncompressed public key
|
86
|
+
Secp256k1::Util.bin_to_hex(key_pair.public_key.uncompressed)
|
87
|
+
# => "044488d620337c338336cb289c5725f454b7cd8a462054e7e8ceb0c7637be23afe20585265771f1b05c8dca7e38cbd91733ffc57d5b3a86161434347d4946da563"
|
88
|
+
```
|
89
|
+
|
90
|
+
### 3. Signing a message
|
91
|
+
|
92
|
+
This example shows how to sign a message using your private key:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
require 'digest'
|
96
|
+
|
97
|
+
context = Secp256k1::Context.new
|
98
|
+
key_pair = context.generate_key_pair
|
99
|
+
|
100
|
+
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
101
|
+
# => #<Secp256k1::Signature:0x0000559b0bc79358>
|
102
|
+
```
|
103
|
+
|
104
|
+
### 4. Getting DER and Compact signature encodings
|
105
|
+
|
106
|
+
This example shows you how to get the DER encoded and compact encoded
|
107
|
+
representations of a signature:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
require 'digest'
|
111
|
+
|
112
|
+
context = Secp256k1::Context.new
|
113
|
+
key_pair = context.generate_key_pair
|
114
|
+
|
115
|
+
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
116
|
+
|
117
|
+
# 1. Get the compact binary representation
|
118
|
+
signature.compact
|
119
|
+
# => "\xAB#e6_\x866\e\xAC\e\x92W\xC8a\x84N\xD4\xB6\x88\xF8\xEE\xDF\xFBC\xE8j\xB2\xF0\x10\xB8\xA0\x89\x13L\e\x9E\x91cB\xD7\xAC\x11\xF7\x02,Y&TM\xA5zp\xFD\xB3\xB1\xDCIV\xBB\\\xAF\x16@\xFC\x00"
|
120
|
+
|
121
|
+
# 2. Get the compact hex representation
|
122
|
+
Secp256k1::Util.bin_to_hex(signature.compact)
|
123
|
+
# => "ab2365365f86361bac1b9257c861844ed4b688f8eedffb43e86ab2f010b8a089134c1b9e916342d7ac11f7022c5926544da57a70fdb3b1dc4956bb5caf1640fc00"
|
124
|
+
|
125
|
+
# 3. Get the DER binary representation
|
126
|
+
signature.der_encoded
|
127
|
+
# => "0E\x02!\x00\xAB#e6_\x866\e\xAC\e\x92W\xC8a\x84N\xD4\xB6\x88\xF8\xEE\xDF\xFBC\xE8j\xB2\xF0\x10\xB8\xA0\x89\x02 \x13L\e\x9E\x91cB\xD7\xAC\x11\xF7\x02,Y&TM\xA5zp\xFD\xB3\xB1\xDCIV\xBB\\\xAF\x16@\xFC"
|
128
|
+
|
129
|
+
# 4. Get the DER hex representation
|
130
|
+
Secp256k1::Util.bin_to_hex(signature.der_encoded)
|
131
|
+
# => "3045022100ab2365365f86361bac1b9257c861844ed4b688f8eedffb43e86ab2f010b8a0890220134c1b9e916342d7ac11f7022c5926544da57a70fdb3b1dc4956bb5caf1640fc"
|
132
|
+
```
|
133
|
+
|
134
|
+
### 5. Verifying a signature
|
135
|
+
|
136
|
+
This example shows how to verify a signature using a public key:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
require 'digest'
|
140
|
+
|
141
|
+
context = Secp256k1::Context.new
|
142
|
+
key_pair = context.generate_key_pair
|
143
|
+
hash = Digest::SHA256.digest("test message")
|
144
|
+
|
145
|
+
signature = context.sign(key_pair.private_key, hash)
|
146
|
+
|
147
|
+
# 1. Verify signature against matching message
|
148
|
+
context.verify(signature, key_pair.public_key, hash)
|
149
|
+
# => true
|
150
|
+
|
151
|
+
# 2. Verify signature against different message
|
152
|
+
context.verify(signature, key_pair.public_key, hash)
|
153
|
+
# => false
|
154
|
+
```
|
155
|
+
|
156
|
+
### 6. Loading a private key or key pair from private key data
|
157
|
+
|
158
|
+
This example shows how to load a key pair from raw binary private key data:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
context = Secp256k1::Context.new
|
162
|
+
|
163
|
+
#1. Load private key alone
|
164
|
+
private_key = Secp256k1::PrivateKey.from_data("I\nX\x85\xAEz}\n\x9B\xA4\\\x81)\xD4\x9Aq\xFDH\t\xBE\x8EP\xC5.\xC6\x1F7-\x86\xA0\xCB\xF9")
|
165
|
+
# => #<Secp256k1::PrivateKey:0x00005647df1bcd30 @data="I\nX\x85\xAEz}\n\x9B\xA4\\\x81)\xD4\x9Aq\xFDH\t\xBE\x8EP\xC5.\xC6\x1F7-\x86\xA0\xCB\xF9">
|
166
|
+
|
167
|
+
# 2. Load key pair from private key data
|
168
|
+
key_pair = context.key_pair_from_private_key("I\nX\x85\xAEz}\n\x9B\xA4\\\x81)\xD4\x9Aq\xFDH\t\xBE\x8EP\xC5.\xC6\x1F7-\x86\xA0\xCB\xF9")
|
169
|
+
# => #<Secp256k1::KeyPair:0x0000559b0bbf9a90 @public_key=#<Secp256k1::PublicKey:0x0000559b0bbf9ab8>, @private_key=#<Secp256k1::PrivateKey:0x0000559b0bbf9ae0 @data="I\nX\x85\xAEz}\n\x9B\xA4\\\x81)Ԛq\xFDH\t\xBE\x8EP\xC5.\xC6\u001F7-\x86\xA0\xCB\xF9">>
|
170
|
+
```
|
171
|
+
|
172
|
+
### 7. Loading a public key from binary data
|
173
|
+
|
174
|
+
This example shows how to load a public key from binary data:
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
# 1. Load public key from uncompressed pubkey
|
178
|
+
public_key = Secp256k1::PublicKey.from_data("\x04$\xA2\xE7\xBB1\xC4|tN\xE6\xE4J-\xED\x9A[\xAFf-<\x14\x84^QQ\"\x14\xC3\x91\xE4\xF2\xB5\xEEEj\xAB\xD9\xFE\b\e7Zk\xC5{k\x12\xE3\xEA\xA2\xA5\xD7\xC1\xA5&\xE5|:K\xA9 X\xA3\x90")
|
179
|
+
# => #<Secp256k1::PublicKey:0x0000559b0bdc72f0>
|
180
|
+
|
181
|
+
# 2. Load public key from compressed pubkey
|
182
|
+
public_key = Secp256k1::PublicKey.from_data("\x02$\xA2\xE7\xBB1\xC4|tN\xE6\xE4J-\xED\x9A[\xAFf-<\x14\x84^QQ\"\x14\xC3\x91\xE4\xF2\xB5")
|
183
|
+
# => #<Secp256k1::PublicKey:0x0000559b0bdd3668>
|
184
|
+
```
|
185
|
+
|
186
|
+
### 8. Loading a DER or compact encoded signature
|
187
|
+
|
188
|
+
This example shows how to load signatures from binary data:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
# 1. From DER encoded signature
|
192
|
+
signature = Secp256k1::Signature.from_der_encoded("0D\x02 <\xC6\x7F/\x921l\x89Z\xFBs\x89p\xEE\x18u\x8B\x92\x9D\xA6\x84\xC5Y<t\xB7\xF1\f\xEE\f\x81J\x02 \t\"\xDF]\x1D\xA7W@^\xAAokH\b\x00\xE2L\xCF\x82\xA3\x05\x1E\x00\xF9\xFC\xB19\x0F\x93|\xB1f")
|
193
|
+
# => #<Secp256k1::Signature:0x0000559b0b823d58>
|
194
|
+
|
195
|
+
# 2. From compact signature
|
196
|
+
signature = Secp256k1::Signature.from_compact("<\xC6\x7F/\x921l\x89Z\xFBs\x89p\xEE\x18u\x8B\x92\x9D\xA6\x84\xC5Y<t\xB7\xF1\f\xEE\f\x81J\t\"\xDF]\x1D\xA7W@^\xAAokH\b\x00\xE2L\xCF\x82\xA3\x05\x1E\x00\xF9\xFC\xB19\x0F\x93|\xB1f\x00")
|
197
|
+
# => #<Secp256k1::Signature:0x0000559b0bdcaa68>
|
198
|
+
```
|
199
|
+
|
200
|
+
Recoverable Signature Examples
|
201
|
+
------------------------------
|
202
|
+
|
203
|
+
### 1. Checking for recovery module
|
204
|
+
|
205
|
+
To check if you have compiled the recovery module into your local libsecp256k1
|
206
|
+
run the following:
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
Secp256k1.have_recovery?
|
210
|
+
# => true
|
211
|
+
```
|
212
|
+
|
213
|
+
### 2. Sign data producing recoverable signature
|
214
|
+
|
215
|
+
You can sign data producing a recoverable signature as follows:
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
require 'digest'
|
219
|
+
|
220
|
+
hash = Digest::SHA256.digest('test message')
|
221
|
+
context = Secp256k1::Context.new
|
222
|
+
key_pair = context.generate_key_pair
|
223
|
+
|
224
|
+
signature = context.sign_recoverable(key_pair.private_key, hash)
|
225
|
+
# => #<Secp256k1::RecoverableSignature:0x000055f2ea76e548>
|
226
|
+
```
|
227
|
+
|
228
|
+
### 3. Serialize recoverable signature as compact representation
|
229
|
+
|
230
|
+
You can produce the compact binary serialization of a recoverable signature:
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
require 'digest'
|
234
|
+
|
235
|
+
hash = Digest::SHA256.digest('test message')
|
236
|
+
context = Secp256k1::Context.new
|
237
|
+
key_pair = context.generate_key_pair
|
238
|
+
|
239
|
+
signature = context.sign_recoverable(key_pair.private_key, hash)
|
240
|
+
compact_data, recovery_id = signature.compact
|
241
|
+
# => ["D,\x9C\xA6%I\x14-\xCA\xC0\x11\x0F\xEB\x1E\xB0\xB6\\-\xE2\b\x98\xFB\xEA\xD5\x9BZ\xE6\xDF#\xC1\x1A\xEEL\xF02\xB1\xE9{\r\xEBhh<\\\xCF\xB6\x98\xEA\x8F\xF65\xF2\xBF\x84\xD8\xE5x\xF0\xA5)\xA2Wb\x9D", 1]
|
242
|
+
```
|
243
|
+
|
244
|
+
### 4. Recoverable signature from compact representation
|
245
|
+
|
246
|
+
You can load a recoverable signature give its compact representation and
|
247
|
+
recovery ID:
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
context = Secp256k1::Context.new
|
251
|
+
|
252
|
+
compact_data = "D,\x9C\xA6%I\x14-\xCA\xC0\x11\x0F\xEB\x1E\xB0\xB6\\-\xE2\b\x98\xFB\xEA\xD5\x9BZ\xE6\xDF#\xC1\x1A\xEEL\xF02\xB1\xE9{\r\xEBhh<\\\xCF\xB6\x98\xEA\x8F\xF65\xF2\xBF\x84\xD8\xE5x\xF0\xA5)\xA2Wb\x9D"
|
253
|
+
recovery_id = 1
|
254
|
+
|
255
|
+
signature = context.recoverable_signature_from_compact(compact_data, recovery_id)
|
256
|
+
# => #<Secp256k1::RecoverableSignature:0x000055f2ea7615c8>
|
257
|
+
```
|
258
|
+
|
259
|
+
### 5. Convert recoverable signature to non-recoverable signature
|
260
|
+
|
261
|
+
You can convert a recoverable signature to a non-recoverable signature suitable
|
262
|
+
for use by all methods that take a [Signature](signature.md) object:
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
require 'digest'
|
266
|
+
|
267
|
+
hash = Digest::SHA256.digest('test message')
|
268
|
+
context = Secp256k1::Context.new
|
269
|
+
key_pair = context.generate_key_pair
|
270
|
+
|
271
|
+
recoverable_signature = context.sign_recoverable(key_pair.private_key, hash)
|
272
|
+
signature = recoverable_signature.to_signature
|
273
|
+
# => #<Secp256k1::Signature:0x000055f2ea8ca4f0>
|
274
|
+
```
|
275
|
+
|
276
|
+
### 6. Recover public key from recoverable signature
|
277
|
+
|
278
|
+
You can recover the [PublicKey](public_key.md) associated with a recoverable signature:
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
require 'digest'
|
282
|
+
|
283
|
+
hash = Digest::SHA256.digest('test message')
|
284
|
+
context = Secp256k1::Context.new
|
285
|
+
key_pair = context.generate_key_pair
|
286
|
+
|
287
|
+
recoverable_signature = context.sign_recoverable(key_pair.private_key, hash)
|
288
|
+
public_key = recoverable_signature.recover_public_key(hash)
|
289
|
+
# => #<Secp256k1::PublicKey:0x000055f2ea756678>
|
290
|
+
|
291
|
+
public_key == key_pair.public_key
|
292
|
+
# => true
|
293
|
+
```
|
294
|
+
|
295
|
+
EC Diffie-Hellman
|
296
|
+
-----------------
|
297
|
+
|
298
|
+
### 1. Checking for ECDH module
|
299
|
+
|
300
|
+
To check if you have compiled the ECDH module into your local libsecp256k1 run
|
301
|
+
the following:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
Secp256k1.have_ecdh?
|
305
|
+
# => true
|
306
|
+
```
|
307
|
+
|
308
|
+
### 2. Generating a shared secret
|
309
|
+
|
310
|
+
To generate a shared secret run the following:
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
context = Secp256k1::Context.new
|
314
|
+
key_pair = context.generate_key_pair
|
315
|
+
|
316
|
+
shared_secret = context.ecdh(key_pair.public_key, key_pair.private_key)
|
317
|
+
shared_secret.data
|
318
|
+
# => "\x1FQ\x90X\xA5\xF2\xAEx;\xD7i\xB6\\T,2[\x90\xD1)a$\x1CA\x17\x8F\e\x91\xE3\x06C\x93"
|
319
|
+
```
|
@@ -0,0 +1,28 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::KeyPair
|
4
|
+
==================
|
5
|
+
|
6
|
+
Secp256k1::KeyPair represents a public-private Secp256k1 key pair.
|
7
|
+
|
8
|
+
Initializers
|
9
|
+
------------
|
10
|
+
|
11
|
+
#### new(public_key, private_key)
|
12
|
+
|
13
|
+
Initializes a new key pair with `public_key` (type: [PublicKey](public_key.md)) and `private_key` (type: [PrivateKey](private_key.md)).
|
14
|
+
|
15
|
+
Instance Methods
|
16
|
+
----------------
|
17
|
+
|
18
|
+
#### public_key
|
19
|
+
|
20
|
+
Returns the [PublicKey](public_key.md) part of this key pair.
|
21
|
+
|
22
|
+
#### private_key
|
23
|
+
|
24
|
+
Returns the [PrivateKey](private_key.md) part of this key pair.
|
25
|
+
|
26
|
+
#### ==(other)
|
27
|
+
|
28
|
+
Returns `true` if the `other` has the same public and private key.
|
@@ -0,0 +1,25 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::PrivateKey
|
4
|
+
=====================
|
5
|
+
|
6
|
+
Secp256k1::PrivateKey represents the private key part of a public-private key pair.
|
7
|
+
|
8
|
+
Class Methods
|
9
|
+
-------------
|
10
|
+
|
11
|
+
#### from_data(private_key_data)
|
12
|
+
|
13
|
+
Loads new private key from the given binary `private_key_data` string. Raises
|
14
|
+
`ArgumentError` if the given data is invalid.
|
15
|
+
|
16
|
+
Instance Methods
|
17
|
+
----------------
|
18
|
+
|
19
|
+
#### data
|
20
|
+
|
21
|
+
Returns the binary private key data as a `String`.
|
22
|
+
|
23
|
+
#### ==(other)
|
24
|
+
|
25
|
+
Returns `true` if this private key matches `other`.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::PublicKey
|
4
|
+
====================
|
5
|
+
|
6
|
+
Secp256k1::PublicKey represents the public key part of a public-private key pair.
|
7
|
+
|
8
|
+
See: [KeyPair](key_pair.md)
|
9
|
+
|
10
|
+
Class Methods
|
11
|
+
-------------
|
12
|
+
|
13
|
+
#### from_data(public_key_data)
|
14
|
+
|
15
|
+
Parses compressed or uncompressed from binary string `public_key_data` and
|
16
|
+
creates and returns a new public key from it. Raises a `RuntimeError` if the
|
17
|
+
given public key data is invalid.
|
18
|
+
|
19
|
+
Instance Methods
|
20
|
+
----------------
|
21
|
+
|
22
|
+
#### compressed
|
23
|
+
|
24
|
+
Returns the binary compressed representation of this public key.
|
25
|
+
|
26
|
+
#### uncompressed
|
27
|
+
|
28
|
+
Returns the binary uncompressed representation of this public key.
|
29
|
+
|
30
|
+
#### ==(other)
|
31
|
+
|
32
|
+
Return `true` if this public key matches `other`.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::RecoverableSignature
|
4
|
+
===============================
|
5
|
+
|
6
|
+
**Requires:** libsecp256k1 was build with recovery module.
|
7
|
+
|
8
|
+
Secp256k1::RecoverableSignature represents a recoverable ECDSA signature
|
9
|
+
signing the 32-byte SHA-256 hash of some data.
|
10
|
+
|
11
|
+
Instance Methods
|
12
|
+
----------------
|
13
|
+
|
14
|
+
#### compact
|
15
|
+
|
16
|
+
Returns an array whose first element is the 64-byte compact signature as a
|
17
|
+
binary string and whose second element is the integer recovery ID.
|
18
|
+
|
19
|
+
#### recover_public_key
|
20
|
+
|
21
|
+
Recovers the public key corresponding to the recoverable signature. Returns a
|
22
|
+
[PublicKey](public_key.md).
|
23
|
+
|
24
|
+
#### to_signature
|
25
|
+
|
26
|
+
Converts a recoverable signature to a non-recoverable [Signature](signature.md) object.
|
27
|
+
|
28
|
+
#### ==(other)
|
29
|
+
|
30
|
+
Returns `true` if this recoverable signature matches `other`.
|
@@ -0,0 +1,19 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1
|
4
|
+
=========
|
5
|
+
|
6
|
+
Secp256k1 is the top-level module for this library.
|
7
|
+
|
8
|
+
Class Methods
|
9
|
+
-------------
|
10
|
+
|
11
|
+
#### have_recovery?
|
12
|
+
|
13
|
+
Returns `true` if the recovery module was built with libsecp256k1, `false`
|
14
|
+
otherwise.
|
15
|
+
|
16
|
+
#### have_ecdh?
|
17
|
+
|
18
|
+
Returns `true` if the EC Diffie-Hellman module was built with libsecp256k1,
|
19
|
+
`false` otherwise.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::SharedSecret
|
4
|
+
=======================
|
5
|
+
|
6
|
+
**Requires:** libsecp256k1 was build with ECDH module.
|
7
|
+
|
8
|
+
Secp256k1::SharedSecret represents a 32-byte shared secret computed from a
|
9
|
+
public key (point) and private key (scalar).
|
10
|
+
|
11
|
+
Instance Methods
|
12
|
+
----------------
|
13
|
+
|
14
|
+
#### data
|
15
|
+
|
16
|
+
Binary string containing the 32-byte shared secret.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::Signature
|
4
|
+
====================
|
5
|
+
|
6
|
+
Secp256k1::Signature represents an ECDSA signature signing the 32-byte SHA-256
|
7
|
+
hash of some data.
|
8
|
+
|
9
|
+
Class Methods
|
10
|
+
-------------
|
11
|
+
|
12
|
+
#### from_compact(compact_signature)
|
13
|
+
|
14
|
+
Parses a signature from binary string `compact_signature`. Raises a
|
15
|
+
`RuntimeError` ig the signature data is invalid.
|
16
|
+
|
17
|
+
#### from_der_encoded(der_encoded_signature)
|
18
|
+
|
19
|
+
Parses a signature from binary string `der_encoded_signature`. Raises a
|
20
|
+
`RuntimeError` ig the signature data is invalid.
|
21
|
+
|
22
|
+
Instance Methods
|
23
|
+
----------------
|
24
|
+
|
25
|
+
#### der_encoded
|
26
|
+
|
27
|
+
Returns the DER encoded representation of this signature.
|
28
|
+
|
29
|
+
#### compact
|
30
|
+
|
31
|
+
Returns the compact 64-byte representation of this signature.
|
32
|
+
|
33
|
+
#### normalized
|
34
|
+
|
35
|
+
Returns an array containing two elements. The first is a Boolean indicating
|
36
|
+
whether or not the signature was normalized, false if it was already in lower-S
|
37
|
+
normal form. The second element is a `Signature` containing the normalized
|
38
|
+
signature object.
|
39
|
+
|
40
|
+
#### ==(other)
|
41
|
+
|
42
|
+
Returns `true` if this signature matches `other`.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
[Index](index.md)
|
2
|
+
|
3
|
+
Secp256k1::Util
|
4
|
+
===============
|
5
|
+
|
6
|
+
Secp256k1::Util in a module containing generally useful methods for using the library.
|
7
|
+
|
8
|
+
Class Methods
|
9
|
+
-------------
|
10
|
+
|
11
|
+
#### bin_to_hex(binary_data)
|
12
|
+
|
13
|
+
Returns the hexadecimal string representation of `binary_data`
|
14
|
+
|
15
|
+
#### hex_to_bin(hex_string)
|
16
|
+
|
17
|
+
Returns the binary string representation of `hex_string`
|
@@ -87,17 +87,14 @@ typedef struct KeyPair_dummy {
|
|
87
87
|
|
88
88
|
typedef struct PublicKey_dummy {
|
89
89
|
secp256k1_pubkey pubkey; // Opaque object containing public key data
|
90
|
-
secp256k1_context *ctx;
|
91
90
|
} PublicKey;
|
92
91
|
|
93
92
|
typedef struct PrivateKey_dummy {
|
94
93
|
unsigned char data[32]; // Bytes comprising the private key data
|
95
|
-
secp256k1_context *ctx;
|
96
94
|
} PrivateKey;
|
97
95
|
|
98
96
|
typedef struct Signature_dummy {
|
99
97
|
secp256k1_ecdsa_signature sig; // Signature object, contains 64-byte signature
|
100
|
-
secp256k1_context *ctx;
|
101
98
|
} Signature;
|
102
99
|
|
103
100
|
#ifdef HAVE_SECP256K1_RECOVERY_H
|
@@ -140,7 +137,6 @@ PublicKey_free(void *in_public_key)
|
|
140
137
|
{
|
141
138
|
PublicKey *public_key;
|
142
139
|
public_key = (PublicKey*)in_public_key;
|
143
|
-
secp256k1_context_destroy(public_key->ctx);
|
144
140
|
xfree(public_key);
|
145
141
|
}
|
146
142
|
|
@@ -157,7 +153,6 @@ PrivateKey_free(void *in_private_key)
|
|
157
153
|
{
|
158
154
|
PrivateKey *private_key;
|
159
155
|
private_key = (PrivateKey*)in_private_key;
|
160
|
-
secp256k1_context_destroy(private_key->ctx);
|
161
156
|
xfree(private_key);
|
162
157
|
}
|
163
158
|
|
@@ -197,7 +192,6 @@ static void
|
|
197
192
|
Signature_free(void *in_signature)
|
198
193
|
{
|
199
194
|
Signature *signature = (Signature*)in_signature;
|
200
|
-
secp256k1_context_destroy(signature->ctx);
|
201
195
|
xfree(signature);
|
202
196
|
}
|
203
197
|
|
@@ -471,13 +465,11 @@ PublicKey_create_from_private_key(Context *in_context,
|
|
471
465
|
rb_raise(rb_eTypeError, "invalid private key data");
|
472
466
|
}
|
473
467
|
|
474
|
-
public_key->ctx = secp256k1_context_clone(in_context->ctx);
|
475
468
|
return result;
|
476
469
|
}
|
477
470
|
|
478
471
|
static VALUE
|
479
|
-
PublicKey_create_from_data(
|
480
|
-
unsigned char *in_public_key_data,
|
472
|
+
PublicKey_create_from_data(unsigned char *in_public_key_data,
|
481
473
|
unsigned int in_public_key_data_len)
|
482
474
|
{
|
483
475
|
PublicKey *public_key;
|
@@ -486,7 +478,7 @@ PublicKey_create_from_data(Context *in_context,
|
|
486
478
|
result = PublicKey_alloc(Secp256k1_PublicKey_class);
|
487
479
|
TypedData_Get_Struct(result, PublicKey, &PublicKey_DataType, public_key);
|
488
480
|
|
489
|
-
if (secp256k1_ec_pubkey_parse(
|
481
|
+
if (secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp,
|
490
482
|
&(public_key->pubkey),
|
491
483
|
in_public_key_data,
|
492
484
|
in_public_key_data_len) != 1)
|
@@ -494,10 +486,31 @@ PublicKey_create_from_data(Context *in_context,
|
|
494
486
|
rb_raise(rb_eRuntimeError, "invalid public key data");
|
495
487
|
}
|
496
488
|
|
497
|
-
public_key->ctx = secp256k1_context_clone(in_context->ctx);
|
498
489
|
return result;
|
499
490
|
}
|
500
491
|
|
492
|
+
/**
|
493
|
+
* Loads a public key from compressed or uncompressed binary data.
|
494
|
+
*
|
495
|
+
* @param in_public_key_data [String] binary string with compressed or
|
496
|
+
* uncompressed public key data.
|
497
|
+
* @return [Secp256k1::PublicKey] public key derived from data.
|
498
|
+
* @raise [RuntimeError] if public key data is invalid.
|
499
|
+
*/
|
500
|
+
static VALUE
|
501
|
+
PublicKey_from_data(VALUE klass, VALUE in_public_key_data)
|
502
|
+
{
|
503
|
+
unsigned char *public_key_data;
|
504
|
+
|
505
|
+
Check_Type(in_public_key_data, T_STRING);
|
506
|
+
|
507
|
+
public_key_data = (unsigned char*)StringValuePtr(in_public_key_data);
|
508
|
+
return PublicKey_create_from_data(
|
509
|
+
public_key_data,
|
510
|
+
(int)RSTRING_LEN(in_public_key_data)
|
511
|
+
);
|
512
|
+
}
|
513
|
+
|
501
514
|
/**
|
502
515
|
* @return [String] binary string containing the uncompressed representation
|
503
516
|
* of this public key.
|
@@ -512,7 +525,7 @@ PublicKey_uncompressed(VALUE self)
|
|
512
525
|
|
513
526
|
TypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
514
527
|
|
515
|
-
secp256k1_ec_pubkey_serialize(
|
528
|
+
secp256k1_ec_pubkey_serialize(secp256k1_context_no_precomp,
|
516
529
|
serialized_pubkey,
|
517
530
|
&serialized_pubkey_len,
|
518
531
|
&(public_key->pubkey),
|
@@ -535,7 +548,7 @@ PublicKey_compressed(VALUE self)
|
|
535
548
|
|
536
549
|
TypedData_Get_Struct(self, PublicKey, &PublicKey_DataType, public_key);
|
537
550
|
|
538
|
-
secp256k1_ec_pubkey_serialize(
|
551
|
+
secp256k1_ec_pubkey_serialize(secp256k1_context_no_precomp,
|
539
552
|
serialized_pubkey,
|
540
553
|
&serialized_pubkey_len,
|
541
554
|
&(public_key->pubkey),
|
@@ -569,14 +582,14 @@ PublicKey_equals(VALUE self, VALUE other)
|
|
569
582
|
TypedData_Get_Struct(other, PublicKey, &PublicKey_DataType, rhs);
|
570
583
|
|
571
584
|
secp256k1_ec_pubkey_serialize(
|
572
|
-
|
585
|
+
secp256k1_context_no_precomp,
|
573
586
|
lhs_compressed,
|
574
587
|
&lhs_len,
|
575
588
|
&(lhs->pubkey),
|
576
589
|
SECP256K1_EC_COMPRESSED
|
577
590
|
);
|
578
591
|
secp256k1_ec_pubkey_serialize(
|
579
|
-
|
592
|
+
secp256k1_context_no_precomp,
|
580
593
|
rhs_compressed,
|
581
594
|
&rhs_len,
|
582
595
|
&(rhs->pubkey),
|
@@ -610,12 +623,13 @@ PrivateKey_alloc(VALUE klass)
|
|
610
623
|
}
|
611
624
|
|
612
625
|
static VALUE
|
613
|
-
PrivateKey_create(
|
626
|
+
PrivateKey_create(unsigned char *in_private_key_data)
|
614
627
|
{
|
615
628
|
PrivateKey *private_key;
|
616
629
|
VALUE result;
|
617
630
|
|
618
|
-
if (secp256k1_ec_seckey_verify(
|
631
|
+
if (secp256k1_ec_seckey_verify(secp256k1_context_no_precomp,
|
632
|
+
in_private_key_data) != 1)
|
619
633
|
{
|
620
634
|
rb_raise(rb_eArgError, "invalid private key data");
|
621
635
|
}
|
@@ -623,13 +637,35 @@ PrivateKey_create(Context *in_context, unsigned char *in_private_key_data)
|
|
623
637
|
result = PrivateKey_alloc(Secp256k1_PrivateKey_class);
|
624
638
|
TypedData_Get_Struct(result, PrivateKey, &PrivateKey_DataType, private_key);
|
625
639
|
MEMCPY(private_key->data, in_private_key_data, char, 32);
|
626
|
-
private_key->ctx = secp256k1_context_clone(in_context->ctx);
|
627
640
|
|
628
641
|
rb_iv_set(result, "@data", rb_str_new((char*)in_private_key_data, 32));
|
629
642
|
|
630
643
|
return result;
|
631
644
|
}
|
632
645
|
|
646
|
+
/**
|
647
|
+
* Load a private key from binary data.
|
648
|
+
*
|
649
|
+
* @param in_private_key_data [String] 32 byte binary string of private key
|
650
|
+
* data.
|
651
|
+
* @return [Secp256k1::PrivateKey] private key loaded from the given data.
|
652
|
+
* @raise [ArgumentError] if private key data is not 32 bytes or is invalid.
|
653
|
+
*/
|
654
|
+
static VALUE
|
655
|
+
PrivateKey_from_data(VALUE klass, VALUE in_private_key_data)
|
656
|
+
{
|
657
|
+
unsigned char *private_key_data;
|
658
|
+
|
659
|
+
Check_Type(in_private_key_data, T_STRING);
|
660
|
+
if (RSTRING_LEN(in_private_key_data) != 32)
|
661
|
+
{
|
662
|
+
rb_raise(rb_eArgError, "private key data must be 32 bytes in length");
|
663
|
+
}
|
664
|
+
|
665
|
+
private_key_data = (unsigned char*)StringValuePtr(in_private_key_data);
|
666
|
+
return PrivateKey_create(private_key_data);
|
667
|
+
}
|
668
|
+
|
633
669
|
/**
|
634
670
|
* Compare two private keys.
|
635
671
|
*
|
@@ -672,6 +708,77 @@ Signature_alloc(VALUE klass)
|
|
672
708
|
return new_instance;
|
673
709
|
}
|
674
710
|
|
711
|
+
/**
|
712
|
+
* Deserializes a Signature from 64-byte compact signature data.
|
713
|
+
*
|
714
|
+
* @param in_compact_signature [String] compact signature as 64-byte binary
|
715
|
+
* string.
|
716
|
+
* @return [Secp256k1::Signature] object deserialized from compact signature.
|
717
|
+
* @raise [ArgumentError] if signature data is invalid.
|
718
|
+
*/
|
719
|
+
static VALUE
|
720
|
+
Signature_from_compact(VALUE klass, VALUE in_compact_signature)
|
721
|
+
{
|
722
|
+
Signature *signature;
|
723
|
+
VALUE signature_result;
|
724
|
+
unsigned char *signature_data;
|
725
|
+
|
726
|
+
Check_Type(in_compact_signature, T_STRING);
|
727
|
+
|
728
|
+
if (RSTRING_LEN(in_compact_signature) != 64)
|
729
|
+
{
|
730
|
+
rb_raise(rb_eArgError, "compact signature must be 64 bytes");
|
731
|
+
}
|
732
|
+
|
733
|
+
signature_data = (unsigned char*)StringValuePtr(in_compact_signature);
|
734
|
+
|
735
|
+
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
736
|
+
TypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
737
|
+
|
738
|
+
if (secp256k1_ecdsa_signature_parse_compact(secp256k1_context_no_precomp,
|
739
|
+
&(signature->sig),
|
740
|
+
signature_data) != 1)
|
741
|
+
{
|
742
|
+
rb_raise(rb_eArgError, "invalid compact signature");
|
743
|
+
}
|
744
|
+
|
745
|
+
return signature_result;
|
746
|
+
}
|
747
|
+
|
748
|
+
/**
|
749
|
+
* Converts a DER encoded binary signature into a signature object.
|
750
|
+
*
|
751
|
+
* @param in_der_encoded_signature [String] DER encoded signature as binary
|
752
|
+
* string.
|
753
|
+
* @return [Secp256k1::Signature] signature object initialized using signature
|
754
|
+
* data.
|
755
|
+
* @raise [ArgumentError] if signature data is invalid.
|
756
|
+
*/
|
757
|
+
static VALUE
|
758
|
+
Signature_from_der_encoded(VALUE klass, VALUE in_der_encoded_signature)
|
759
|
+
{
|
760
|
+
Signature *signature;
|
761
|
+
VALUE signature_result;
|
762
|
+
unsigned char *signature_data;
|
763
|
+
|
764
|
+
Check_Type(in_der_encoded_signature, T_STRING);
|
765
|
+
|
766
|
+
signature_data = (unsigned char*)StringValuePtr(in_der_encoded_signature);
|
767
|
+
|
768
|
+
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
769
|
+
TypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
770
|
+
|
771
|
+
if (secp256k1_ecdsa_signature_parse_der(secp256k1_context_no_precomp,
|
772
|
+
&(signature->sig),
|
773
|
+
signature_data,
|
774
|
+
RSTRING_LEN(in_der_encoded_signature)) != 1)
|
775
|
+
{
|
776
|
+
rb_raise(rb_eArgError, "invalid DER encoded signature");
|
777
|
+
}
|
778
|
+
|
779
|
+
return signature_result;
|
780
|
+
}
|
781
|
+
|
675
782
|
/**
|
676
783
|
* Return Distinguished Encoding Rules (DER) encoded signature data.
|
677
784
|
*
|
@@ -688,7 +795,7 @@ Signature_der_encoded(VALUE self)
|
|
688
795
|
TypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
689
796
|
|
690
797
|
der_signature_len = 72;
|
691
|
-
if (secp256k1_ecdsa_signature_serialize_der(
|
798
|
+
if (secp256k1_ecdsa_signature_serialize_der(secp256k1_context_no_precomp,
|
692
799
|
der_signature,
|
693
800
|
&der_signature_len,
|
694
801
|
&(signature->sig)) != 1)
|
@@ -713,7 +820,7 @@ Signature_compact(VALUE self)
|
|
713
820
|
|
714
821
|
TypedData_Get_Struct(self, Signature, &Signature_DataType, signature);
|
715
822
|
|
716
|
-
if (secp256k1_ecdsa_signature_serialize_compact(
|
823
|
+
if (secp256k1_ecdsa_signature_serialize_compact(secp256k1_context_no_precomp,
|
717
824
|
compact_signature,
|
718
825
|
&(signature->sig)) != 1)
|
719
826
|
{
|
@@ -751,15 +858,13 @@ Signature_normalized(VALUE self)
|
|
751
858
|
|
752
859
|
was_normalized = Qfalse;
|
753
860
|
if (secp256k1_ecdsa_signature_normalize(
|
754
|
-
|
861
|
+
secp256k1_context_no_precomp,
|
755
862
|
&(normalized_signature->sig),
|
756
863
|
&(signature->sig)) == 1)
|
757
864
|
{
|
758
865
|
was_normalized = Qtrue;
|
759
866
|
}
|
760
867
|
|
761
|
-
normalized_signature->ctx = secp256k1_context_clone(signature->ctx);
|
762
|
-
|
763
868
|
result = rb_ary_new2(2);
|
764
869
|
rb_ary_push(result, was_normalized);
|
765
870
|
rb_ary_push(result, result_sig);
|
@@ -787,10 +892,10 @@ Signature_equals(VALUE self, VALUE other)
|
|
787
892
|
TypedData_Get_Struct(other, Signature, &Signature_DataType, rhs);
|
788
893
|
|
789
894
|
secp256k1_ecdsa_signature_serialize_compact(
|
790
|
-
|
895
|
+
secp256k1_context_no_precomp, lhs_compact, &(lhs->sig)
|
791
896
|
);
|
792
897
|
secp256k1_ecdsa_signature_serialize_compact(
|
793
|
-
|
898
|
+
secp256k1_context_no_precomp, rhs_compact, &(rhs->sig)
|
794
899
|
);
|
795
900
|
|
796
901
|
if (memcmp(lhs_compact, rhs_compact, 64) == 0)
|
@@ -845,7 +950,7 @@ RecoverableSignature_compact(VALUE self)
|
|
845
950
|
);
|
846
951
|
|
847
952
|
if (secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
848
|
-
|
953
|
+
secp256k1_context_no_precomp,
|
849
954
|
compact_sig,
|
850
955
|
&recovery_id,
|
851
956
|
&(recoverable_signature->sig)) != 1)
|
@@ -891,11 +996,10 @@ RecoverableSignature_to_signature(VALUE self)
|
|
891
996
|
|
892
997
|
// NOTE: This method cannot fail
|
893
998
|
secp256k1_ecdsa_recoverable_signature_convert(
|
894
|
-
|
999
|
+
secp256k1_context_no_precomp,
|
895
1000
|
&(signature->sig),
|
896
1001
|
&(recoverable_signature->sig));
|
897
1002
|
|
898
|
-
signature->ctx = secp256k1_context_clone(recoverable_signature->ctx);
|
899
1003
|
return result;
|
900
1004
|
}
|
901
1005
|
|
@@ -936,7 +1040,6 @@ RecoverableSignature_recover_public_key(VALUE self, VALUE in_hash32)
|
|
936
1040
|
&(recoverable_signature->sig),
|
937
1041
|
hash32) == 1)
|
938
1042
|
{
|
939
|
-
public_key->ctx = secp256k1_context_clone(recoverable_signature->ctx);
|
940
1043
|
return result;
|
941
1044
|
}
|
942
1045
|
|
@@ -1076,7 +1179,7 @@ Context_generate_key_pair(VALUE self)
|
|
1076
1179
|
|
1077
1180
|
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1078
1181
|
|
1079
|
-
private_key = PrivateKey_create(
|
1182
|
+
private_key = PrivateKey_create(private_key_bytes);
|
1080
1183
|
public_key = PublicKey_create_from_private_key(context, private_key_bytes);
|
1081
1184
|
result = rb_funcall(
|
1082
1185
|
Secp256k1_KeyPair_class,
|
@@ -1089,57 +1192,6 @@ Context_generate_key_pair(VALUE self)
|
|
1089
1192
|
return result;
|
1090
1193
|
}
|
1091
1194
|
|
1092
|
-
/**
|
1093
|
-
* Loads a public key from compressed or uncompressed binary data.
|
1094
|
-
*
|
1095
|
-
* @param in_public_key_data [String] binary string with compressed or
|
1096
|
-
* uncompressed public key data.
|
1097
|
-
* @return [Secp256k1::PublicKey] public key derived from data.
|
1098
|
-
* @raise [RuntimeError] if public key data is invalid.
|
1099
|
-
*/
|
1100
|
-
static VALUE
|
1101
|
-
Context_public_key_from_data(VALUE self, VALUE in_public_key_data)
|
1102
|
-
{
|
1103
|
-
Context *context;
|
1104
|
-
unsigned char *public_key_data;
|
1105
|
-
|
1106
|
-
Check_Type(in_public_key_data, T_STRING);
|
1107
|
-
|
1108
|
-
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1109
|
-
public_key_data = (unsigned char*)StringValuePtr(in_public_key_data);
|
1110
|
-
return PublicKey_create_from_data(
|
1111
|
-
context,
|
1112
|
-
public_key_data,
|
1113
|
-
(int)RSTRING_LEN(in_public_key_data)
|
1114
|
-
);
|
1115
|
-
}
|
1116
|
-
|
1117
|
-
/**
|
1118
|
-
* Load a private key from binary data.
|
1119
|
-
*
|
1120
|
-
* @param in_private_key_data [String] 32 byte binary string of private key
|
1121
|
-
* data.
|
1122
|
-
* @return [Secp256k1::PrivateKey] private key loaded from the given data.
|
1123
|
-
* @raise [ArgumentError] if private key data is not 32 bytes or is invalid.
|
1124
|
-
*/
|
1125
|
-
static VALUE
|
1126
|
-
Context_private_key_from_data(VALUE self, VALUE in_private_key_data)
|
1127
|
-
{
|
1128
|
-
Context *context;
|
1129
|
-
unsigned char *private_key_data;
|
1130
|
-
|
1131
|
-
Check_Type(in_private_key_data, T_STRING);
|
1132
|
-
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1133
|
-
private_key_data = (unsigned char*)StringValuePtr(in_private_key_data);
|
1134
|
-
|
1135
|
-
if (RSTRING_LEN(in_private_key_data) != 32)
|
1136
|
-
{
|
1137
|
-
rb_raise(rb_eArgError, "private key data must be 32 bytes in length");
|
1138
|
-
}
|
1139
|
-
|
1140
|
-
return PrivateKey_create(context, private_key_data);
|
1141
|
-
}
|
1142
|
-
|
1143
1195
|
/**
|
1144
1196
|
* Converts binary private key data into a new key pair.
|
1145
1197
|
*
|
@@ -1157,16 +1209,16 @@ Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
|
|
1157
1209
|
unsigned char *private_key_data;
|
1158
1210
|
|
1159
1211
|
Check_Type(in_private_key_data, T_STRING);
|
1212
|
+
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1160
1213
|
|
1161
1214
|
if (RSTRING_LEN(in_private_key_data) != 32)
|
1162
1215
|
{
|
1163
1216
|
rb_raise(rb_eArgError, "private key data must be 32 bytes in length");
|
1164
1217
|
}
|
1165
1218
|
|
1166
|
-
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1167
1219
|
private_key_data = (unsigned char*)StringValuePtr(in_private_key_data);
|
1168
1220
|
|
1169
|
-
private_key = PrivateKey_create(
|
1221
|
+
private_key = PrivateKey_create(private_key_data);
|
1170
1222
|
public_key = PublicKey_create_from_private_key(context, private_key_data);
|
1171
1223
|
|
1172
1224
|
return rb_funcall(
|
@@ -1178,83 +1230,6 @@ Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
|
|
1178
1230
|
);
|
1179
1231
|
}
|
1180
1232
|
|
1181
|
-
/**
|
1182
|
-
* Converts a DER encoded binary signature into a signature object.
|
1183
|
-
*
|
1184
|
-
* @param in_der_encoded_signature [String] DER encoded signature as binary
|
1185
|
-
* string.
|
1186
|
-
* @return [Secp256k1::Signature] signature object initialized using signature
|
1187
|
-
* data.
|
1188
|
-
* @raise [ArgumentError] if signature data is invalid.
|
1189
|
-
*/
|
1190
|
-
static VALUE
|
1191
|
-
Context_signature_from_der_encoded(VALUE self, VALUE in_der_encoded_signature)
|
1192
|
-
{
|
1193
|
-
Context *context;
|
1194
|
-
Signature *signature;
|
1195
|
-
VALUE signature_result;
|
1196
|
-
unsigned char *signature_data;
|
1197
|
-
|
1198
|
-
Check_Type(in_der_encoded_signature, T_STRING);
|
1199
|
-
|
1200
|
-
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1201
|
-
signature_data = (unsigned char*)StringValuePtr(in_der_encoded_signature);
|
1202
|
-
|
1203
|
-
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
1204
|
-
TypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
1205
|
-
|
1206
|
-
if (secp256k1_ecdsa_signature_parse_der(context->ctx,
|
1207
|
-
&(signature->sig),
|
1208
|
-
signature_data,
|
1209
|
-
RSTRING_LEN(in_der_encoded_signature)) != 1)
|
1210
|
-
{
|
1211
|
-
rb_raise(rb_eArgError, "invalid DER encoded signature");
|
1212
|
-
}
|
1213
|
-
|
1214
|
-
signature->ctx = secp256k1_context_clone(context->ctx);
|
1215
|
-
return signature_result;
|
1216
|
-
}
|
1217
|
-
|
1218
|
-
/**
|
1219
|
-
* Deserializes a Signature from 64-byte compact signature data.
|
1220
|
-
*
|
1221
|
-
* @param in_compact_signature [String] compact signature as 64-byte binary
|
1222
|
-
* string.
|
1223
|
-
* @return [Secp256k1::Signature] object deserialized from compact signature.
|
1224
|
-
* @raise [ArgumentError] if signature data is invalid.
|
1225
|
-
*/
|
1226
|
-
static VALUE
|
1227
|
-
Context_signature_from_compact(VALUE self, VALUE in_compact_signature)
|
1228
|
-
{
|
1229
|
-
Context *context;
|
1230
|
-
Signature *signature;
|
1231
|
-
VALUE signature_result;
|
1232
|
-
unsigned char *signature_data;
|
1233
|
-
|
1234
|
-
Check_Type(in_compact_signature, T_STRING);
|
1235
|
-
|
1236
|
-
if (RSTRING_LEN(in_compact_signature) != 64)
|
1237
|
-
{
|
1238
|
-
rb_raise(rb_eArgError, "compact signature must be 64 bytes");
|
1239
|
-
}
|
1240
|
-
|
1241
|
-
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1242
|
-
signature_data = (unsigned char*)StringValuePtr(in_compact_signature);
|
1243
|
-
|
1244
|
-
signature_result = Signature_alloc(Secp256k1_Signature_class);
|
1245
|
-
TypedData_Get_Struct(signature_result, Signature, &Signature_DataType, signature);
|
1246
|
-
|
1247
|
-
if (secp256k1_ecdsa_signature_parse_compact(context->ctx,
|
1248
|
-
&(signature->sig),
|
1249
|
-
signature_data) != 1)
|
1250
|
-
{
|
1251
|
-
rb_raise(rb_eArgError, "invalid compact signature");
|
1252
|
-
}
|
1253
|
-
|
1254
|
-
signature->ctx = secp256k1_context_clone(context->ctx);
|
1255
|
-
return signature_result;
|
1256
|
-
}
|
1257
|
-
|
1258
1233
|
/**
|
1259
1234
|
* Computes the ECDSA signature of the data using the secp256k1 elliptic curve.
|
1260
1235
|
*
|
@@ -1294,7 +1269,6 @@ Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1294
1269
|
private_key->data,
|
1295
1270
|
&(signature->sig))))
|
1296
1271
|
{
|
1297
|
-
signature->ctx = secp256k1_context_clone(context->ctx);
|
1298
1272
|
return signature_result;
|
1299
1273
|
}
|
1300
1274
|
|
@@ -1444,7 +1418,7 @@ Context_recoverable_signature_from_compact(
|
|
1444
1418
|
);
|
1445
1419
|
|
1446
1420
|
if (secp256k1_ecdsa_recoverable_signature_parse_compact(
|
1447
|
-
|
1421
|
+
secp256k1_context_no_precomp,
|
1448
1422
|
&(recoverable_signature->sig),
|
1449
1423
|
compact_sig,
|
1450
1424
|
recovery_id) == 1)
|
@@ -1587,14 +1561,6 @@ void Init_rbsecp256k1()
|
|
1587
1561
|
"key_pair_from_private_key",
|
1588
1562
|
Context_key_pair_from_private_key,
|
1589
1563
|
1);
|
1590
|
-
rb_define_method(Secp256k1_Context_class,
|
1591
|
-
"public_key_from_data",
|
1592
|
-
Context_public_key_from_data,
|
1593
|
-
1);
|
1594
|
-
rb_define_method(Secp256k1_Context_class,
|
1595
|
-
"private_key_from_data",
|
1596
|
-
Context_private_key_from_data,
|
1597
|
-
1);
|
1598
1564
|
rb_define_method(Secp256k1_Context_class,
|
1599
1565
|
"sign",
|
1600
1566
|
Context_sign,
|
@@ -1603,14 +1569,6 @@ void Init_rbsecp256k1()
|
|
1603
1569
|
"verify",
|
1604
1570
|
Context_verify,
|
1605
1571
|
3);
|
1606
|
-
rb_define_method(Secp256k1_Context_class,
|
1607
|
-
"signature_from_der_encoded",
|
1608
|
-
Context_signature_from_der_encoded,
|
1609
|
-
1);
|
1610
|
-
rb_define_method(Secp256k1_Context_class,
|
1611
|
-
"signature_from_compact",
|
1612
|
-
Context_signature_from_compact,
|
1613
|
-
1);
|
1614
1572
|
|
1615
1573
|
// Secp256k1::KeyPair
|
1616
1574
|
Secp256k1_KeyPair_class = rb_define_class_under(Secp256k1_module,
|
@@ -1638,6 +1596,12 @@ void Init_rbsecp256k1()
|
|
1638
1596
|
"uncompressed",
|
1639
1597
|
PublicKey_uncompressed,
|
1640
1598
|
0);
|
1599
|
+
rb_define_singleton_method(
|
1600
|
+
Secp256k1_PublicKey_class,
|
1601
|
+
"from_data",
|
1602
|
+
PublicKey_from_data,
|
1603
|
+
1
|
1604
|
+
);
|
1641
1605
|
rb_define_method(Secp256k1_PublicKey_class, "==", PublicKey_equals, 1);
|
1642
1606
|
|
1643
1607
|
// Secp256k1::PrivateKey
|
@@ -1647,6 +1611,12 @@ void Init_rbsecp256k1()
|
|
1647
1611
|
rb_define_alloc_func(Secp256k1_PrivateKey_class, PrivateKey_alloc);
|
1648
1612
|
rb_define_attr(Secp256k1_PrivateKey_class, "data", 1, 0);
|
1649
1613
|
rb_define_method(Secp256k1_PrivateKey_class, "==", PrivateKey_equals, 1);
|
1614
|
+
rb_define_singleton_method(
|
1615
|
+
Secp256k1_PrivateKey_class,
|
1616
|
+
"from_data",
|
1617
|
+
PrivateKey_from_data,
|
1618
|
+
1
|
1619
|
+
);
|
1650
1620
|
|
1651
1621
|
// Secp256k1::Signature
|
1652
1622
|
Secp256k1_Signature_class = rb_define_class_under(Secp256k1_module,
|
@@ -1669,6 +1639,18 @@ void Init_rbsecp256k1()
|
|
1669
1639
|
"==",
|
1670
1640
|
Signature_equals,
|
1671
1641
|
1);
|
1642
|
+
rb_define_singleton_method(
|
1643
|
+
Secp256k1_Signature_class,
|
1644
|
+
"from_compact",
|
1645
|
+
Signature_from_compact,
|
1646
|
+
1
|
1647
|
+
);
|
1648
|
+
rb_define_singleton_method(
|
1649
|
+
Secp256k1_Signature_class,
|
1650
|
+
"from_der_encoded",
|
1651
|
+
Signature_from_der_encoded,
|
1652
|
+
1
|
1653
|
+
);
|
1672
1654
|
|
1673
1655
|
#ifdef HAVE_SECP256K1_RECOVERY_H
|
1674
1656
|
// Secp256k1::RecoverableSignature
|
data/lib/rbsecp256k1/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbsecp256k1
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Scrivner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mini_portile2
|
@@ -131,6 +131,16 @@ extra_rdoc_files: []
|
|
131
131
|
files:
|
132
132
|
- README.md
|
133
133
|
- Rakefile
|
134
|
+
- documentation/context.md
|
135
|
+
- documentation/index.md
|
136
|
+
- documentation/key_pair.md
|
137
|
+
- documentation/private_key.md
|
138
|
+
- documentation/public_key.md
|
139
|
+
- documentation/recoverable_signature.md
|
140
|
+
- documentation/secp256k1.md
|
141
|
+
- documentation/shared_secret.md
|
142
|
+
- documentation/signature.md
|
143
|
+
- documentation/util.md
|
134
144
|
- ext/rbsecp256k1/extconf.rb
|
135
145
|
- ext/rbsecp256k1/rbsecp256k1.c
|
136
146
|
- lib/rbsecp256k1.rb
|