rbsecp256k1 6.0.1 → 6.0.2
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/LICENSE +24 -24
- data/README.md +134 -129
- data/Rakefile +23 -18
- data/documentation/context.md +125 -98
- data/documentation/index.md +391 -378
- data/documentation/key_pair.md +25 -25
- data/documentation/private_key.md +25 -25
- data/documentation/public_key.md +36 -36
- data/documentation/recoverable_signature.md +30 -30
- data/documentation/schnorr_signature.md +34 -30
- data/documentation/secp256k1.md +24 -24
- data/documentation/shared_secret.md +14 -14
- data/documentation/signature.md +42 -42
- data/documentation/util.md +17 -17
- data/documentation/xonly_public_key.md +29 -29
- data/ext/rbsecp256k1/extconf.rb +62 -121
- data/ext/rbsecp256k1/rbsecp256k1.c +2429 -2244
- data/ext/rbsecp256k1/secp256k1_recipe.rb +76 -0
- data/lib/rbsecp256k1/context.rb +40 -36
- data/lib/rbsecp256k1/util.rb +28 -28
- data/lib/rbsecp256k1/version.rb +5 -5
- data/lib/rbsecp256k1.rb +14 -14
- metadata +16 -1
data/documentation/index.md
CHANGED
|
@@ -1,378 +1,391 @@
|
|
|
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
|
-
| | [XOnlyPublicKey](xonly_public_key.md) |
|
|
15
|
-
| | [PrivateKey](private_key.md) |
|
|
16
|
-
| | [SharedSecret](shared_secret.md) |
|
|
17
|
-
| | [Signature](signature.md) |
|
|
18
|
-
| | [RecoverableSignature](recoverable_signature.md) |
|
|
19
|
-
| | [SchnorrSignature](schnorr_signature.md) |
|
|
20
|
-
|
|
21
|
-
Glossary
|
|
22
|
-
--------
|
|
23
|
-
|
|
24
|
-
**[Context](context.md)** is a libsecp256k1 library context. It contains
|
|
25
|
-
pre-computed tables and values to make ECDSA signing and verification more
|
|
26
|
-
efficient.
|
|
27
|
-
|
|
28
|
-
**[KeyPair](key_pair.md)** is a Secp256k1 elliptic-curve key pair.
|
|
29
|
-
|
|
30
|
-
**[PublicKey](public_key.md)** is a Secp256k1 public key. It can come in either
|
|
31
|
-
compressed or uncompressed format.
|
|
32
|
-
|
|
33
|
-
**[XOnlyPublicKey](xonly_public_key.md)** is a Secp256k1 x-only public key.
|
|
34
|
-
|
|
35
|
-
**[PrivateKey](private_key.md)** is a 64-byte Secp256k1 private key.
|
|
36
|
-
|
|
37
|
-
**[SharedSecret](shared_secret.md)** A 32-byte shared secret computed from a
|
|
38
|
-
public key (point) and private key (scalar).
|
|
39
|
-
|
|
40
|
-
**[Signature](signature.md)** is an ECDSA signature of the SHA-256 message hash
|
|
41
|
-
of a piece of data.
|
|
42
|
-
|
|
43
|
-
**[RecoverableSignature](recoverable_signature.md)** is a recoverable ECDSA signature of the SHA-256 message
|
|
44
|
-
hash of a piece of data.
|
|
45
|
-
|
|
46
|
-
**[SchnorrSignature](schnorr_signature.md)** is a Schnorr signature of a
|
|
47
|
-
|
|
48
|
-
Examples
|
|
49
|
-
--------
|
|
50
|
-
|
|
51
|
-
### 1. Creating a libsecp256k1 context
|
|
52
|
-
|
|
53
|
-
This example demonstrates how to create a new libsecp256k1 context. This is the
|
|
54
|
-
first step of using this library:
|
|
55
|
-
|
|
56
|
-
```ruby
|
|
57
|
-
context = Secp256k1::Context.create
|
|
58
|
-
# => #<Secp256k1::Context:0x0000559b0bd8f5d0>
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### 2. Generating a key pair
|
|
62
|
-
|
|
63
|
-
This example shows how to generate a new public-private key pair:
|
|
64
|
-
|
|
65
|
-
```ruby
|
|
66
|
-
context = Secp256k1::Context.create
|
|
67
|
-
key_pair = context.generate_key_pair
|
|
68
|
-
# => #<Secp256k1::KeyPair:0x0000559b0bc876b0>
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### 3. Getting compressed and uncompressed public key representations
|
|
72
|
-
|
|
73
|
-
This example shows how to generate compressed and uncompressed public keys:
|
|
74
|
-
|
|
75
|
-
```ruby
|
|
76
|
-
context = Secp256k1::Context.create
|
|
77
|
-
key_pair = context.generate_key_pair
|
|
78
|
-
|
|
79
|
-
# 1. Get the binary representation of compressed public key
|
|
80
|
-
key_pair.public_key.compressed
|
|
81
|
-
# => "\x03D\x88\xD6 3|3\x836\xCB(\x9CW%\xF4T\xB7\xCD\x8AF T\xE7\xE8\xCE\xB0\xC7c{\xE2:\xFE"
|
|
82
|
-
|
|
83
|
-
# 2. Show hex representation of compressed public key
|
|
84
|
-
Secp256k1::Util.bin_to_hex(key_pair.public_key.compressed)
|
|
85
|
-
# => "034488d620337c338336cb289c5725f454b7cd8a462054e7e8ceb0c7637be23afe"
|
|
86
|
-
|
|
87
|
-
# 3. Get the binary representation of uncompressed public key
|
|
88
|
-
key_pair.public_key.uncompressed
|
|
89
|
-
# => "\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"
|
|
90
|
-
|
|
91
|
-
# 4. Show hex representation of uncompressed public key
|
|
92
|
-
Secp256k1::Util.bin_to_hex(key_pair.public_key.uncompressed)
|
|
93
|
-
# => "044488d620337c338336cb289c5725f454b7cd8a462054e7e8ceb0c7637be23afe20585265771f1b05c8dca7e38cbd91733ffc57d5b3a86161434347d4946da563"
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### 3. Signing a message
|
|
97
|
-
|
|
98
|
-
This example shows how to sign a message using your private key:
|
|
99
|
-
|
|
100
|
-
```ruby
|
|
101
|
-
require 'digest'
|
|
102
|
-
|
|
103
|
-
context = Secp256k1::Context.create
|
|
104
|
-
key_pair = context.generate_key_pair
|
|
105
|
-
|
|
106
|
-
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
|
107
|
-
# => #<Secp256k1::Signature:0x0000559b0bc79358>
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### 4. Getting DER and Compact signature encodings
|
|
111
|
-
|
|
112
|
-
This example shows you how to get the DER encoded and compact encoded
|
|
113
|
-
representations of a signature:
|
|
114
|
-
|
|
115
|
-
```ruby
|
|
116
|
-
require 'digest'
|
|
117
|
-
|
|
118
|
-
context = Secp256k1::Context.create
|
|
119
|
-
key_pair = context.generate_key_pair
|
|
120
|
-
|
|
121
|
-
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
|
122
|
-
|
|
123
|
-
# 1. Get the compact binary representation
|
|
124
|
-
signature.compact
|
|
125
|
-
# => "\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"
|
|
126
|
-
|
|
127
|
-
# 2. Get the compact hex representation
|
|
128
|
-
Secp256k1::Util.bin_to_hex(signature.compact)
|
|
129
|
-
# => "ab2365365f86361bac1b9257c861844ed4b688f8eedffb43e86ab2f010b8a089134c1b9e916342d7ac11f7022c5926544da57a70fdb3b1dc4956bb5caf1640fc00"
|
|
130
|
-
|
|
131
|
-
# 3. Get the DER binary representation
|
|
132
|
-
signature.der_encoded
|
|
133
|
-
# => "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"
|
|
134
|
-
|
|
135
|
-
# 4. Get the DER hex representation
|
|
136
|
-
Secp256k1::Util.bin_to_hex(signature.der_encoded)
|
|
137
|
-
# => "3045022100ab2365365f86361bac1b9257c861844ed4b688f8eedffb43e86ab2f010b8a0890220134c1b9e916342d7ac11f7022c5926544da57a70fdb3b1dc4956bb5caf1640fc"
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### 5. Verifying a signature
|
|
141
|
-
|
|
142
|
-
This example shows how to verify a signature using a public key:
|
|
143
|
-
|
|
144
|
-
```ruby
|
|
145
|
-
require 'digest'
|
|
146
|
-
|
|
147
|
-
context = Secp256k1::Context.create
|
|
148
|
-
key_pair = context.generate_key_pair
|
|
149
|
-
hash = Digest::SHA256.digest("test message")
|
|
150
|
-
|
|
151
|
-
signature = context.sign(key_pair.private_key, hash)
|
|
152
|
-
|
|
153
|
-
# 1. Verify signature against matching message
|
|
154
|
-
context.verify(signature, key_pair.public_key, hash)
|
|
155
|
-
# => true
|
|
156
|
-
|
|
157
|
-
# 2. Verify signature against different message
|
|
158
|
-
context.verify(signature, key_pair.public_key, hash)
|
|
159
|
-
# => false
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### 6. Loading a private key or key pair from private key data
|
|
163
|
-
|
|
164
|
-
This example shows how to load a key pair from raw binary private key data:
|
|
165
|
-
|
|
166
|
-
```ruby
|
|
167
|
-
context = Secp256k1::Context.create
|
|
168
|
-
|
|
169
|
-
#1. Load private key alone
|
|
170
|
-
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")
|
|
171
|
-
# => #<Secp256k1::PrivateKey:0x00005647df1bcd30>
|
|
172
|
-
|
|
173
|
-
# 2. Load key pair from private key data
|
|
174
|
-
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")
|
|
175
|
-
# => #<Secp256k1::KeyPair:0x0000559b0bbf9a90>
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### 7. Loading a public key from binary data
|
|
179
|
-
|
|
180
|
-
This example shows how to load a public key from binary data:
|
|
181
|
-
|
|
182
|
-
```ruby
|
|
183
|
-
# 1. Load public key from uncompressed pubkey
|
|
184
|
-
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")
|
|
185
|
-
# => #<Secp256k1::PublicKey:0x0000559b0bdc72f0>
|
|
186
|
-
|
|
187
|
-
# 2. Load public key from compressed pubkey
|
|
188
|
-
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")
|
|
189
|
-
# => #<Secp256k1::PublicKey:0x0000559b0bdd3668>
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### 8. Loading a DER or compact encoded signature
|
|
193
|
-
|
|
194
|
-
This example shows how to load signatures from binary data:
|
|
195
|
-
|
|
196
|
-
```ruby
|
|
197
|
-
# 1. From DER encoded signature
|
|
198
|
-
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")
|
|
199
|
-
# => #<Secp256k1::Signature:0x0000559b0b823d58>
|
|
200
|
-
|
|
201
|
-
# 2. From compact signature
|
|
202
|
-
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")
|
|
203
|
-
# => #<Secp256k1::Signature:0x0000559b0bdcaa68>
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
Schnorr Signature Examples
|
|
207
|
-
--------------------------
|
|
208
|
-
|
|
209
|
-
### 1. Checking for the Schnorr module
|
|
210
|
-
|
|
211
|
-
To check if you have compiled the schnorr signature module into your local
|
|
212
|
-
libsecp256k1 run the following:
|
|
213
|
-
|
|
214
|
-
```ruby
|
|
215
|
-
Secp256k1.have_schnorr?
|
|
216
|
-
# => true
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### 2. Calculate the tagged SHA-256 hash of data
|
|
220
|
-
|
|
221
|
-
You can produce the tagged SHA-256 hash recommended for use with Schnorr
|
|
222
|
-
signatures as follows:
|
|
223
|
-
|
|
224
|
-
```ruby
|
|
225
|
-
context = Secp256k1::Context.create
|
|
226
|
-
|
|
227
|
-
context.tagged_sha256('my_test_tag', 'data')
|
|
228
|
-
=> "0\x85|\xC8h\x9A\x8C^\x0FoD\xDF\xD0,\x1C\x1EV}\xE8\xA8<\xC5\xA5vI\x9E`=\x9B\xC4\xA8\xAE"
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### 3. Sign and verify a message using Schnorr signatures
|
|
232
|
-
|
|
233
|
-
```ruby
|
|
234
|
-
context = Secp256k1::Context.create
|
|
235
|
-
key_pair = context.generate_key_pair
|
|
236
|
-
message = context.tagged_sha256('my_test_tag', 'data')
|
|
237
|
-
|
|
238
|
-
schnorr_sig = context.sign_schnorr(key_pair, message)
|
|
239
|
-
=> #<Secp256k1::SchnorrSignature:0x00007f4de11e5768>
|
|
240
|
-
|
|
241
|
-
schnorr_sig.verify(message, key_pair.xonly_public_key)
|
|
242
|
-
=> true
|
|
243
|
-
|
|
244
|
-
schnorr_sig.serialized
|
|
245
|
-
=> "\x16\xEF\x04\xB0JP\xE9\x90\xC2\xB1\xE6-l\xDB\x1D\xAE\xAAc\xBF@9s\x02\xC2\xD5[\xFB\x19Q\xFAI^Hj\xD1)\xBE\xEA\xA5!a\xAD\xBEO\xCE7\x9Em\x13;\xE8R\x8A\x81$\nv\xF4\xD3\xB25\xA9\xF9\xC0"
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
=>
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Secp256k1.
|
|
269
|
-
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
recovery_id =
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
signature
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
public_key
|
|
351
|
-
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
# => true
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
# =>
|
|
378
|
-
```
|
|
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
|
+
| | [XOnlyPublicKey](xonly_public_key.md) |
|
|
15
|
+
| | [PrivateKey](private_key.md) |
|
|
16
|
+
| | [SharedSecret](shared_secret.md) |
|
|
17
|
+
| | [Signature](signature.md) |
|
|
18
|
+
| | [RecoverableSignature](recoverable_signature.md) |
|
|
19
|
+
| | [SchnorrSignature](schnorr_signature.md) |
|
|
20
|
+
|
|
21
|
+
Glossary
|
|
22
|
+
--------
|
|
23
|
+
|
|
24
|
+
**[Context](context.md)** is a libsecp256k1 library context. It contains
|
|
25
|
+
pre-computed tables and values to make ECDSA signing and verification more
|
|
26
|
+
efficient.
|
|
27
|
+
|
|
28
|
+
**[KeyPair](key_pair.md)** is a Secp256k1 elliptic-curve key pair.
|
|
29
|
+
|
|
30
|
+
**[PublicKey](public_key.md)** is a Secp256k1 public key. It can come in either
|
|
31
|
+
compressed or uncompressed format.
|
|
32
|
+
|
|
33
|
+
**[XOnlyPublicKey](xonly_public_key.md)** is a Secp256k1 x-only public key.
|
|
34
|
+
|
|
35
|
+
**[PrivateKey](private_key.md)** is a 64-byte Secp256k1 private key.
|
|
36
|
+
|
|
37
|
+
**[SharedSecret](shared_secret.md)** A 32-byte shared secret computed from a
|
|
38
|
+
public key (point) and private key (scalar).
|
|
39
|
+
|
|
40
|
+
**[Signature](signature.md)** is an ECDSA signature of the SHA-256 message hash
|
|
41
|
+
of a piece of data.
|
|
42
|
+
|
|
43
|
+
**[RecoverableSignature](recoverable_signature.md)** is a recoverable ECDSA signature of the SHA-256 message
|
|
44
|
+
hash of a piece of data.
|
|
45
|
+
|
|
46
|
+
**[SchnorrSignature](schnorr_signature.md)** is a 64-byte Schnorr signature of a message of any byte length.
|
|
47
|
+
|
|
48
|
+
Examples
|
|
49
|
+
--------
|
|
50
|
+
|
|
51
|
+
### 1. Creating a libsecp256k1 context
|
|
52
|
+
|
|
53
|
+
This example demonstrates how to create a new libsecp256k1 context. This is the
|
|
54
|
+
first step of using this library:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
context = Secp256k1::Context.create
|
|
58
|
+
# => #<Secp256k1::Context:0x0000559b0bd8f5d0>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 2. Generating a key pair
|
|
62
|
+
|
|
63
|
+
This example shows how to generate a new public-private key pair:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
context = Secp256k1::Context.create
|
|
67
|
+
key_pair = context.generate_key_pair
|
|
68
|
+
# => #<Secp256k1::KeyPair:0x0000559b0bc876b0>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Getting compressed and uncompressed public key representations
|
|
72
|
+
|
|
73
|
+
This example shows how to generate compressed and uncompressed public keys:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
context = Secp256k1::Context.create
|
|
77
|
+
key_pair = context.generate_key_pair
|
|
78
|
+
|
|
79
|
+
# 1. Get the binary representation of compressed public key
|
|
80
|
+
key_pair.public_key.compressed
|
|
81
|
+
# => "\x03D\x88\xD6 3|3\x836\xCB(\x9CW%\xF4T\xB7\xCD\x8AF T\xE7\xE8\xCE\xB0\xC7c{\xE2:\xFE"
|
|
82
|
+
|
|
83
|
+
# 2. Show hex representation of compressed public key
|
|
84
|
+
Secp256k1::Util.bin_to_hex(key_pair.public_key.compressed)
|
|
85
|
+
# => "034488d620337c338336cb289c5725f454b7cd8a462054e7e8ceb0c7637be23afe"
|
|
86
|
+
|
|
87
|
+
# 3. Get the binary representation of uncompressed public key
|
|
88
|
+
key_pair.public_key.uncompressed
|
|
89
|
+
# => "\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"
|
|
90
|
+
|
|
91
|
+
# 4. Show hex representation of uncompressed public key
|
|
92
|
+
Secp256k1::Util.bin_to_hex(key_pair.public_key.uncompressed)
|
|
93
|
+
# => "044488d620337c338336cb289c5725f454b7cd8a462054e7e8ceb0c7637be23afe20585265771f1b05c8dca7e38cbd91733ffc57d5b3a86161434347d4946da563"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Signing a message
|
|
97
|
+
|
|
98
|
+
This example shows how to sign a message using your private key:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
require 'digest'
|
|
102
|
+
|
|
103
|
+
context = Secp256k1::Context.create
|
|
104
|
+
key_pair = context.generate_key_pair
|
|
105
|
+
|
|
106
|
+
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
|
107
|
+
# => #<Secp256k1::Signature:0x0000559b0bc79358>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 4. Getting DER and Compact signature encodings
|
|
111
|
+
|
|
112
|
+
This example shows you how to get the DER encoded and compact encoded
|
|
113
|
+
representations of a signature:
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
require 'digest'
|
|
117
|
+
|
|
118
|
+
context = Secp256k1::Context.create
|
|
119
|
+
key_pair = context.generate_key_pair
|
|
120
|
+
|
|
121
|
+
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
|
122
|
+
|
|
123
|
+
# 1. Get the compact binary representation
|
|
124
|
+
signature.compact
|
|
125
|
+
# => "\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"
|
|
126
|
+
|
|
127
|
+
# 2. Get the compact hex representation
|
|
128
|
+
Secp256k1::Util.bin_to_hex(signature.compact)
|
|
129
|
+
# => "ab2365365f86361bac1b9257c861844ed4b688f8eedffb43e86ab2f010b8a089134c1b9e916342d7ac11f7022c5926544da57a70fdb3b1dc4956bb5caf1640fc00"
|
|
130
|
+
|
|
131
|
+
# 3. Get the DER binary representation
|
|
132
|
+
signature.der_encoded
|
|
133
|
+
# => "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"
|
|
134
|
+
|
|
135
|
+
# 4. Get the DER hex representation
|
|
136
|
+
Secp256k1::Util.bin_to_hex(signature.der_encoded)
|
|
137
|
+
# => "3045022100ab2365365f86361bac1b9257c861844ed4b688f8eedffb43e86ab2f010b8a0890220134c1b9e916342d7ac11f7022c5926544da57a70fdb3b1dc4956bb5caf1640fc"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 5. Verifying a signature
|
|
141
|
+
|
|
142
|
+
This example shows how to verify a signature using a public key:
|
|
143
|
+
|
|
144
|
+
```ruby
|
|
145
|
+
require 'digest'
|
|
146
|
+
|
|
147
|
+
context = Secp256k1::Context.create
|
|
148
|
+
key_pair = context.generate_key_pair
|
|
149
|
+
hash = Digest::SHA256.digest("test message")
|
|
150
|
+
|
|
151
|
+
signature = context.sign(key_pair.private_key, hash)
|
|
152
|
+
|
|
153
|
+
# 1. Verify signature against matching message
|
|
154
|
+
context.verify(signature, key_pair.public_key, hash)
|
|
155
|
+
# => true
|
|
156
|
+
|
|
157
|
+
# 2. Verify signature against different message
|
|
158
|
+
context.verify(signature, key_pair.public_key, hash)
|
|
159
|
+
# => false
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 6. Loading a private key or key pair from private key data
|
|
163
|
+
|
|
164
|
+
This example shows how to load a key pair from raw binary private key data:
|
|
165
|
+
|
|
166
|
+
```ruby
|
|
167
|
+
context = Secp256k1::Context.create
|
|
168
|
+
|
|
169
|
+
#1. Load private key alone
|
|
170
|
+
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")
|
|
171
|
+
# => #<Secp256k1::PrivateKey:0x00005647df1bcd30>
|
|
172
|
+
|
|
173
|
+
# 2. Load key pair from private key data
|
|
174
|
+
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")
|
|
175
|
+
# => #<Secp256k1::KeyPair:0x0000559b0bbf9a90>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 7. Loading a public key from binary data
|
|
179
|
+
|
|
180
|
+
This example shows how to load a public key from binary data:
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
# 1. Load public key from uncompressed pubkey
|
|
184
|
+
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")
|
|
185
|
+
# => #<Secp256k1::PublicKey:0x0000559b0bdc72f0>
|
|
186
|
+
|
|
187
|
+
# 2. Load public key from compressed pubkey
|
|
188
|
+
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")
|
|
189
|
+
# => #<Secp256k1::PublicKey:0x0000559b0bdd3668>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 8. Loading a DER or compact encoded signature
|
|
193
|
+
|
|
194
|
+
This example shows how to load signatures from binary data:
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
# 1. From DER encoded signature
|
|
198
|
+
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")
|
|
199
|
+
# => #<Secp256k1::Signature:0x0000559b0b823d58>
|
|
200
|
+
|
|
201
|
+
# 2. From compact signature
|
|
202
|
+
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")
|
|
203
|
+
# => #<Secp256k1::Signature:0x0000559b0bdcaa68>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Schnorr Signature Examples
|
|
207
|
+
--------------------------
|
|
208
|
+
|
|
209
|
+
### 1. Checking for the Schnorr module
|
|
210
|
+
|
|
211
|
+
To check if you have compiled the schnorr signature module into your local
|
|
212
|
+
libsecp256k1 run the following:
|
|
213
|
+
|
|
214
|
+
```ruby
|
|
215
|
+
Secp256k1.have_schnorr?
|
|
216
|
+
# => true
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 2. Calculate the tagged SHA-256 hash of data
|
|
220
|
+
|
|
221
|
+
You can produce the tagged SHA-256 hash recommended for use with Schnorr
|
|
222
|
+
signatures as follows:
|
|
223
|
+
|
|
224
|
+
```ruby
|
|
225
|
+
context = Secp256k1::Context.create
|
|
226
|
+
|
|
227
|
+
context.tagged_sha256('my_test_tag', 'data')
|
|
228
|
+
=> "0\x85|\xC8h\x9A\x8C^\x0FoD\xDF\xD0,\x1C\x1EV}\xE8\xA8<\xC5\xA5vI\x9E`=\x9B\xC4\xA8\xAE"
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 3. Sign and verify a message using Schnorr signatures
|
|
232
|
+
|
|
233
|
+
```ruby
|
|
234
|
+
context = Secp256k1::Context.create
|
|
235
|
+
key_pair = context.generate_key_pair
|
|
236
|
+
message = context.tagged_sha256('my_test_tag', 'data')
|
|
237
|
+
|
|
238
|
+
schnorr_sig = context.sign_schnorr(key_pair, message)
|
|
239
|
+
=> #<Secp256k1::SchnorrSignature:0x00007f4de11e5768>
|
|
240
|
+
|
|
241
|
+
schnorr_sig.verify(message, key_pair.xonly_public_key)
|
|
242
|
+
=> true
|
|
243
|
+
|
|
244
|
+
schnorr_sig.serialized
|
|
245
|
+
=> "\x16\xEF\x04\xB0JP\xE9\x90\xC2\xB1\xE6-l\xDB\x1D\xAE\xAAc\xBF@9s\x02\xC2\xD5[\xFB\x19Q\xFAI^Hj\xD1)\xBE\xEA\xA5!a\xAD\xBEO\xCE7\x9Em\x13;\xE8R\x8A\x81$\nv\xF4\xD3\xB25\xA9\xF9\xC0"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Messages can also be signed directly, including empty strings. No implicit
|
|
249
|
+
hashing, padding, or truncation is performed; use the same bytes for verification.
|
|
250
|
+
The tagged hash above is an explicit application choice.
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
message = 'a message of any byte length'.b
|
|
254
|
+
signature = context.sign_schnorr(key_pair, message)
|
|
255
|
+
signature.verify(message, key_pair.xonly_public_key)
|
|
256
|
+
# => true
|
|
257
|
+
signature.serialized.bytesize
|
|
258
|
+
# => 64
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 4. Load a Schnorr signature from binary serialized version
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
context = Secp256k1::Context.create
|
|
265
|
+
|
|
266
|
+
schnorr_sig_raw = "\x16\xEF\x04\xB0JP\xE9\x90\xC2\xB1\xE6-l\xDB\x1D\xAE\xAAc\xBF@9s\x02\xC2\xD5[\xFB\x19Q\xFAI^Hj\xD1)\xBE\xEA\xA5!a\xAD\xBEO\xCE7\x9Em\x13;\xE8R\x8A\x81$\nv\xF4\xD3\xB25\xA9\xF9\xC0"
|
|
267
|
+
|
|
268
|
+
Secp256k1::SchnorrSignature.from_data(schnorr_sig_raw)
|
|
269
|
+
=> #<Secp256k1::SchnorrSignature:0x00007f4de1225818>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Recoverable Signature Examples
|
|
273
|
+
------------------------------
|
|
274
|
+
|
|
275
|
+
### 1. Checking for recovery module
|
|
276
|
+
|
|
277
|
+
To check if you have compiled the recovery module into your local libsecp256k1
|
|
278
|
+
run the following:
|
|
279
|
+
|
|
280
|
+
```ruby
|
|
281
|
+
Secp256k1.have_recovery?
|
|
282
|
+
# => true
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 2. Sign data producing recoverable signature
|
|
286
|
+
|
|
287
|
+
You can sign data producing a recoverable signature as follows:
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
yrequire 'digest'
|
|
291
|
+
|
|
292
|
+
hash = Digest::SHA256.digest('test message')
|
|
293
|
+
context = Secp256k1::Context.create
|
|
294
|
+
key_pair = context.generate_key_pair
|
|
295
|
+
|
|
296
|
+
signature = context.sign_recoverable(key_pair.private_key, hash)
|
|
297
|
+
# => #<Secp256k1::RecoverableSignature:0x000055f2ea76e548>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 3. Serialize recoverable signature as compact representation
|
|
301
|
+
|
|
302
|
+
You can produce the compact binary serialization of a recoverable signature:
|
|
303
|
+
|
|
304
|
+
```ruby
|
|
305
|
+
require 'digest'
|
|
306
|
+
|
|
307
|
+
hash = Digest::SHA256.digest('test message')
|
|
308
|
+
context = Secp256k1::Context.create
|
|
309
|
+
key_pair = context.generate_key_pair
|
|
310
|
+
|
|
311
|
+
signature = context.sign_recoverable(key_pair.private_key, hash)
|
|
312
|
+
compact_data, recovery_id = signature.compact
|
|
313
|
+
# => ["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]
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### 4. Recoverable signature from compact representation
|
|
317
|
+
|
|
318
|
+
You can load a recoverable signature give its compact representation and
|
|
319
|
+
recovery ID:
|
|
320
|
+
|
|
321
|
+
```ruby
|
|
322
|
+
context = Secp256k1::Context.create
|
|
323
|
+
|
|
324
|
+
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"
|
|
325
|
+
recovery_id = 1
|
|
326
|
+
|
|
327
|
+
signature = context.recoverable_signature_from_compact(compact_data, recovery_id)
|
|
328
|
+
# => #<Secp256k1::RecoverableSignature:0x000055f2ea7615c8>
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### 5. Convert recoverable signature to non-recoverable signature
|
|
332
|
+
|
|
333
|
+
You can convert a recoverable signature to a non-recoverable signature suitable
|
|
334
|
+
for use by all methods that take a [Signature](signature.md) object:
|
|
335
|
+
|
|
336
|
+
```ruby
|
|
337
|
+
require 'digest'
|
|
338
|
+
|
|
339
|
+
hash = Digest::SHA256.digest('test message')
|
|
340
|
+
context = Secp256k1::Context.create
|
|
341
|
+
key_pair = context.generate_key_pair
|
|
342
|
+
|
|
343
|
+
recoverable_signature = context.sign_recoverable(key_pair.private_key, hash)
|
|
344
|
+
signature = recoverable_signature.to_signature
|
|
345
|
+
# => #<Secp256k1::Signature:0x000055f2ea8ca4f0>
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### 6. Recover public key from recoverable signature
|
|
349
|
+
|
|
350
|
+
You can recover the [PublicKey](public_key.md) associated with a recoverable signature:
|
|
351
|
+
|
|
352
|
+
```ruby
|
|
353
|
+
require 'digest'
|
|
354
|
+
|
|
355
|
+
hash = Digest::SHA256.digest('test message')
|
|
356
|
+
context = Secp256k1::Context.create
|
|
357
|
+
key_pair = context.generate_key_pair
|
|
358
|
+
|
|
359
|
+
recoverable_signature = context.sign_recoverable(key_pair.private_key, hash)
|
|
360
|
+
public_key = recoverable_signature.recover_public_key(hash)
|
|
361
|
+
# => #<Secp256k1::PublicKey:0x000055f2ea756678>
|
|
362
|
+
|
|
363
|
+
public_key == key_pair.public_key
|
|
364
|
+
# => true
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
EC Diffie-Hellman
|
|
368
|
+
-----------------
|
|
369
|
+
|
|
370
|
+
### 1. Checking for ECDH module
|
|
371
|
+
|
|
372
|
+
To check if you have compiled the ECDH module into your local libsecp256k1 run
|
|
373
|
+
the following:
|
|
374
|
+
|
|
375
|
+
```ruby
|
|
376
|
+
Secp256k1.have_ecdh?
|
|
377
|
+
# => true
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### 2. Generating a shared secret
|
|
381
|
+
|
|
382
|
+
To generate a shared secret run the following:
|
|
383
|
+
|
|
384
|
+
```ruby
|
|
385
|
+
context = Secp256k1::Context.create
|
|
386
|
+
key_pair = context.generate_key_pair
|
|
387
|
+
|
|
388
|
+
shared_secret = context.ecdh(key_pair.public_key, key_pair.private_key)
|
|
389
|
+
shared_secret.data
|
|
390
|
+
# => "\x1FQ\x90X\xA5\xF2\xAEx;\xD7i\xB6\\T,2[\x90\xD1)a$\x1CA\x17\x8F\e\x91\xE3\x06C\x93"
|
|
391
|
+
```
|