rbsecp256k1 4.0.0 → 5.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/README.md +7 -3
- data/Rakefile +2 -0
- data/documentation/context.md +20 -5
- data/documentation/index.md +13 -13
- data/documentation/private_key.md +1 -1
- data/documentation/public_key.md +2 -2
- data/documentation/signature.md +2 -2
- data/ext/rbsecp256k1/extconf.rb +9 -55
- data/ext/rbsecp256k1/rbsecp256k1.c +140 -128
- data/lib/rbsecp256k1.rb +3 -0
- data/lib/rbsecp256k1/context.rb +29 -0
- data/lib/rbsecp256k1/util.rb +2 -0
- data/lib/rbsecp256k1/version.rb +3 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09bce1370a196e16d15f8d923add9097a24e54cd16d6966252eaef876b43e8e2'
|
4
|
+
data.tar.gz: 59c16c569f2ea9a18d67f041b0a6bcd4b334d747a165e8801192094518a0a11b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 457122cce9314f5f6af45c73fc2b55977e98765d5aa13e18e6a7f6ea614f0af0559857a6a735c4c066760b62af9fa970200645fb93f1f4fd333a6f3412297ad5
|
7
|
+
data.tar.gz: 4f503461cc54439ea891b4c0827d93a8e403abac1e9503f5be7b422c09abfae59917507d029ea0a3d6bb2cde10c64c256e9c6463ef0e1faace5e568d4d7d6282
|
data/README.md
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.com/etscrivner/rbsecp256k1) [](https://badge.fury.io/rb/rbsecp256k1)
|
4
4
|
|
5
|
-
|
6
|
-
and later libsecp256k1 is bundled with the gem.
|
5
|
+
Native extension gem for secp256k1 ECDSA. Wraps [libsecp256k1](https://github.com/bitcoin-core/secp256k1). In
|
6
|
+
rbsecp256k1 3.0.0 and later libsecp256k1 is bundled with the gem.
|
7
7
|
|
8
|
-
[Documentation](documentation/index.md)
|
8
|
+
* [Documentation](documentation/index.md)
|
9
|
+
* [Examples](examples/README.md)
|
9
10
|
|
10
11
|
### Why wrap libsecp256k1?
|
11
12
|
|
@@ -16,6 +17,9 @@ faster than the OpenSSL implementation of the same curve. It is the only library
|
|
16
17
|
that provides constant time signing of this curve and has been deployed as part
|
17
18
|
of Bitcoin since [v0.10.0](https://bitcoin.org/en/release/v0.10.0#improved-signing-security)
|
18
19
|
|
20
|
+
Natively wrapping the library in an extension gem means users don't have to
|
21
|
+
worry about compiling or locating the library, unlike many [FFI](https://github.com/ffi/ffi) based gems.
|
22
|
+
|
19
23
|
## Installation
|
20
24
|
|
21
25
|
The simplest installation:
|
data/Rakefile
CHANGED
data/documentation/context.md
CHANGED
@@ -10,10 +10,25 @@ for multiple operations as much as possible.
|
|
10
10
|
Initializers
|
11
11
|
------------
|
12
12
|
|
13
|
-
#### new
|
13
|
+
#### new(context_randomization_bytes: nil)
|
14
14
|
|
15
15
|
Returns a newly initialized libsecp256k1 context. The context is randomized at
|
16
|
-
initialization
|
16
|
+
initialization if given `context_randomization_bytes`. The
|
17
|
+
`context_randomization_bytes` argument can optionally take a string containing
|
18
|
+
32 bytes of random data, if not provided then the Context is not randomized and
|
19
|
+
may be vulnerable to side-channel attacks.
|
20
|
+
|
21
|
+
Class Methods
|
22
|
+
-------------
|
23
|
+
|
24
|
+
#### create
|
25
|
+
|
26
|
+
Creates and returns a new randomized `Context` using `SecureRandom` for the
|
27
|
+
random initialization bytes. This is the recommended method for initialization.
|
28
|
+
|
29
|
+
#### create_unrandomized
|
30
|
+
|
31
|
+
Creates a new unrandomized `Context`.
|
17
32
|
|
18
33
|
Instance Methods
|
19
34
|
----------------
|
@@ -23,7 +38,7 @@ Instance Methods
|
|
23
38
|
**Requires:** libsecp256k1 was built with the experimental ECDH module.
|
24
39
|
|
25
40
|
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 `
|
41
|
+
[SharedSecret](shared_secret.md) containing the 32-byte shared secret. Raises a `Secp256k1::Error` if
|
27
42
|
the `scalar` is invalid (zero or causes an overflow).
|
28
43
|
|
29
44
|
#### generate_key_pair
|
@@ -34,7 +49,7 @@ secure random number generator (CSRNG) provided by OpenSSL.
|
|
34
49
|
#### key_pair_from_private_key(private_key_data)
|
35
50
|
|
36
51
|
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 `
|
52
|
+
`private_key_data` is expected to be a binary string. Raises a `Secp256k1::Error`
|
38
53
|
if the private key is invalid or key derivation fails.
|
39
54
|
|
40
55
|
#### recoverable_signature_from_compact(compact_signature, recovery_id)
|
@@ -42,7 +57,7 @@ if the private key is invalid or key derivation fails.
|
|
42
57
|
**Requires:** libsecp256k1 was build with recovery module.
|
43
58
|
|
44
59
|
Attempts to load a [RecoverableSignature](recoverable_signature.md) from the given `compact_signature`
|
45
|
-
and `recovery_id`. Raises a
|
60
|
+
and `recovery_id`. Raises a `Secp256k1::DeserializationError` if the signature data or recovery ID are invalid.
|
46
61
|
|
47
62
|
#### sign(private_key, hash32)
|
48
63
|
|
data/documentation/index.md
CHANGED
@@ -48,7 +48,7 @@ This example demonstrates how to create a new libsecp256k1 context. This is the
|
|
48
48
|
first step of using this library:
|
49
49
|
|
50
50
|
```ruby
|
51
|
-
context = Secp256k1::Context.
|
51
|
+
context = Secp256k1::Context.create
|
52
52
|
# => #<Secp256k1::Context:0x0000559b0bd8f5d0>
|
53
53
|
```
|
54
54
|
|
@@ -57,7 +57,7 @@ context = Secp256k1::Context.new
|
|
57
57
|
This example shows how to generate a new public-private key pair:
|
58
58
|
|
59
59
|
```ruby
|
60
|
-
context = Secp256k1::Context.
|
60
|
+
context = Secp256k1::Context.create
|
61
61
|
key_pair = context.generate_key_pair
|
62
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
63
|
```
|
@@ -67,7 +67,7 @@ key_pair = context.generate_key_pair
|
|
67
67
|
This example shows how to generate compressed and uncompressed public keys:
|
68
68
|
|
69
69
|
```ruby
|
70
|
-
context = Secp256k1::Context.
|
70
|
+
context = Secp256k1::Context.create
|
71
71
|
key_pair = context.generate_key_pair
|
72
72
|
|
73
73
|
# 1. Get the binary representation of compressed public key
|
@@ -94,7 +94,7 @@ This example shows how to sign a message using your private key:
|
|
94
94
|
```ruby
|
95
95
|
require 'digest'
|
96
96
|
|
97
|
-
context = Secp256k1::Context.
|
97
|
+
context = Secp256k1::Context.create
|
98
98
|
key_pair = context.generate_key_pair
|
99
99
|
|
100
100
|
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
@@ -109,7 +109,7 @@ representations of a signature:
|
|
109
109
|
```ruby
|
110
110
|
require 'digest'
|
111
111
|
|
112
|
-
context = Secp256k1::Context.
|
112
|
+
context = Secp256k1::Context.create
|
113
113
|
key_pair = context.generate_key_pair
|
114
114
|
|
115
115
|
signature = context.sign(key_pair.private_key, Digest::SHA256.digest("test message"))
|
@@ -138,7 +138,7 @@ This example shows how to verify a signature using a public key:
|
|
138
138
|
```ruby
|
139
139
|
require 'digest'
|
140
140
|
|
141
|
-
context = Secp256k1::Context.
|
141
|
+
context = Secp256k1::Context.create
|
142
142
|
key_pair = context.generate_key_pair
|
143
143
|
hash = Digest::SHA256.digest("test message")
|
144
144
|
|
@@ -158,7 +158,7 @@ context.verify(signature, key_pair.public_key, hash)
|
|
158
158
|
This example shows how to load a key pair from raw binary private key data:
|
159
159
|
|
160
160
|
```ruby
|
161
|
-
context = Secp256k1::Context.
|
161
|
+
context = Secp256k1::Context.create
|
162
162
|
|
163
163
|
#1. Load private key alone
|
164
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")
|
@@ -218,7 +218,7 @@ You can sign data producing a recoverable signature as follows:
|
|
218
218
|
require 'digest'
|
219
219
|
|
220
220
|
hash = Digest::SHA256.digest('test message')
|
221
|
-
context = Secp256k1::Context.
|
221
|
+
context = Secp256k1::Context.create
|
222
222
|
key_pair = context.generate_key_pair
|
223
223
|
|
224
224
|
signature = context.sign_recoverable(key_pair.private_key, hash)
|
@@ -233,7 +233,7 @@ You can produce the compact binary serialization of a recoverable signature:
|
|
233
233
|
require 'digest'
|
234
234
|
|
235
235
|
hash = Digest::SHA256.digest('test message')
|
236
|
-
context = Secp256k1::Context.
|
236
|
+
context = Secp256k1::Context.create
|
237
237
|
key_pair = context.generate_key_pair
|
238
238
|
|
239
239
|
signature = context.sign_recoverable(key_pair.private_key, hash)
|
@@ -247,7 +247,7 @@ You can load a recoverable signature give its compact representation and
|
|
247
247
|
recovery ID:
|
248
248
|
|
249
249
|
```ruby
|
250
|
-
context = Secp256k1::Context.
|
250
|
+
context = Secp256k1::Context.create
|
251
251
|
|
252
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
253
|
recovery_id = 1
|
@@ -265,7 +265,7 @@ for use by all methods that take a [Signature](signature.md) object:
|
|
265
265
|
require 'digest'
|
266
266
|
|
267
267
|
hash = Digest::SHA256.digest('test message')
|
268
|
-
context = Secp256k1::Context.
|
268
|
+
context = Secp256k1::Context.create
|
269
269
|
key_pair = context.generate_key_pair
|
270
270
|
|
271
271
|
recoverable_signature = context.sign_recoverable(key_pair.private_key, hash)
|
@@ -281,7 +281,7 @@ You can recover the [PublicKey](public_key.md) associated with a recoverable sig
|
|
281
281
|
require 'digest'
|
282
282
|
|
283
283
|
hash = Digest::SHA256.digest('test message')
|
284
|
-
context = Secp256k1::Context.
|
284
|
+
context = Secp256k1::Context.create
|
285
285
|
key_pair = context.generate_key_pair
|
286
286
|
|
287
287
|
recoverable_signature = context.sign_recoverable(key_pair.private_key, hash)
|
@@ -310,7 +310,7 @@ Secp256k1.have_ecdh?
|
|
310
310
|
To generate a shared secret run the following:
|
311
311
|
|
312
312
|
```ruby
|
313
|
-
context = Secp256k1::Context.
|
313
|
+
context = Secp256k1::Context.create
|
314
314
|
key_pair = context.generate_key_pair
|
315
315
|
|
316
316
|
shared_secret = context.ecdh(key_pair.public_key, key_pair.private_key)
|
@@ -11,7 +11,7 @@ Class Methods
|
|
11
11
|
#### from_data(private_key_data)
|
12
12
|
|
13
13
|
Loads new private key from the given binary `private_key_data` string. Raises
|
14
|
-
`
|
14
|
+
`Secp256k1::Error` if the given data is invalid.
|
15
15
|
|
16
16
|
Instance Methods
|
17
17
|
----------------
|
data/documentation/public_key.md
CHANGED
@@ -13,8 +13,8 @@ Class Methods
|
|
13
13
|
#### from_data(public_key_data)
|
14
14
|
|
15
15
|
Parses compressed or uncompressed from binary string `public_key_data` and
|
16
|
-
creates and returns a new public key from it. Raises a `
|
17
|
-
given public key data is invalid.
|
16
|
+
creates and returns a new public key from it. Raises a `Secp256k1::DeserializationError`
|
17
|
+
if the given public key data is invalid.
|
18
18
|
|
19
19
|
Instance Methods
|
20
20
|
----------------
|
data/documentation/signature.md
CHANGED
@@ -12,12 +12,12 @@ Class Methods
|
|
12
12
|
#### from_compact(compact_signature)
|
13
13
|
|
14
14
|
Parses a signature from binary string `compact_signature`. Raises a
|
15
|
-
`
|
15
|
+
`Secp256k1::DeserializationError` if the signature data is invalid.
|
16
16
|
|
17
17
|
#### from_der_encoded(der_encoded_signature)
|
18
18
|
|
19
19
|
Parses a signature from binary string `der_encoded_signature`. Raises a
|
20
|
-
`
|
20
|
+
`Secp256k1::DeserializationError` if the signature data is invalid.
|
21
21
|
|
22
22
|
Instance Methods
|
23
23
|
----------------
|
data/ext/rbsecp256k1/extconf.rb
CHANGED
@@ -1,27 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'mini_portile2'
|
2
4
|
require 'mkmf'
|
3
5
|
require 'zip'
|
4
6
|
|
5
|
-
# Indicates the platform on which the package is being installed
|
6
|
-
INSTALLING_OS =
|
7
|
-
if RUBY_PLATFORM =~ /darwin/
|
8
|
-
:macos
|
9
|
-
elsif RUBY_PLATFORM =~ /linux/
|
10
|
-
:linux
|
11
|
-
else
|
12
|
-
:unknown
|
13
|
-
end
|
14
|
-
|
15
|
-
# Fixed path to Homebrew OpenSSL pkgconfig file
|
16
|
-
HOMEBREW_OPENSSL_PKGCONFIG = '/usr/local/opt/openssl/lib/pkgconfig'.freeze
|
17
|
-
|
18
7
|
# Recipe for downloading and building libsecp256k1 as part of installation
|
19
8
|
class Secp256k1Recipe < MiniPortile
|
20
9
|
# Hard-coded URL for libsecp256k1 zipfile (HEAD of master as of 26-11-2018)
|
21
|
-
LIBSECP256K1_ZIP_URL = 'https://github.com/bitcoin-core/secp256k1/archive/e34ceb333b1c0e6f4115ecbb80c632ac1042fa49.zip'
|
10
|
+
LIBSECP256K1_ZIP_URL = 'https://github.com/bitcoin-core/secp256k1/archive/e34ceb333b1c0e6f4115ecbb80c632ac1042fa49.zip'
|
22
11
|
|
23
12
|
# Expected SHA-256 of the zipfile above (computed using sha256sum)
|
24
|
-
LIBSECP256K1_SHA256 = 'd87d3ca7ebc42edbabb0f38e79205040b24b09b3e6d1c9ac89585de9bf302143'
|
13
|
+
LIBSECP256K1_SHA256 = 'd87d3ca7ebc42edbabb0f38e79205040b24b09b3e6d1c9ac89585de9bf302143'
|
25
14
|
|
26
15
|
WITH_RECOVERY = ENV.fetch('WITH_RECOVERY', '1') == '1'
|
27
16
|
WITH_ECDH = ENV.fetch('WITH_ECDH', '1') == '1'
|
@@ -82,46 +71,6 @@ class Secp256k1Recipe < MiniPortile
|
|
82
71
|
end
|
83
72
|
end
|
84
73
|
|
85
|
-
# OpenSSL flags
|
86
|
-
message("checking for OpenSSL\n")
|
87
|
-
results = pkg_config('openssl')
|
88
|
-
|
89
|
-
# Failed to find package OpenSSL
|
90
|
-
unless results && results[1]
|
91
|
-
# Check if the user happens to have OpenSSL installed via Homebrew on a path
|
92
|
-
# we know about.
|
93
|
-
# rubocop:disable Style/GlobalVars
|
94
|
-
if INSTALLING_OS == :macos && File.exist?(HOMEBREW_OPENSSL_PKGCONFIG)
|
95
|
-
begin
|
96
|
-
require 'rubygems'
|
97
|
-
gem 'pkg-config', (gem_ver = '~> 1.3')
|
98
|
-
require 'pkg-config'
|
99
|
-
rescue LoadError
|
100
|
-
message(
|
101
|
-
"pkg-config could not be used to find openssl\n" \
|
102
|
-
"Please install either `pkg-config` or the pkg-config gem via\n" \
|
103
|
-
"gem install pkg-config -v #{gem_ver.inspect}\n\n"
|
104
|
-
)
|
105
|
-
else
|
106
|
-
message("Initial check failed. Trying homebrew openssl path...\n")
|
107
|
-
message("Using pkg-config gem version #{PKGConfig::VERSION}\n")
|
108
|
-
PKGConfig.add_path(HOMEBREW_OPENSSL_PKGCONFIG)
|
109
|
-
|
110
|
-
cflags = PKGConfig.cflags('openssl')
|
111
|
-
ldflags = PKGConfig.libs_only_L('openssl')
|
112
|
-
libs = PKGConfig.libs_only_l('openssl')
|
113
|
-
|
114
|
-
$CFLAGS += " " << cflags if cflags
|
115
|
-
$libs += " " << libs if libs
|
116
|
-
$LDFLAGS = [$LDFLAGS, ldflags].join(' ')
|
117
|
-
|
118
|
-
results = [cflags, libs, ldflags]
|
119
|
-
end
|
120
|
-
end
|
121
|
-
# rubocop:enable Style/GlobalVars
|
122
|
-
end
|
123
|
-
abort "missing openssl pkg-config information" unless results && results[1]
|
124
|
-
|
125
74
|
if with_config('system-library')
|
126
75
|
# Require that libsecp256k1 be installed using `make install` or similar.
|
127
76
|
message("checking for libsecp256k1\n")
|
@@ -142,6 +91,11 @@ else
|
|
142
91
|
"-Wall"
|
143
92
|
]
|
144
93
|
)
|
94
|
+
append_ldflags(
|
95
|
+
[
|
96
|
+
"-Wl,--no-as-needed"
|
97
|
+
]
|
98
|
+
)
|
145
99
|
# rubocop:disable Style/GlobalVars
|
146
100
|
$LIBPATH = ["#{recipe.path}/lib"] | $LIBPATH
|
147
101
|
# rubocop:enable Style/GlobalVars
|
@@ -6,12 +6,8 @@
|
|
6
6
|
// and verifying signatures using the library.
|
7
7
|
//
|
8
8
|
// Dependencies:
|
9
|
-
//
|
10
|
-
// * openssl
|
9
|
+
// * libsecp256k1
|
11
10
|
#include <ruby.h>
|
12
|
-
|
13
|
-
#include <openssl/rand.h>
|
14
|
-
|
15
11
|
#include <secp256k1.h>
|
16
12
|
|
17
13
|
// Include recoverable signatures functionality if available
|
@@ -44,6 +40,14 @@
|
|
44
40
|
// applications. Context initialization is expensive so it is recommended that
|
45
41
|
// a single context be initialized and used throughout an application when
|
46
42
|
// possible.
|
43
|
+
//
|
44
|
+
// Exception Hierarchy:
|
45
|
+
//
|
46
|
+
// The following hierarchy is used for exceptions raised from the library:
|
47
|
+
//
|
48
|
+
// +- Error (Descends from StandardError)
|
49
|
+
// |-- SerializationError
|
50
|
+
// |-- DeserializationError
|
47
51
|
|
48
52
|
//
|
49
53
|
// The section below contains purely internal methods used exclusively by the
|
@@ -61,6 +65,9 @@ const size_t COMPACT_SIG_SIZE_BYTES = 64;
|
|
61
65
|
// objects from anywhere. The use of global variables seems to be inline with
|
62
66
|
// how the Ruby project builds its own extension gems.
|
63
67
|
static VALUE Secp256k1_module;
|
68
|
+
static VALUE Secp256k1_Error_class;
|
69
|
+
static VALUE Secp256k1_SerializationError_class;
|
70
|
+
static VALUE Secp256k1_DeserializationError_class;
|
64
71
|
static VALUE Secp256k1_Context_class;
|
65
72
|
static VALUE Secp256k1_KeyPair_class;
|
66
73
|
static VALUE Secp256k1_PublicKey_class;
|
@@ -262,33 +269,6 @@ typedef enum ResultT_dummy {
|
|
262
269
|
RESULT_FAILURE
|
263
270
|
} ResultT;
|
264
271
|
|
265
|
-
/**
|
266
|
-
* Generate a series of cryptographically secure random bytes using OpenSSL.
|
267
|
-
*
|
268
|
-
* \param out_bytes Desired number of bytes will be written here.
|
269
|
-
* \param in_size Number of bytes of random data to be generated.
|
270
|
-
* \return RESULT_SUCCESS if the bytes were generated successfully,
|
271
|
-
* RESULT_FAILURE otherwise.
|
272
|
-
*/
|
273
|
-
static ResultT
|
274
|
-
GenerateRandomBytes(unsigned char *out_bytes, int in_size)
|
275
|
-
{
|
276
|
-
// OpenSSL RNG has not been seeded with enough data and is therefore
|
277
|
-
// not usable.
|
278
|
-
if (RAND_status() == 0)
|
279
|
-
{
|
280
|
-
return RESULT_FAILURE;
|
281
|
-
}
|
282
|
-
|
283
|
-
// Attempt to generate random bytes using the OpenSSL RNG
|
284
|
-
if (RAND_bytes(out_bytes, in_size) != 1)
|
285
|
-
{
|
286
|
-
return RESULT_FAILURE;
|
287
|
-
}
|
288
|
-
|
289
|
-
return RESULT_SUCCESS;
|
290
|
-
}
|
291
|
-
|
292
272
|
/**
|
293
273
|
* Computes the ECDSA signature of the given 32-byte SHA-256 hash.
|
294
274
|
*
|
@@ -462,7 +442,7 @@ PublicKey_create_from_private_key(Context *in_context,
|
|
462
442
|
(&public_key->pubkey),
|
463
443
|
private_key_data) != 1)
|
464
444
|
{
|
465
|
-
rb_raise(
|
445
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid private key data");
|
466
446
|
}
|
467
447
|
|
468
448
|
return result;
|
@@ -483,7 +463,7 @@ PublicKey_create_from_data(unsigned char *in_public_key_data,
|
|
483
463
|
in_public_key_data,
|
484
464
|
in_public_key_data_len) != 1)
|
485
465
|
{
|
486
|
-
rb_raise(
|
466
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid public key data");
|
487
467
|
}
|
488
468
|
|
489
469
|
return result;
|
@@ -495,7 +475,7 @@ PublicKey_create_from_data(unsigned char *in_public_key_data,
|
|
495
475
|
* @param in_public_key_data [String] binary string with compressed or
|
496
476
|
* uncompressed public key data.
|
497
477
|
* @return [Secp256k1::PublicKey] public key derived from data.
|
498
|
-
* @raise [
|
478
|
+
* @raise [Secp256k1::DeserializationError] if public key data is invalid.
|
499
479
|
*/
|
500
480
|
static VALUE
|
501
481
|
PublicKey_from_data(VALUE klass, VALUE in_public_key_data)
|
@@ -631,7 +611,7 @@ PrivateKey_create(unsigned char *in_private_key_data)
|
|
631
611
|
if (secp256k1_ec_seckey_verify(secp256k1_context_no_precomp,
|
632
612
|
in_private_key_data) != 1)
|
633
613
|
{
|
634
|
-
rb_raise(
|
614
|
+
rb_raise(Secp256k1_Error_class, "invalid private key data");
|
635
615
|
}
|
636
616
|
|
637
617
|
result = PrivateKey_alloc(Secp256k1_PrivateKey_class);
|
@@ -649,7 +629,7 @@ PrivateKey_create(unsigned char *in_private_key_data)
|
|
649
629
|
* @param in_private_key_data [String] 32 byte binary string of private key
|
650
630
|
* data.
|
651
631
|
* @return [Secp256k1::PrivateKey] private key loaded from the given data.
|
652
|
-
* @raise [
|
632
|
+
* @raise [Secp256k1::Error] if private key data is not 32 bytes or is invalid.
|
653
633
|
*/
|
654
634
|
static VALUE
|
655
635
|
PrivateKey_from_data(VALUE klass, VALUE in_private_key_data)
|
@@ -659,7 +639,10 @@ PrivateKey_from_data(VALUE klass, VALUE in_private_key_data)
|
|
659
639
|
Check_Type(in_private_key_data, T_STRING);
|
660
640
|
if (RSTRING_LEN(in_private_key_data) != 32)
|
661
641
|
{
|
662
|
-
rb_raise(
|
642
|
+
rb_raise(
|
643
|
+
Secp256k1_Error_class,
|
644
|
+
"private key data must be 32 bytes in length"
|
645
|
+
);
|
663
646
|
}
|
664
647
|
|
665
648
|
private_key_data = (unsigned char*)StringValuePtr(in_private_key_data);
|
@@ -714,7 +697,7 @@ Signature_alloc(VALUE klass)
|
|
714
697
|
* @param in_compact_signature [String] compact signature as 64-byte binary
|
715
698
|
* string.
|
716
699
|
* @return [Secp256k1::Signature] object deserialized from compact signature.
|
717
|
-
* @raise [
|
700
|
+
* @raise [Secp256k1::DeserializationError] if signature data is invalid.
|
718
701
|
*/
|
719
702
|
static VALUE
|
720
703
|
Signature_from_compact(VALUE klass, VALUE in_compact_signature)
|
@@ -727,7 +710,7 @@ Signature_from_compact(VALUE klass, VALUE in_compact_signature)
|
|
727
710
|
|
728
711
|
if (RSTRING_LEN(in_compact_signature) != 64)
|
729
712
|
{
|
730
|
-
rb_raise(
|
713
|
+
rb_raise(Secp256k1_Error_class, "compact signature must be 64 bytes");
|
731
714
|
}
|
732
715
|
|
733
716
|
signature_data = (unsigned char*)StringValuePtr(in_compact_signature);
|
@@ -739,7 +722,7 @@ Signature_from_compact(VALUE klass, VALUE in_compact_signature)
|
|
739
722
|
&(signature->sig),
|
740
723
|
signature_data) != 1)
|
741
724
|
{
|
742
|
-
rb_raise(
|
725
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid compact signature");
|
743
726
|
}
|
744
727
|
|
745
728
|
return signature_result;
|
@@ -752,7 +735,7 @@ Signature_from_compact(VALUE klass, VALUE in_compact_signature)
|
|
752
735
|
* string.
|
753
736
|
* @return [Secp256k1::Signature] signature object initialized using signature
|
754
737
|
* data.
|
755
|
-
* @raise [
|
738
|
+
* @raise [Secp256k1::DeserializationError] if signature data is invalid.
|
756
739
|
*/
|
757
740
|
static VALUE
|
758
741
|
Signature_from_der_encoded(VALUE klass, VALUE in_der_encoded_signature)
|
@@ -773,7 +756,7 @@ Signature_from_der_encoded(VALUE klass, VALUE in_der_encoded_signature)
|
|
773
756
|
signature_data,
|
774
757
|
RSTRING_LEN(in_der_encoded_signature)) != 1)
|
775
758
|
{
|
776
|
-
rb_raise(
|
759
|
+
rb_raise(Secp256k1_DeserializationError_class, "invalid DER encoded signature");
|
777
760
|
}
|
778
761
|
|
779
762
|
return signature_result;
|
@@ -800,7 +783,10 @@ Signature_der_encoded(VALUE self)
|
|
800
783
|
&der_signature_len,
|
801
784
|
&(signature->sig)) != 1)
|
802
785
|
{
|
803
|
-
rb_raise(
|
786
|
+
rb_raise(
|
787
|
+
Secp256k1_SerializationError_class,
|
788
|
+
"could not compute DER encoded signature"
|
789
|
+
);
|
804
790
|
}
|
805
791
|
|
806
792
|
return rb_str_new((char*)der_signature, der_signature_len);
|
@@ -824,7 +810,10 @@ Signature_compact(VALUE self)
|
|
824
810
|
compact_signature,
|
825
811
|
&(signature->sig)) != 1)
|
826
812
|
{
|
827
|
-
rb_raise(
|
813
|
+
rb_raise(
|
814
|
+
Secp256k1_SerializationError_class,
|
815
|
+
"unable to compute compact signature"
|
816
|
+
);
|
828
817
|
}
|
829
818
|
|
830
819
|
return rb_str_new((char*)compact_signature, COMPACT_SIG_SIZE_BYTES);
|
@@ -932,7 +921,7 @@ RecoverableSignature_alloc(VALUE klass)
|
|
932
921
|
*
|
933
922
|
* @return [Array] first element is the 64 byte compact encoding of signature,
|
934
923
|
* the second element is the integer recovery ID.
|
935
|
-
* @raise [
|
924
|
+
* @raise [Secp256k1::SerializationError] if signature serialization fails.
|
936
925
|
*/
|
937
926
|
static VALUE
|
938
927
|
RecoverableSignature_compact(VALUE self)
|
@@ -955,7 +944,10 @@ RecoverableSignature_compact(VALUE self)
|
|
955
944
|
&recovery_id,
|
956
945
|
&(recoverable_signature->sig)) != 1)
|
957
946
|
{
|
958
|
-
rb_raise(
|
947
|
+
rb_raise(
|
948
|
+
Secp256k1_SerializationError_class,
|
949
|
+
"unable to serialize recoverable signature"
|
950
|
+
);
|
959
951
|
}
|
960
952
|
|
961
953
|
// Create a new array with room for 2 elements and push data onto it
|
@@ -1008,7 +1000,9 @@ RecoverableSignature_to_signature(VALUE self)
|
|
1008
1000
|
*
|
1009
1001
|
* @param in_hash32 [String] 32-byte SHA-256 hash of data.
|
1010
1002
|
* @return [Secp256k1::PublicKey] recovered public key.
|
1011
|
-
* @raise [
|
1003
|
+
* @raise [Secp256k1::Error] if hash given is not 32 bytes.
|
1004
|
+
* @raise [Secp256k1::DeserializationError] if public key could not be
|
1005
|
+
* recovered.
|
1012
1006
|
*/
|
1013
1007
|
static VALUE
|
1014
1008
|
RecoverableSignature_recover_public_key(VALUE self, VALUE in_hash32)
|
@@ -1021,7 +1015,7 @@ RecoverableSignature_recover_public_key(VALUE self, VALUE in_hash32)
|
|
1021
1015
|
Check_Type(in_hash32, T_STRING);
|
1022
1016
|
if (RSTRING_LEN(in_hash32) != 32)
|
1023
1017
|
{
|
1024
|
-
rb_raise(
|
1018
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
|
1025
1019
|
}
|
1026
1020
|
|
1027
1021
|
TypedData_Get_Struct(
|
@@ -1043,7 +1037,7 @@ RecoverableSignature_recover_public_key(VALUE self, VALUE in_hash32)
|
|
1043
1037
|
return result;
|
1044
1038
|
}
|
1045
1039
|
|
1046
|
-
rb_raise(
|
1040
|
+
rb_raise(Secp256k1_DeserializationError_class, "unable to recover public key");
|
1047
1041
|
}
|
1048
1042
|
|
1049
1043
|
/**
|
@@ -1131,14 +1125,27 @@ Context_alloc(VALUE klass)
|
|
1131
1125
|
*
|
1132
1126
|
* Context initialization should be infrequent as it is an expensive operation.
|
1133
1127
|
*
|
1128
|
+
* @param context_randomization_bytes [String,nil] (Optional) 32 bytes of
|
1129
|
+
* random data used to randomize the context. If omitted then the
|
1130
|
+
* context remains unrandomized. It is recommended that you provide this
|
1131
|
+
* argument.
|
1134
1132
|
* @return [Secp256k1::Context]
|
1135
|
-
* @raise [
|
1133
|
+
* @raise [Secp256k1::Error] if context randomization fails.
|
1136
1134
|
*/
|
1137
1135
|
static VALUE
|
1138
|
-
Context_initialize(VALUE self)
|
1136
|
+
Context_initialize(int argc, const VALUE* argv, VALUE self)
|
1139
1137
|
{
|
1140
1138
|
Context *context;
|
1141
|
-
unsigned char
|
1139
|
+
unsigned char *seed32;
|
1140
|
+
VALUE context_randomization_bytes;
|
1141
|
+
VALUE opts;
|
1142
|
+
static ID kwarg_ids;
|
1143
|
+
|
1144
|
+
context_randomization_bytes = Qnil;
|
1145
|
+
if (!kwarg_ids)
|
1146
|
+
{
|
1147
|
+
CONST_ID(kwarg_ids, "context_randomization_bytes");
|
1148
|
+
}
|
1142
1149
|
|
1143
1150
|
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
1144
1151
|
|
@@ -1146,50 +1153,46 @@ Context_initialize(VALUE self)
|
|
1146
1153
|
SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY
|
1147
1154
|
);
|
1148
1155
|
|
1149
|
-
//
|
1150
|
-
//
|
1151
|
-
|
1152
|
-
|
1156
|
+
// Handle optional second argument containing random bytes to use for
|
1157
|
+
// randomization. We pass ":" to rb_scan_args to say that we expect keyword
|
1158
|
+
// arguments. We then parse the opts result of the scan in order to grab
|
1159
|
+
// context_randomization_bytes from the hash.
|
1160
|
+
rb_scan_args(argc, argv, ":", &opts);
|
1161
|
+
rb_get_kwargs(opts, &kwarg_ids, 0, 1, &context_randomization_bytes);
|
1162
|
+
|
1163
|
+
// We need this check because rb_get_kwargs will set the result to Qundef if
|
1164
|
+
// the keyword argument is not provided. This lets us use the NIL_P
|
1165
|
+
// predicate.
|
1166
|
+
if (context_randomization_bytes == Qundef)
|
1153
1167
|
{
|
1154
|
-
|
1168
|
+
context_randomization_bytes = Qnil;
|
1155
1169
|
}
|
1156
1170
|
|
1157
|
-
|
1158
|
-
}
|
1159
|
-
|
1160
|
-
/**
|
1161
|
-
* Generate a new public-private key pair.
|
1162
|
-
*
|
1163
|
-
* @return [Secp256k1::KeyPair] newly generated key pair.
|
1164
|
-
* @raise [RuntimeError] if private key generation fails.
|
1165
|
-
*/
|
1166
|
-
static VALUE
|
1167
|
-
Context_generate_key_pair(VALUE self)
|
1168
|
-
{
|
1169
|
-
Context *context;
|
1170
|
-
VALUE private_key;
|
1171
|
-
VALUE public_key;
|
1172
|
-
VALUE result;
|
1173
|
-
unsigned char private_key_bytes[32];
|
1174
|
-
|
1175
|
-
if (FAILURE(GenerateRandomBytes(private_key_bytes, 32)))
|
1171
|
+
if (!NIL_P(context_randomization_bytes)) // Random bytes given
|
1176
1172
|
{
|
1177
|
-
|
1173
|
+
Check_Type(context_randomization_bytes, T_STRING);
|
1174
|
+
if (RSTRING_LEN(context_randomization_bytes) != 32)
|
1175
|
+
{
|
1176
|
+
rb_raise(
|
1177
|
+
Secp256k1_Error_class,
|
1178
|
+
"context_randomization_bytes must be 32 bytes in length"
|
1179
|
+
);
|
1180
|
+
}
|
1181
|
+
|
1182
|
+
seed32 = (unsigned char*)StringValuePtr(context_randomization_bytes);
|
1183
|
+
|
1184
|
+
// Randomize the context at initialization time rather than before calls so
|
1185
|
+
// the same context can be used across threads safely.
|
1186
|
+
if (secp256k1_context_randomize(context->ctx, seed32) != 1)
|
1187
|
+
{
|
1188
|
+
rb_raise(
|
1189
|
+
Secp256k1_Error_class,
|
1190
|
+
"context randomization failed"
|
1191
|
+
);
|
1192
|
+
}
|
1178
1193
|
}
|
1179
1194
|
|
1180
|
-
|
1181
|
-
|
1182
|
-
private_key = PrivateKey_create(private_key_bytes);
|
1183
|
-
public_key = PublicKey_create_from_private_key(context, private_key_bytes);
|
1184
|
-
result = rb_funcall(
|
1185
|
-
Secp256k1_KeyPair_class,
|
1186
|
-
rb_intern("new"),
|
1187
|
-
2,
|
1188
|
-
public_key,
|
1189
|
-
private_key
|
1190
|
-
);
|
1191
|
-
|
1192
|
-
return result;
|
1195
|
+
return self;
|
1193
1196
|
}
|
1194
1197
|
|
1195
1198
|
/**
|
@@ -1197,7 +1200,7 @@ Context_generate_key_pair(VALUE self)
|
|
1197
1200
|
*
|
1198
1201
|
* @param in_private_key_data [String] binary private key data
|
1199
1202
|
* @return [Secp256k1::KeyPair] key pair initialized from the private key data.
|
1200
|
-
* @raise [
|
1203
|
+
* @raise [Secp256k1::Error] if the private key data is invalid or key derivation
|
1201
1204
|
* fails.
|
1202
1205
|
*/
|
1203
1206
|
static VALUE
|
@@ -1213,7 +1216,7 @@ Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
|
|
1213
1216
|
|
1214
1217
|
if (RSTRING_LEN(in_private_key_data) != 32)
|
1215
1218
|
{
|
1216
|
-
rb_raise(
|
1219
|
+
rb_raise(Secp256k1_Error_class, "private key data must be 32 bytes in length");
|
1217
1220
|
}
|
1218
1221
|
|
1219
1222
|
private_key_data = (unsigned char*)StringValuePtr(in_private_key_data);
|
@@ -1237,8 +1240,8 @@ Context_key_pair_from_private_key(VALUE self, VALUE in_private_key_data)
|
|
1237
1240
|
* signing.
|
1238
1241
|
* @param in_hash32 [String] 32-byte binary string with SHA-256 hash of data.
|
1239
1242
|
* @return [Secp256k1::Signature] signature resulting from signing data.
|
1240
|
-
* @raise [
|
1241
|
-
*
|
1243
|
+
* @raise [Secp256k1::Error] if hash is not 32-bytes in length or signature
|
1244
|
+
* computation fails.
|
1242
1245
|
*/
|
1243
1246
|
static VALUE
|
1244
1247
|
Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
@@ -1253,7 +1256,7 @@ Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1253
1256
|
|
1254
1257
|
if (RSTRING_LEN(in_hash32) != 32)
|
1255
1258
|
{
|
1256
|
-
rb_raise(
|
1259
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
|
1257
1260
|
}
|
1258
1261
|
|
1259
1262
|
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
@@ -1272,7 +1275,7 @@ Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1272
1275
|
return signature_result;
|
1273
1276
|
}
|
1274
1277
|
|
1275
|
-
rb_raise(
|
1278
|
+
rb_raise(Secp256k1_Error_class, "unable to compute signature");
|
1276
1279
|
}
|
1277
1280
|
|
1278
1281
|
/**
|
@@ -1284,7 +1287,7 @@ Context_sign(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1284
1287
|
* @param in_hash32 [String] 32-byte binary string containing SHA-256 hash of
|
1285
1288
|
* data.
|
1286
1289
|
* @return [Boolean] True if the signature is valid, false otherwise.
|
1287
|
-
* @raise [
|
1290
|
+
* @raise [Secp256k1::Error] if hash is not 32-bytes in length.
|
1288
1291
|
*/
|
1289
1292
|
static VALUE
|
1290
1293
|
Context_verify(VALUE self, VALUE in_signature, VALUE in_pubkey, VALUE in_hash32)
|
@@ -1298,7 +1301,7 @@ Context_verify(VALUE self, VALUE in_signature, VALUE in_pubkey, VALUE in_hash32)
|
|
1298
1301
|
|
1299
1302
|
if (RSTRING_LEN(in_hash32) != 32)
|
1300
1303
|
{
|
1301
|
-
rb_raise(
|
1304
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32-bytes in length");
|
1302
1305
|
}
|
1303
1306
|
|
1304
1307
|
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
@@ -1328,7 +1331,8 @@ Context_verify(VALUE self, VALUE in_signature, VALUE in_pubkey, VALUE in_hash32)
|
|
1328
1331
|
* @param in_hash32 [String] 32-byte binary string with SHA-256 hash of data.
|
1329
1332
|
* @return [Secp256k1::RecoverableSignature] recoverable signature produced by
|
1330
1333
|
* signing the SHA-256 hash `in_hash32` with `in_private_key`.
|
1331
|
-
* @raise [
|
1334
|
+
* @raise [Secp256k1::Error] if the hash is not 32 bytes or signature could not
|
1335
|
+
* be computed.
|
1332
1336
|
*/
|
1333
1337
|
static VALUE
|
1334
1338
|
Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
@@ -1342,7 +1346,7 @@ Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1342
1346
|
Check_Type(in_hash32, T_STRING);
|
1343
1347
|
if (RSTRING_LEN(in_hash32) != 32)
|
1344
1348
|
{
|
1345
|
-
rb_raise(
|
1349
|
+
rb_raise(Secp256k1_Error_class, "in_hash32 is not 32 bytes in length");
|
1346
1350
|
}
|
1347
1351
|
|
1348
1352
|
TypedData_Get_Struct(self, Context, &Context_DataType, context);
|
@@ -1368,7 +1372,7 @@ Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1368
1372
|
return result;
|
1369
1373
|
}
|
1370
1374
|
|
1371
|
-
rb_raise(
|
1375
|
+
rb_raise(Secp256k1_Error_class, "unable to compute recoverable signature");
|
1372
1376
|
}
|
1373
1377
|
|
1374
1378
|
/**
|
@@ -1378,8 +1382,9 @@ Context_sign_recoverable(VALUE self, VALUE in_private_key, VALUE in_hash32)
|
|
1378
1382
|
* data.
|
1379
1383
|
* @param in_recovery_id [Integer] recovery ID (range [0, 3])
|
1380
1384
|
* @return [Secp256k1::RecoverableSignature] signature parsed from data.
|
1381
|
-
* @raise [
|
1382
|
-
*
|
1385
|
+
* @raise [Secp256k1::DeserializationError] if signature data or recovery ID is
|
1386
|
+
* invalid.
|
1387
|
+
* @raise [Secp256k1::Error] if compact signature is not 64 bytes or recovery ID
|
1383
1388
|
* is not in range [0, 3].
|
1384
1389
|
*/
|
1385
1390
|
static VALUE
|
@@ -1401,12 +1406,12 @@ Context_recoverable_signature_from_compact(
|
|
1401
1406
|
|
1402
1407
|
if (RSTRING_LEN(in_compact_sig) != 64)
|
1403
1408
|
{
|
1404
|
-
rb_raise(
|
1409
|
+
rb_raise(Secp256k1_Error_class, "compact signature is not 64 bytes");
|
1405
1410
|
}
|
1406
1411
|
|
1407
1412
|
if (recovery_id < 0 || recovery_id > 3)
|
1408
1413
|
{
|
1409
|
-
rb_raise(
|
1414
|
+
rb_raise(Secp256k1_Error_class, "invalid recovery ID, must be in range [0, 3]");
|
1410
1415
|
}
|
1411
1416
|
|
1412
1417
|
result = RecoverableSignature_alloc(Secp256k1_RecoverableSignature_class);
|
@@ -1427,7 +1432,7 @@ Context_recoverable_signature_from_compact(
|
|
1427
1432
|
return result;
|
1428
1433
|
}
|
1429
1434
|
|
1430
|
-
rb_raise(
|
1435
|
+
rb_raise(Secp256k1_DeserializationError_class, "unable to parse recoverable signature");
|
1431
1436
|
}
|
1432
1437
|
|
1433
1438
|
#endif // HAVE_SECP256K1_RECOVERY_H
|
@@ -1443,7 +1448,7 @@ Context_recoverable_signature_from_compact(
|
|
1443
1448
|
* @param point [Secp256k1::PublicKey] public-key representing ECDH point.
|
1444
1449
|
* @param scalar [Secp256k1::PrivateKey] private-key representing ECDH scalar.
|
1445
1450
|
* @return [Secp256k1::SharedSecret] shared secret
|
1446
|
-
* @raise [
|
1451
|
+
* @raise [Secp256k1::Error] If scalar was invalid (zero or caused overflow).
|
1447
1452
|
*/
|
1448
1453
|
static VALUE
|
1449
1454
|
Context_ecdh(VALUE self, VALUE point, VALUE scalar)
|
@@ -1470,7 +1475,7 @@ Context_ecdh(VALUE self, VALUE point, VALUE scalar)
|
|
1470
1475
|
NULL,
|
1471
1476
|
NULL) != 1)
|
1472
1477
|
{
|
1473
|
-
rb_raise(
|
1478
|
+
rb_raise(Secp256k1_Error_class, "invalid scalar provided to ecdh");
|
1474
1479
|
}
|
1475
1480
|
|
1476
1481
|
rb_iv_set(result, "@data", rb_str_new((char*)shared_secret->data, 32));
|
@@ -1522,13 +1527,6 @@ Secp256k1_have_ecdh(VALUE module)
|
|
1522
1527
|
|
1523
1528
|
void Init_rbsecp256k1()
|
1524
1529
|
{
|
1525
|
-
// NOTE: All classes derive from Data (rb_cData) rather than Object
|
1526
|
-
// (rb_cObject). This makes it so we don't have to call rb_undef_alloc_func
|
1527
|
-
// for each class and can instead simply define the allocation methods for
|
1528
|
-
// each class.
|
1529
|
-
//
|
1530
|
-
// See: https://github.com/ruby/ruby/blob/trunk/doc/extension.rdoc#encapsulate-c-data-into-a-ruby-object
|
1531
|
-
|
1532
1530
|
// Secp256k1
|
1533
1531
|
Secp256k1_module = rb_define_module("Secp256k1");
|
1534
1532
|
rb_define_singleton_method(
|
@@ -1544,19 +1542,27 @@ void Init_rbsecp256k1()
|
|
1544
1542
|
0
|
1545
1543
|
);
|
1546
1544
|
|
1545
|
+
// Secp256k1 exception hierarchy
|
1546
|
+
Secp256k1_Error_class = rb_define_class_under(
|
1547
|
+
Secp256k1_module, "Error", rb_eStandardError
|
1548
|
+
);
|
1549
|
+
Secp256k1_SerializationError_class = rb_define_class_under(
|
1550
|
+
Secp256k1_module, "SerializationError", Secp256k1_Error_class
|
1551
|
+
);
|
1552
|
+
Secp256k1_DeserializationError_class = rb_define_class_under(
|
1553
|
+
Secp256k1_module, "DeserializationError", Secp256k1_Error_class
|
1554
|
+
);
|
1555
|
+
|
1547
1556
|
// Secp256k1::Context
|
1548
1557
|
Secp256k1_Context_class = rb_define_class_under(
|
1549
|
-
Secp256k1_module, "Context",
|
1558
|
+
Secp256k1_module, "Context", rb_cObject
|
1550
1559
|
);
|
1560
|
+
rb_undef_alloc_func(Secp256k1_Context_class);
|
1551
1561
|
rb_define_alloc_func(Secp256k1_Context_class, Context_alloc);
|
1552
1562
|
rb_define_method(Secp256k1_Context_class,
|
1553
1563
|
"initialize",
|
1554
1564
|
Context_initialize,
|
1555
|
-
|
1556
|
-
rb_define_method(Secp256k1_Context_class,
|
1557
|
-
"generate_key_pair",
|
1558
|
-
Context_generate_key_pair,
|
1559
|
-
0);
|
1565
|
+
-1);
|
1560
1566
|
rb_define_method(Secp256k1_Context_class,
|
1561
1567
|
"key_pair_from_private_key",
|
1562
1568
|
Context_key_pair_from_private_key,
|
@@ -1573,7 +1579,8 @@ void Init_rbsecp256k1()
|
|
1573
1579
|
// Secp256k1::KeyPair
|
1574
1580
|
Secp256k1_KeyPair_class = rb_define_class_under(Secp256k1_module,
|
1575
1581
|
"KeyPair",
|
1576
|
-
|
1582
|
+
rb_cObject);
|
1583
|
+
rb_undef_alloc_func(Secp256k1_KeyPair_class);
|
1577
1584
|
rb_define_alloc_func(Secp256k1_KeyPair_class, KeyPair_alloc);
|
1578
1585
|
rb_define_attr(Secp256k1_KeyPair_class, "public_key", 1, 0);
|
1579
1586
|
rb_define_attr(Secp256k1_KeyPair_class, "private_key", 1, 0);
|
@@ -1586,7 +1593,8 @@ void Init_rbsecp256k1()
|
|
1586
1593
|
// Secp256k1::PublicKey
|
1587
1594
|
Secp256k1_PublicKey_class = rb_define_class_under(Secp256k1_module,
|
1588
1595
|
"PublicKey",
|
1589
|
-
|
1596
|
+
rb_cObject);
|
1597
|
+
rb_undef_alloc_func(Secp256k1_PublicKey_class);
|
1590
1598
|
rb_define_alloc_func(Secp256k1_PublicKey_class, PublicKey_alloc);
|
1591
1599
|
rb_define_method(Secp256k1_PublicKey_class,
|
1592
1600
|
"compressed",
|
@@ -1606,8 +1614,9 @@ void Init_rbsecp256k1()
|
|
1606
1614
|
|
1607
1615
|
// Secp256k1::PrivateKey
|
1608
1616
|
Secp256k1_PrivateKey_class = rb_define_class_under(
|
1609
|
-
Secp256k1_module, "PrivateKey",
|
1617
|
+
Secp256k1_module, "PrivateKey", rb_cObject
|
1610
1618
|
);
|
1619
|
+
rb_undef_alloc_func(Secp256k1_PrivateKey_class);
|
1611
1620
|
rb_define_alloc_func(Secp256k1_PrivateKey_class, PrivateKey_alloc);
|
1612
1621
|
rb_define_attr(Secp256k1_PrivateKey_class, "data", 1, 0);
|
1613
1622
|
rb_define_method(Secp256k1_PrivateKey_class, "==", PrivateKey_equals, 1);
|
@@ -1621,7 +1630,8 @@ void Init_rbsecp256k1()
|
|
1621
1630
|
// Secp256k1::Signature
|
1622
1631
|
Secp256k1_Signature_class = rb_define_class_under(Secp256k1_module,
|
1623
1632
|
"Signature",
|
1624
|
-
|
1633
|
+
rb_cObject);
|
1634
|
+
rb_undef_alloc_func(Secp256k1_Signature_class);
|
1625
1635
|
rb_define_alloc_func(Secp256k1_Signature_class, Signature_alloc);
|
1626
1636
|
rb_define_method(Secp256k1_Signature_class,
|
1627
1637
|
"der_encoded",
|
@@ -1657,8 +1667,9 @@ void Init_rbsecp256k1()
|
|
1657
1667
|
Secp256k1_RecoverableSignature_class = rb_define_class_under(
|
1658
1668
|
Secp256k1_module,
|
1659
1669
|
"RecoverableSignature",
|
1660
|
-
|
1670
|
+
rb_cObject
|
1661
1671
|
);
|
1672
|
+
rb_undef_alloc_func(Secp256k1_RecoverableSignature_class);
|
1662
1673
|
rb_define_alloc_func(
|
1663
1674
|
Secp256k1_RecoverableSignature_class,
|
1664
1675
|
RecoverableSignature_alloc
|
@@ -1707,8 +1718,9 @@ void Init_rbsecp256k1()
|
|
1707
1718
|
Secp256k1_SharedSecret_class = rb_define_class_under(
|
1708
1719
|
Secp256k1_module,
|
1709
1720
|
"SharedSecret",
|
1710
|
-
|
1721
|
+
rb_cObject
|
1711
1722
|
);
|
1723
|
+
rb_undef_alloc_func(Secp256k1_SharedSecret_class);
|
1712
1724
|
rb_define_alloc_func(Secp256k1_SharedSecret_class, SharedSecret_alloc);
|
1713
1725
|
rb_define_attr(Secp256k1_SharedSecret_class, "data", 1, 0);
|
1714
1726
|
|
data/lib/rbsecp256k1.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module Secp256k1
|
6
|
+
# Wrapper around a secp256k1_context object.
|
7
|
+
class Context
|
8
|
+
# Create a new randomized context.
|
9
|
+
#
|
10
|
+
# @return [Secp256k1::Context] randomized context
|
11
|
+
def self.create
|
12
|
+
new(context_randomization_bytes: SecureRandom.random_bytes(32))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Create a new non-randomized context.
|
16
|
+
#
|
17
|
+
# @return [Secp256k1::Context] non-randomized context
|
18
|
+
def self.create_unrandomized
|
19
|
+
new
|
20
|
+
end
|
21
|
+
|
22
|
+
# Generates a new random key pair.
|
23
|
+
#
|
24
|
+
# @return [Secp256k1::KeyPair] public-private key pair.
|
25
|
+
def generate_key_pair
|
26
|
+
key_pair_from_private_key(SecureRandom.random_bytes(32))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rbsecp256k1/util.rb
CHANGED
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: 5.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-
|
11
|
+
date: 2019-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mini_portile2
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.7'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.7'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: yard
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,6 +144,7 @@ files:
|
|
144
144
|
- ext/rbsecp256k1/extconf.rb
|
145
145
|
- ext/rbsecp256k1/rbsecp256k1.c
|
146
146
|
- lib/rbsecp256k1.rb
|
147
|
+
- lib/rbsecp256k1/context.rb
|
147
148
|
- lib/rbsecp256k1/util.rb
|
148
149
|
- lib/rbsecp256k1/version.rb
|
149
150
|
homepage: https://github.com/etscrivner/rbsecp256k1
|
@@ -170,6 +171,6 @@ rubyforge_project:
|
|
170
171
|
rubygems_version: 2.7.6
|
171
172
|
signing_key:
|
172
173
|
specification_version: 4
|
173
|
-
summary:
|
174
|
+
summary: Native extension gem for secp256k1 ECDSA. Wraps libsecp256k1. In rbsecp256k1
|
174
175
|
3.0.0 and later libsecp256k1 is bundled with the gem.
|
175
176
|
test_files: []
|