rbsecp256k1 4.0.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.com/etscrivner/rbsecp256k1.svg?branch=master)](https://travis-ci.com/etscrivner/rbsecp256k1) [![Gem Version](https://badge.fury.io/rb/rbsecp256k1.svg)](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: []
|