ring_sig 0.2.0 → 0.3.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 +5 -13
- data/.travis.yml +1 -1
- data/CHANGELOG.md +18 -0
- data/README.md +51 -18
- data/lib/ring_sig/hasher.rb +22 -9
- data/lib/ring_sig/private_key.rb +31 -52
- data/lib/ring_sig/public_key.rb +18 -29
- data/lib/ring_sig/signature.rb +21 -44
- data/lib/ring_sig/version.rb +1 -1
- data/lib/ring_sig.rb +0 -15
- data/ring_sig.gemspec +1 -1
- data/spec/hasher_spec.rb +2 -2
- data/spec/private_key_spec.rb +15 -25
- data/spec/public_key_spec.rb +8 -7
- data/spec/signature_spec.rb +4 -3
- metadata +25 -26
- data/lib/ring_sig/ecdsa/point.rb +0 -6
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MDhiZDVlZTVmYzc2YWZkYTIxY2U1NjgyOWNlMzY2YWIyM2E0MDAxMQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a9a8ff4b8548f802c19f9529c15034fc4c1329ab
|
4
|
+
data.tar.gz: 56e3a1befb6c39b8c8205e49f167598fd3fc0bfa
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MjBhN2EyNmVmOTdiMTQwYzdmODliOGIyNzJkMzdiYzIzMmVkMGZiNThiZTQ2
|
11
|
-
MmFhZDcwZWZjMDY2ZDcyZDgxOWI4ZjY1ZDUzM2IzNTA4NWI2YzU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ZWMxNjk0YzE3NzM0YmQzYjcwMDdjM2NiODBhYWFlNTA1MmQ5MmQxNWY4MDQ1
|
14
|
-
Njk4M2E1ZGM4OTA3MmQ5ZTMwZThiYmY4ZTRhZTA4ZmE2MmNlZTZiMTYzMGY4
|
15
|
-
ZWU1MTQ2ZmZlNDk2ZTUzMjUyMmRjMTFhOWY2OGU4ZGU1NjFlMmE=
|
6
|
+
metadata.gz: d07e37c8ea67cceb18a6eca210cb03ce3c29381a3fe627ed24994a83e3b1093107521cc2b9588f76d26c4469aad9cd9eb266f80e34edfadb80b999d986fb1434
|
7
|
+
data.tar.gz: 594217e061216f7e336827112e9ed01bb35772ba6b6547173eb673d3d79dd385bdd920a6c38231b21134a2e4333a8375440130d6e28b044aa95a3f4d32867305
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,24 @@ This gem follows [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html)
|
|
5
5
|
All classes and public methods are part of the public API, unless explicitly
|
6
6
|
noted otherwise in their documentation.
|
7
7
|
|
8
|
+
0.3.0
|
9
|
+
----
|
10
|
+
Released on 2014-09-15
|
11
|
+
|
12
|
+
This release breaks API compatibility with version 0.2.0.
|
13
|
+
|
14
|
+
- Change `PrivateKey`, `PublicKey`, and `Signature` constructors such that they
|
15
|
+
accept a required `Hasher` argument rather than an optional `ECDSA::Group` and
|
16
|
+
`hash_algorithm`. The `Hasher` encapsulates these properties.
|
17
|
+
- Change `Hasher` constructor so that `group` and `hash_algorithm` attributes
|
18
|
+
are passed in as explicit arguments rather than options.
|
19
|
+
- Remove `RingSig.default_group` and `RingSig.defaut_hash_algorithm` attributes.
|
20
|
+
There are now no default algorithms.
|
21
|
+
- Update gem dependency for `ecdsa` gem to 1.2.
|
22
|
+
|
23
|
+
This will hopefully be the last major API change for a while, but it still may
|
24
|
+
change until 1.0 is released.
|
25
|
+
|
8
26
|
0.2.0
|
9
27
|
----
|
10
28
|
Released on 2014-09-12
|
data/README.md
CHANGED
@@ -46,61 +46,94 @@ at RubyGems.org. To install it, run:
|
|
46
46
|
|
47
47
|
## Usage
|
48
48
|
|
49
|
+
### Initialization
|
50
|
+
|
49
51
|
First, require the gem:
|
52
|
+
|
50
53
|
```ruby
|
51
54
|
require 'ring_sig'
|
52
55
|
```
|
53
56
|
|
54
|
-
|
57
|
+
Instantiate a hasher. This specifies the `ECDSA::Group`, and the hash algorithm
|
58
|
+
that will be used for signing.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
hasher = RingSig::Hasher::Secp256k1_Sha256
|
62
|
+
```
|
63
|
+
|
64
|
+
Create a private key for signing. For our example, we'll just use the
|
55
65
|
private key `1`. In the wild, you'll want to utilize a securely generated key.
|
66
|
+
|
56
67
|
```ruby
|
57
|
-
key = RingSig::PrivateKey.new(1)
|
68
|
+
key = RingSig::PrivateKey.new(1, hasher)
|
58
69
|
```
|
59
70
|
|
60
|
-
|
71
|
+
Instantiate a set a foreign public keys for signing. To demonstrate that any
|
61
72
|
arbitrary keys can be used, we'll use the public keys from the coinbase
|
62
|
-
transactions of the first three blocks on the bitcoin blockchain
|
73
|
+
transactions of the first three blocks on the bitcoin blockchain (we can do this
|
74
|
+
since our hasher uses Secp256k1 as its `ECDSA::Group`).
|
63
75
|
|
64
76
|
```ruby
|
65
77
|
foreign_keys = %w{
|
66
78
|
04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f
|
67
79
|
0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee
|
68
80
|
047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77
|
69
|
-
}.map {|s| RingSig::PublicKey.from_hex(s) }
|
81
|
+
}.map {|s| RingSig::PublicKey.from_hex(s, hasher) }
|
70
82
|
```
|
71
83
|
|
84
|
+
### Signing
|
85
|
+
|
72
86
|
Next, we sign the message. This will assign a `RingSig::Signature` to the `sig`
|
73
87
|
variable, and a deterministically shuffled Array of `RingSig::PublicKey`s to the
|
74
88
|
`public_keys` variable.
|
89
|
+
|
75
90
|
```ruby
|
76
91
|
sig, public_keys = key.sign("Hello World!", foreign_keys)
|
77
92
|
```
|
78
93
|
|
79
|
-
You can
|
94
|
+
You can encode the contents of the signature using the `to_hex` method:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
sig_hex = sig.to_hex
|
98
|
+
```
|
99
|
+
|
100
|
+
### Verifying
|
101
|
+
In order to verify the signature, the verifier will need the signature, and the
|
102
|
+
ordered set of public keys.
|
103
|
+
|
104
|
+
In order to instantiate a signature object from a hex string, you can use the
|
105
|
+
`from_hex` method:
|
106
|
+
|
80
107
|
```ruby
|
81
|
-
|
108
|
+
sig2 = RingSig::Signature.from_hex(sig_hex, hasher)
|
82
109
|
```
|
83
110
|
|
84
111
|
Finally, verify the signature:
|
112
|
+
|
85
113
|
```ruby
|
86
|
-
|
114
|
+
sig2.verify("Hello World!", public_keys)
|
87
115
|
```
|
88
116
|
|
89
|
-
|
90
|
-
|
117
|
+
### Algorithms
|
118
|
+
|
119
|
+
The above example signature used Secp256k1 for the ECDSA group, and SHA256 for
|
120
|
+
the hash algorithm. You can specify alternates if you'd like, by using a
|
121
|
+
different hasher:
|
122
|
+
|
91
123
|
```ruby
|
92
|
-
key = RingSig::PrivateKey.new(1,
|
124
|
+
key = RingSig::PrivateKey.new(1, RingSig::Hasher::Secp384r1_Sha384)
|
93
125
|
```
|
94
126
|
|
95
|
-
You can also
|
127
|
+
You can also instantiate your own hasher directly, rather than using the
|
128
|
+
pre-defined constants:
|
129
|
+
|
96
130
|
```ruby
|
97
|
-
|
98
|
-
RingSig.default_hash_algorithm = OpenSSL::Digest::RIPEMD160
|
99
|
-
key = RingSig::PrivateKey.new(1)
|
100
|
-
puts key.group # ECDSA::Group::Secp256r1
|
101
|
-
puts key.hash_algorithm # OpenSSL::Digest::RIPEMD160
|
131
|
+
hasher = RingSig::Hasher.new(ECDSA::Group::Secp384r1, OpenSSL::Digest::SHA384)
|
102
132
|
```
|
103
133
|
|
134
|
+
Note that the byte-length of the group's order and the digest method must match,
|
135
|
+
or else the signatures generated will leak the position of the true signer.
|
136
|
+
|
104
137
|
## Standards
|
105
138
|
|
106
139
|
There currently aren't any standards around Ring Signatures that I know of. This
|
@@ -136,7 +169,7 @@ for this gem.
|
|
136
169
|
|
137
170
|
## Supported platforms
|
138
171
|
|
139
|
-
Ruby
|
172
|
+
Ruby 1.9.3 and above, including jruby-19mode.
|
140
173
|
|
141
174
|
## Documentation
|
142
175
|
|
data/lib/ring_sig/hasher.rb
CHANGED
@@ -5,17 +5,19 @@ module RingSig
|
|
5
5
|
attr_reader :group
|
6
6
|
|
7
7
|
# @return [#digest]
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :algorithm
|
9
9
|
|
10
10
|
# Creates a new instance of {Hasher}.
|
11
11
|
#
|
12
|
-
# @
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
# @note The byte-length of the group's order and the digest method must
|
13
|
+
# match, or else signatures generated from this hasher will leak the
|
14
|
+
# position of the true signer.
|
15
|
+
#
|
16
|
+
# @param group [ECDSA::Group]
|
17
|
+
# @param algorithm [#digest]
|
18
|
+
def initialize(group, algorithm)
|
19
|
+
@group = group
|
20
|
+
@algorithm = algorithm
|
19
21
|
end
|
20
22
|
|
21
23
|
# Continuously hashes until a value less than the group's order is found.
|
@@ -25,7 +27,7 @@ module RingSig
|
|
25
27
|
def hash_string(s)
|
26
28
|
n = nil
|
27
29
|
loop do
|
28
|
-
s =
|
30
|
+
s = algorithm.digest(s)
|
29
31
|
n = s.unpack('H*').first.to_i(16)
|
30
32
|
break if n < @group.order
|
31
33
|
end
|
@@ -76,6 +78,11 @@ module RingSig
|
|
76
78
|
array
|
77
79
|
end
|
78
80
|
|
81
|
+
# @return [Boolean] true if the hashers are equal.
|
82
|
+
def ==(other)
|
83
|
+
group == other.group && algorithm == other.algorithm
|
84
|
+
end
|
85
|
+
|
79
86
|
private
|
80
87
|
|
81
88
|
# Deterministically returns a random number between 0 and n.
|
@@ -91,5 +98,11 @@ module RingSig
|
|
91
98
|
return r % n if r < @group.order - @group.order % n
|
92
99
|
end
|
93
100
|
end
|
101
|
+
|
102
|
+
Secp256k1_Sha256 = new(ECDSA::Group::Secp256k1, OpenSSL::Digest::SHA256)
|
103
|
+
Secp256r1_Sha256 = new(ECDSA::Group::Secp256r1, OpenSSL::Digest::SHA256)
|
104
|
+
Secp384r1_Sha384 = new(ECDSA::Group::Secp384r1, OpenSSL::Digest::SHA384)
|
105
|
+
Secp160k1_Ripemd160 = new(ECDSA::Group::Secp160k1, OpenSSL::Digest::RIPEMD160)
|
106
|
+
Secp160r1_Ripemd160 = new(ECDSA::Group::Secp160r1, OpenSSL::Digest::RIPEMD160)
|
94
107
|
end
|
95
108
|
end
|
data/lib/ring_sig/private_key.rb
CHANGED
@@ -11,65 +11,44 @@ module RingSig
|
|
11
11
|
# @return [PublicKey]
|
12
12
|
attr_reader :public_key
|
13
13
|
|
14
|
-
# @return [
|
15
|
-
attr_reader :
|
16
|
-
|
17
|
-
# @return [#digest]
|
18
|
-
attr_reader :hash_algorithm
|
14
|
+
# @return [Hasher]
|
15
|
+
attr_reader :hasher
|
19
16
|
|
20
17
|
# Creates a new instance of {PrivateKey}.
|
21
18
|
#
|
22
19
|
# @param value [Integer]
|
23
|
-
# @param
|
24
|
-
|
25
|
-
# @option opts :hash_algorithm [#digest]
|
26
|
-
def initialize(value, opts = {})
|
27
|
-
@group = opts.delete(:group) { RingSig.default_group }
|
28
|
-
@hash_algorithm = opts.delete(:hash_algorithm) { RingSig.default_hash_algorithm }
|
29
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
30
|
-
|
20
|
+
# @param hasher [Hasher]
|
21
|
+
def initialize(value, hasher)
|
31
22
|
raise ArgumentError, "Value is not an integer" unless value.is_a?(Integer)
|
32
23
|
raise ArgumentError, "Value is too small" if value < 1
|
33
|
-
raise ArgumentError, "Value is too large" if value >= group.order
|
24
|
+
raise ArgumentError, "Value is too large" if value >= hasher.group.order
|
34
25
|
|
35
26
|
@value = value
|
36
|
-
@
|
37
|
-
@
|
27
|
+
@hasher = hasher
|
28
|
+
@public_key = PublicKey.new(hasher.group.generator * value, hasher)
|
38
29
|
end
|
39
30
|
|
40
31
|
# Creates a new instance of {PrivateKey} from a hex string.
|
41
32
|
#
|
42
33
|
# @param hex_string [String]
|
43
|
-
# @param
|
44
|
-
# @option opts :group [ECDSA::Group]
|
45
|
-
# @option opts :hash_algorithm [#digest]
|
34
|
+
# @param hasher [Hasher]
|
46
35
|
# @return [PrivateKey]
|
47
|
-
def self.from_hex(hex_string,
|
48
|
-
|
49
|
-
hash_algorithm = opts.delete(:hash_algorithm) { RingSig.default_hash_algorithm }
|
50
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
51
|
-
|
52
|
-
self.from_octet([hex_string].pack('H*'), group: group, hash_algorithm: hash_algorithm)
|
36
|
+
def self.from_hex(hex_string, hasher)
|
37
|
+
self.from_octet([hex_string].pack('H*'), hasher)
|
53
38
|
end
|
54
39
|
|
55
40
|
# Creates a new instance of {PrivateKey} from an octet string.
|
56
41
|
#
|
57
42
|
# @param octet_string [String]
|
58
|
-
# @param
|
59
|
-
# @option opts :group [ECDSA::Group]
|
60
|
-
# @option opts :hash_algorithm [#digest]
|
43
|
+
# @param hasher [Hasher]
|
61
44
|
# @return [PrivateKey]
|
62
|
-
def self.from_octet(octet_string,
|
63
|
-
|
64
|
-
|
65
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
66
|
-
|
67
|
-
value = ECDSA::Format::FieldElementOctetString.decode(octet_string, group.field)
|
68
|
-
PrivateKey.new(value, group: group, hash_algorithm: hash_algorithm)
|
45
|
+
def self.from_octet(octet_string, hasher)
|
46
|
+
value = ECDSA::Format::FieldElementOctetString.decode(octet_string, hasher.group.field)
|
47
|
+
PrivateKey.new(value, hasher)
|
69
48
|
end
|
70
49
|
|
71
50
|
# Encodes this private key into an octet string. The encoded data contains
|
72
|
-
# only the value. It does not contain the
|
51
|
+
# only the value. It does not contain the hasher.
|
73
52
|
#
|
74
53
|
# @return [String]
|
75
54
|
def to_hex
|
@@ -77,11 +56,11 @@ module RingSig
|
|
77
56
|
end
|
78
57
|
|
79
58
|
# Encodes this public key into a hex string. The encoded data contains
|
80
|
-
# only the value. It does not contain the
|
59
|
+
# only the value. It does not contain the hasher.
|
81
60
|
#
|
82
61
|
# @return [String]
|
83
62
|
def to_octet
|
84
|
-
ECDSA::Format::FieldElementOctetString.encode(value, group.field)
|
63
|
+
ECDSA::Format::FieldElementOctetString.encode(value, hasher.group.field)
|
85
64
|
end
|
86
65
|
|
87
66
|
# Signs a message with this key's private key and a set of foreign public
|
@@ -95,27 +74,27 @@ module RingSig
|
|
95
74
|
# @return [Array(Signature, Array<PublicKey>)] A pair containing the signature
|
96
75
|
# and the set of public keys (in the correct order) for verifying.
|
97
76
|
def sign(message, foreign_keys)
|
98
|
-
raise ArgumentError "Foreign keys must all have the same
|
77
|
+
raise ArgumentError "Foreign keys must all have the same hasher" unless foreign_keys.all?{ |e| e.hasher == hasher }
|
99
78
|
|
100
|
-
message_digest =
|
101
|
-
seed =
|
79
|
+
message_digest = hasher.hash_string(message)
|
80
|
+
seed = hasher.hash_array([value, message_digest])
|
102
81
|
|
103
|
-
all_keys =
|
82
|
+
all_keys = hasher.shuffle([self] + foreign_keys, seed)
|
104
83
|
|
105
84
|
q_array, w_array = generate_q_w(all_keys, seed)
|
106
85
|
ll_array, rr_array = generate_ll_rr(all_keys, q_array, w_array)
|
107
|
-
challenge =
|
86
|
+
challenge = hasher.hash_array([message_digest] + ll_array + rr_array)
|
108
87
|
c_array, r_array = generate_c_r(all_keys, q_array, w_array, challenge)
|
109
88
|
|
110
89
|
public_keys = all_keys.map(&:public_key)
|
111
|
-
signature = Signature.new(key_image, c_array, r_array,
|
90
|
+
signature = Signature.new(key_image, c_array, r_array, hasher)
|
112
91
|
|
113
92
|
[signature, public_keys]
|
114
93
|
end
|
115
94
|
|
116
95
|
# @return [ECDSA::Point] the key image.
|
117
96
|
def key_image
|
118
|
-
@key_image ||=
|
97
|
+
@key_image ||= hasher.hash_point(point) * value
|
119
98
|
end
|
120
99
|
|
121
100
|
# @return [ECDSA::Point] the public key's point.
|
@@ -126,7 +105,7 @@ module RingSig
|
|
126
105
|
# @return [Boolean] true if the private keys are equal.
|
127
106
|
def ==(other)
|
128
107
|
return false unless other.is_a?(PrivateKey)
|
129
|
-
value == other.value &&
|
108
|
+
value == other.value && hasher == other.hasher
|
130
109
|
end
|
131
110
|
|
132
111
|
private
|
@@ -135,9 +114,9 @@ module RingSig
|
|
135
114
|
q_array, w_array = [], []
|
136
115
|
|
137
116
|
all_keys.each_with_index do |k, i|
|
138
|
-
q_array[i] =
|
117
|
+
q_array[i] = hasher.hash_array(['q', seed, i])
|
139
118
|
w_array[i] = 0
|
140
|
-
w_array[i] =
|
119
|
+
w_array[i] = hasher.hash_array(['w', seed, i]) if k.is_a?(PublicKey)
|
141
120
|
end
|
142
121
|
|
143
122
|
[q_array, w_array]
|
@@ -147,8 +126,8 @@ module RingSig
|
|
147
126
|
ll_array, rr_array = [], []
|
148
127
|
|
149
128
|
all_keys.each_with_index do |k, i|
|
150
|
-
ll_array[i] = group.generator * q_array[i]
|
151
|
-
rr_array[i] =
|
129
|
+
ll_array[i] = hasher.group.generator * q_array[i]
|
130
|
+
rr_array[i] = hasher.hash_point(k.point) * q_array[i]
|
152
131
|
if k.is_a?(PublicKey)
|
153
132
|
ll_array[i] += k.point * w_array[i]
|
154
133
|
rr_array[i] += key_image * w_array[i]
|
@@ -166,8 +145,8 @@ module RingSig
|
|
166
145
|
c_array[i] = w_array[i]
|
167
146
|
r_array[i] = q_array[i]
|
168
147
|
else
|
169
|
-
c_array[i] = (challenge - w_array.inject{|a, b| a + b}) % group.order
|
170
|
-
r_array[i] = (q_array[i] - c_array[i] * k.value) % group.order
|
148
|
+
c_array[i] = (challenge - w_array.inject{|a, b| a + b}) % hasher.group.order
|
149
|
+
r_array[i] = (q_array[i] - c_array[i] * k.value) % hasher.group.order
|
171
150
|
end
|
172
151
|
end
|
173
152
|
|
data/lib/ring_sig/public_key.rb
CHANGED
@@ -7,56 +7,45 @@ module RingSig
|
|
7
7
|
# @return [ECDSA::Point]
|
8
8
|
attr_reader :point
|
9
9
|
|
10
|
-
# @return [
|
11
|
-
attr_reader :
|
10
|
+
# @return [Hasher]
|
11
|
+
attr_reader :hasher
|
12
12
|
|
13
13
|
# Creates a new instance of {PublicKey}.
|
14
14
|
#
|
15
15
|
# @param point [ECDSA::Point]
|
16
|
-
# @param
|
17
|
-
|
18
|
-
def initialize(point, opts = {})
|
19
|
-
@group = opts.delete(:group) { RingSig.default_group }
|
20
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
21
|
-
|
16
|
+
# @param hasher [Hasher]
|
17
|
+
def initialize(point, hasher)
|
22
18
|
raise ArgumentError, "Point is not an ECDSA::Point" unless point.is_a?(ECDSA::Point)
|
23
|
-
raise ArgumentError, "Point is not on the group's curve" unless group.include?(point)
|
19
|
+
raise ArgumentError, "Point is not on the group's curve" unless hasher.group.include?(point)
|
24
20
|
|
25
21
|
@point = point
|
22
|
+
@hasher = hasher
|
26
23
|
end
|
27
24
|
|
28
25
|
# Creates a new instance of {PublicKey} from a hex string.
|
29
26
|
#
|
30
27
|
# @param hex_string [String]
|
31
|
-
# @param
|
32
|
-
# @option opts :group [ECDSA::Group]
|
28
|
+
# @param hasher [Hasher]
|
33
29
|
# @return [PublicKey]
|
34
|
-
def self.from_hex(hex_string,
|
35
|
-
|
36
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
37
|
-
|
38
|
-
self.from_octet([hex_string].pack('H*'), group: group)
|
30
|
+
def self.from_hex(hex_string, hasher)
|
31
|
+
self.from_octet([hex_string].pack('H*'), hasher)
|
39
32
|
end
|
40
33
|
|
41
34
|
# Creates a new instance of {PublicKey} from an octet string.
|
42
35
|
#
|
43
36
|
# @param octet_string [String]
|
44
|
-
# @param
|
45
|
-
# @option opts :group [ECDSA::Group]
|
37
|
+
# @param hasher [Hasher]
|
46
38
|
# @return [PublicKey]
|
47
|
-
def self.from_octet(octet_string,
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
point = ECDSA::Format::PointOctetString.decode(octet_string, group)
|
52
|
-
PublicKey.new(point, group: group)
|
39
|
+
def self.from_octet(octet_string, hasher)
|
40
|
+
point = ECDSA::Format::PointOctetString.decode(octet_string, hasher.group)
|
41
|
+
PublicKey.new(point, hasher)
|
53
42
|
end
|
54
43
|
|
55
44
|
# Encodes this public key into an octet string. The encoded data contains
|
56
|
-
# only the point. It does not contain the
|
45
|
+
# only the point. It does not contain the hasher.
|
57
46
|
#
|
58
47
|
# @param opts [Hash]
|
59
|
-
# @option opts :compression
|
48
|
+
# @option opts [Boolean] :compression (true)
|
60
49
|
# @return [String]
|
61
50
|
def to_hex(opts = {})
|
62
51
|
compression = opts.delete(:compression) { true }
|
@@ -66,10 +55,10 @@ module RingSig
|
|
66
55
|
end
|
67
56
|
|
68
57
|
# Encodes this public key into a hex string. The encoded data contains
|
69
|
-
# only the point. It does not contain the
|
58
|
+
# only the point. It does not contain the hasher.
|
70
59
|
#
|
71
60
|
# @param opts [Hash]
|
72
|
-
# @option opts :compression
|
61
|
+
# @option opts [Boolean] :compression (true)
|
73
62
|
# @return [String]
|
74
63
|
def to_octet(opts = {})
|
75
64
|
compression = opts.delete(:compression) { true }
|
@@ -86,7 +75,7 @@ module RingSig
|
|
86
75
|
# @return [Boolean] true if the public keys are equal.
|
87
76
|
def ==(other)
|
88
77
|
return false unless other.is_a?(PublicKey)
|
89
|
-
point == other.point &&
|
78
|
+
point == other.point && hasher == other.hasher
|
90
79
|
end
|
91
80
|
end
|
92
81
|
end
|
data/lib/ring_sig/signature.rb
CHANGED
@@ -10,75 +10,53 @@ module RingSig
|
|
10
10
|
# @return [Array]
|
11
11
|
attr_reader :r_array
|
12
12
|
|
13
|
-
# @return [
|
14
|
-
attr_reader :
|
15
|
-
|
16
|
-
# @return [#digest]
|
17
|
-
attr_reader :hash_algorithm
|
13
|
+
# @return [Hasher]
|
14
|
+
attr_reader :hasher
|
18
15
|
|
19
16
|
# Creates a new instance of {Signature}.
|
20
17
|
#
|
21
18
|
# @param key_image [ECDSA::Point]
|
22
19
|
# @param c_array [Array<Integer>]
|
23
20
|
# @param r_array [Array<Integer>]
|
24
|
-
# @param
|
25
|
-
|
26
|
-
# @option opts :hash_algorithm [#digest]
|
27
|
-
def initialize(key_image, c_array, r_array, opts = {})
|
28
|
-
@group = opts.delete(:group) { RingSig.default_group }
|
29
|
-
@hash_algorithm = opts.delete(:hash_algorithm) { RingSig.default_hash_algorithm }
|
30
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
31
|
-
|
21
|
+
# @param hasher [Hasher]
|
22
|
+
def initialize(key_image, c_array, r_array, hasher)
|
32
23
|
@key_image, @c_array, @r_array = key_image, c_array, r_array
|
33
24
|
key_image.is_a?(ECDSA::Point) or raise ArgumentError, 'key_image is not an ECDSA::Point.'
|
34
25
|
c_array.is_a?(Array) or raise ArgumentError, 'c_array is not an array.'
|
35
26
|
r_array.is_a?(Array) or raise ArgumentError, 'r_array is not an array.'
|
36
27
|
|
37
|
-
@hasher =
|
28
|
+
@hasher = hasher
|
38
29
|
end
|
39
30
|
|
40
31
|
# Creates a new instance of {Signature} from a der string.
|
41
32
|
#
|
42
33
|
# @param der_string [String]
|
43
|
-
# @param
|
44
|
-
# @option opts :group [ECDSA::Group]
|
45
|
-
# @option opts :hash_algorithm [#digest]
|
34
|
+
# @param hasher [Hasher]
|
46
35
|
# @return [Signature]
|
47
|
-
def self.from_der(der_string,
|
48
|
-
group = opts.delete(:group) { RingSig.default_group }
|
49
|
-
hash_algorithm = opts.delete(:hash_algorithm) { RingSig.default_hash_algorithm }
|
50
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
51
|
-
|
36
|
+
def self.from_der(der_string, hasher)
|
52
37
|
asn1 = OpenSSL::ASN1.decode(der_string)
|
53
38
|
|
54
|
-
key_image = ECDSA::Format::PointOctetString.decode(asn1.value[0].value, group)
|
39
|
+
key_image = ECDSA::Format::PointOctetString.decode(asn1.value[0].value, hasher.group)
|
55
40
|
c_array = asn1.value[1].value.map{|i| i.value.to_i}
|
56
41
|
r_array = asn1.value[2].value.map{|i| i.value.to_i}
|
57
42
|
|
58
|
-
Signature.new(key_image, c_array, r_array,
|
43
|
+
Signature.new(key_image, c_array, r_array, hasher)
|
59
44
|
end
|
60
45
|
|
61
46
|
# Creates a new instance of {Signature} from a hex string.
|
62
47
|
#
|
63
48
|
# @param hex_string [String]
|
64
|
-
# @param
|
65
|
-
# @option opts :group [ECDSA::Group]
|
66
|
-
# @option opts :hash_algorithm [#digest]
|
49
|
+
# @param hasher [Hasher]
|
67
50
|
# @return [Signature]
|
68
|
-
def self.from_hex(hex_string,
|
69
|
-
|
70
|
-
hash_algorithm = opts.delete(:hash_algorithm) { RingSig.default_hash_algorithm }
|
71
|
-
raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?
|
72
|
-
|
73
|
-
Signature.from_der([hex_string].pack('H*'), group: group, hash_algorithm: hash_algorithm)
|
51
|
+
def self.from_hex(hex_string, hasher)
|
52
|
+
Signature.from_der([hex_string].pack('H*'), hasher)
|
74
53
|
end
|
75
54
|
|
76
55
|
# Encodes this signature into a der string. The encoded data contains
|
77
|
-
# the key_image, c_array, and r_array. It does not contain the
|
78
|
-
# or hash_algorithm.
|
56
|
+
# the key_image, c_array, and r_array. It does not contain the hasher.
|
79
57
|
#
|
80
58
|
# @param opts [Hash]
|
81
|
-
# @option opts :compression
|
59
|
+
# @option opts [Boolean] :compression (true)
|
82
60
|
# @return [String]
|
83
61
|
def to_der(opts = {})
|
84
62
|
compression = opts.delete(:compression) { true }
|
@@ -92,11 +70,10 @@ module RingSig
|
|
92
70
|
end
|
93
71
|
|
94
72
|
# Encodes this signature into a hex string. The encoded data contains
|
95
|
-
# the key_image, c_array, and r_array. It does not contain the
|
96
|
-
# or hash_algorithm.
|
73
|
+
# the key_image, c_array, and r_array. It does not contain the hasher.
|
97
74
|
#
|
98
75
|
# @param opts [Hash]
|
99
|
-
# @option opts :compression
|
76
|
+
# @option opts [Boolean] :compression (true)
|
100
77
|
# @return [String]
|
101
78
|
def to_hex(opts = {})
|
102
79
|
compression = opts.delete(:compression) { true }
|
@@ -115,14 +92,14 @@ module RingSig
|
|
115
92
|
rr_array = []
|
116
93
|
|
117
94
|
public_keys.each_with_index do |k, i|
|
118
|
-
ll_array[i] = (group.generator * r_array[i]) + (k.point * c_array[i])
|
119
|
-
rr_array[i] = (
|
95
|
+
ll_array[i] = (hasher.group.generator * r_array[i]) + (k.point * c_array[i])
|
96
|
+
rr_array[i] = (hasher.hash_point(k.point) * (r_array[i]) + key_image * c_array[i])
|
120
97
|
end
|
121
98
|
|
122
|
-
c_sum = c_array.inject{|a, b| a + b} % group.order
|
99
|
+
c_sum = c_array.inject{|a, b| a + b} % hasher.group.order
|
123
100
|
|
124
|
-
message_digest =
|
125
|
-
challenge =
|
101
|
+
message_digest = hasher.hash_string(message)
|
102
|
+
challenge = hasher.hash_array([message_digest] + ll_array + rr_array)
|
126
103
|
|
127
104
|
c_sum == challenge
|
128
105
|
end
|
data/lib/ring_sig/version.rb
CHANGED
data/lib/ring_sig.rb
CHANGED
@@ -5,22 +5,7 @@ require 'ring_sig/private_key'
|
|
5
5
|
require 'ring_sig/public_key'
|
6
6
|
require 'ring_sig/signature'
|
7
7
|
require 'ring_sig/version'
|
8
|
-
require 'ring_sig/ecdsa/point'
|
9
8
|
|
10
9
|
# The top-level module for the RingSig gem.
|
11
10
|
module RingSig
|
12
|
-
class << self
|
13
|
-
# @return [ECDSA::Group] the default group. This group will be used in any
|
14
|
-
# method in the RingSig library that calls for a group, if none is
|
15
|
-
# specified. Starts as `ECDSA::Group::Secp256k1`.
|
16
|
-
attr_accessor :default_group
|
17
|
-
|
18
|
-
# @return [#digest] the default hash algorithm. This hash algorithm will be
|
19
|
-
# used in any method in the RingSig library that calls for a hash
|
20
|
-
# algorithm, if none is specified. Starts as `OpenSSL::Digest::SHA256`.
|
21
|
-
attr_accessor :default_hash_algorithm
|
22
|
-
end
|
23
|
-
|
24
|
-
self.default_group = ECDSA::Group::Secp256k1
|
25
|
-
self.default_hash_algorithm = OpenSSL::Digest::SHA256
|
26
11
|
end
|
data/ring_sig.gemspec
CHANGED
data/spec/hasher_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe RingSig::Hasher do
|
|
4
4
|
context 'Standard: SHA256 hash algorithm, secp256k1 group' do
|
5
5
|
group = ECDSA::Group::Secp256k1
|
6
6
|
hash_algorithm = OpenSSL::Digest::SHA256
|
7
|
-
hasher = RingSig::Hasher.new(group
|
7
|
+
hasher = RingSig::Hasher.new(group, hash_algorithm)
|
8
8
|
|
9
9
|
describe '#hash_string' do
|
10
10
|
it 'hashes "a"' do
|
@@ -67,7 +67,7 @@ describe RingSig::Hasher do
|
|
67
67
|
SimpleHashAlgorithm
|
68
68
|
end
|
69
69
|
|
70
|
-
let(:hasher) { RingSig::Hasher.new(group
|
70
|
+
let(:hasher) { RingSig::Hasher.new(group, hash_algorithm) }
|
71
71
|
|
72
72
|
# We test the hash_algorithm itself in this context, since we implemented our own simple hash_algorithm.
|
73
73
|
shared_examples_for 'hash algorithm' do |input, expected_value|
|
data/spec/private_key_spec.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe RingSig::PrivateKey do
|
4
|
-
|
4
|
+
hasher = RingSig::Hasher::Secp256k1_Sha256
|
5
|
+
key = RingSig::PrivateKey.new(1, hasher)
|
5
6
|
key_hex = '0000000000000000000000000000000000000000000000000000000000000001'
|
6
7
|
group = ECDSA::Group::Secp256k1
|
7
8
|
message = 'a'
|
@@ -10,14 +11,14 @@ describe RingSig::PrivateKey do
|
|
10
11
|
04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f
|
11
12
|
0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee
|
12
13
|
047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77
|
13
|
-
}.map {|s| RingSig::PublicKey.from_hex(s) }
|
14
|
+
}.map {|s| RingSig::PublicKey.from_hex(s, hasher) }
|
14
15
|
|
15
16
|
it 'raises ArgumentError if value is too small' do
|
16
|
-
expect { RingSig::PrivateKey.new(0) }.to raise_error(ArgumentError)
|
17
|
+
expect { RingSig::PrivateKey.new(0, hasher) }.to raise_error(ArgumentError)
|
17
18
|
end
|
18
19
|
|
19
20
|
it 'raises ArgumentError if value is too large' do
|
20
|
-
expect { RingSig::PrivateKey.new(group.order) }.to raise_error(ArgumentError)
|
21
|
+
expect { RingSig::PrivateKey.new(group.order, hasher) }.to raise_error(ArgumentError)
|
21
22
|
end
|
22
23
|
|
23
24
|
describe '#key_image' do
|
@@ -47,7 +48,7 @@ describe RingSig::PrivateKey do
|
|
47
48
|
|
48
49
|
describe '#from_hex' do
|
49
50
|
it 'converts from hex' do
|
50
|
-
expect(RingSig::PrivateKey.from_hex(key_hex)).to eq key
|
51
|
+
expect(RingSig::PrivateKey.from_hex(key_hex, hasher)).to eq key
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
@@ -59,18 +60,18 @@ describe RingSig::PrivateKey do
|
|
59
60
|
|
60
61
|
describe '#from_octet' do
|
61
62
|
it 'converts from octet' do
|
62
|
-
expect(RingSig::PrivateKey.from_octet([key_hex].pack('H*'))).to eq key
|
63
|
+
expect(RingSig::PrivateKey.from_octet([key_hex].pack('H*'), hasher)).to eq key
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
66
67
|
describe '==' do
|
67
68
|
it 'returns true when keys are the same' do
|
68
69
|
expect(key).to eq key
|
69
|
-
expect(RingSig::PrivateKey.new(key.value) == key).to eq true
|
70
|
+
expect(RingSig::PrivateKey.new(key.value, hasher) == key).to eq true
|
70
71
|
end
|
71
72
|
|
72
73
|
it 'returns false when keys are different' do
|
73
|
-
expect(RingSig::PrivateKey.new(2) == key).to eq false
|
74
|
+
expect(RingSig::PrivateKey.new(2, hasher) == key).to eq false
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
@@ -105,33 +106,22 @@ describe RingSig::PrivateKey do
|
|
105
106
|
end
|
106
107
|
end
|
107
108
|
|
108
|
-
context 'alternate
|
109
|
+
context 'alternate hasher' do
|
109
110
|
before(:all) do
|
110
|
-
@
|
111
|
-
@old_default_hash_algorithm = RingSig.default_hash_algorithm
|
112
|
-
RingSig.default_group = ECDSA::Group::Secp256r1
|
113
|
-
RingSig.default_hash_algorithm = OpenSSL::Digest::RIPEMD160
|
114
|
-
|
115
|
-
@key = RingSig::PrivateKey.new(1)
|
111
|
+
@key = RingSig::PrivateKey.new(1, RingSig::Hasher::Secp160k1_Ripemd160)
|
116
112
|
@foreign_keys = [
|
117
|
-
RingSig::PrivateKey.new(2).public_key,
|
118
|
-
RingSig::PrivateKey.new(3).public_key,
|
119
|
-
RingSig::PrivateKey.new(4).public_key,
|
113
|
+
RingSig::PrivateKey.new(2, RingSig::Hasher::Secp160k1_Ripemd160).public_key,
|
114
|
+
RingSig::PrivateKey.new(3, RingSig::Hasher::Secp160k1_Ripemd160).public_key,
|
120
115
|
]
|
121
116
|
end
|
122
117
|
|
123
|
-
after(:all) do
|
124
|
-
RingSig.default_group = @old_default_group
|
125
|
-
RingSig.default_hash_algorithm = @old_default_hash_algorithm
|
126
|
-
end
|
127
|
-
|
128
118
|
describe '#sign' do
|
129
119
|
it 'signs and verifies' do
|
130
120
|
sig, public_keys = @key.sign(message, @foreign_keys)
|
131
121
|
|
132
|
-
expect(sig.to_hex).to eq '
|
122
|
+
expect(sig.to_hex).to eq '3081a004150335d6eb01d7c658c2aae34e1e910e1b44c993069d30430214685baa33eacec37ff3530d710ca852731e1ac7b0021500881bf1e9c67d05c7a8a6ef93552a7852466034360214211b72b5e3a934d0e096441c5208b4322a83b7a130420214098d90e6e0a5e08186815be4a20a41480d55d7c202141cd9f8cc0df48519ecd6ad6e354ca634c8b604c2021415019f51cc2480ef6148dcd35a4be28037bf8899'
|
133
123
|
|
134
|
-
expected_public_keys = [
|
124
|
+
expected_public_keys = [2, 1, 0].map{|i| ([@key] + @foreign_keys)[i].public_key}
|
135
125
|
expect(public_keys).to eq expected_public_keys
|
136
126
|
|
137
127
|
expect(sig.verify(message, public_keys)).to be true
|
data/spec/public_key_spec.rb
CHANGED
@@ -4,10 +4,11 @@ describe RingSig::PublicKey do
|
|
4
4
|
compressed_hex = '03678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb6'
|
5
5
|
uncompressed_hex = '04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f'
|
6
6
|
group = ECDSA::Group::Secp256k1
|
7
|
+
hasher = RingSig::Hasher::Secp256k1_Sha256
|
7
8
|
key = RingSig::PublicKey.new(group.new_point([
|
8
9
|
46833799212576611471711417854818141128240043280360231002189938627535641370294,
|
9
10
|
33454781559405909841731692443380420218121109572881027288991311028992835919199
|
10
|
-
]))
|
11
|
+
]), hasher)
|
11
12
|
|
12
13
|
describe '#to_hex' do
|
13
14
|
it 'converts to compressed hex' do
|
@@ -21,11 +22,11 @@ describe RingSig::PublicKey do
|
|
21
22
|
|
22
23
|
describe '#from_hex' do
|
23
24
|
it 'converts from compressed hex' do
|
24
|
-
expect(RingSig::PublicKey.from_hex(compressed_hex)).to eq key
|
25
|
+
expect(RingSig::PublicKey.from_hex(compressed_hex, hasher)).to eq key
|
25
26
|
end
|
26
27
|
|
27
28
|
it 'converts from uncompressed hex' do
|
28
|
-
expect(RingSig::PublicKey.from_hex(uncompressed_hex)).to eq key
|
29
|
+
expect(RingSig::PublicKey.from_hex(uncompressed_hex, hasher)).to eq key
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
@@ -41,22 +42,22 @@ describe RingSig::PublicKey do
|
|
41
42
|
|
42
43
|
describe '#from_octet' do
|
43
44
|
it 'converts from compressed octet' do
|
44
|
-
expect(RingSig::PublicKey.from_octet([compressed_hex].pack('H*'))).to eq key
|
45
|
+
expect(RingSig::PublicKey.from_octet([compressed_hex].pack('H*'), hasher)).to eq key
|
45
46
|
end
|
46
47
|
|
47
48
|
it 'converts from uncompressed octet' do
|
48
|
-
expect(RingSig::PublicKey.from_octet([uncompressed_hex].pack('H*'))).to eq key
|
49
|
+
expect(RingSig::PublicKey.from_octet([uncompressed_hex].pack('H*'), hasher)).to eq key
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
52
53
|
describe '==' do
|
53
54
|
it 'returns true when keys are the same' do
|
54
55
|
expect(key).to eq key
|
55
|
-
expect(RingSig::PublicKey.new(key.point) == key).to eq true
|
56
|
+
expect(RingSig::PublicKey.new(key.point, hasher) == key).to eq true
|
56
57
|
end
|
57
58
|
|
58
59
|
it 'returns false when keys are different' do
|
59
|
-
expect(RingSig::PublicKey.new(group.generator) == key).to eq false
|
60
|
+
expect(RingSig::PublicKey.new(group.generator, hasher) == key).to eq false
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
data/spec/signature_spec.rb
CHANGED
@@ -2,7 +2,8 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe RingSig::Signature do
|
4
4
|
group = ECDSA::Group::Secp256k1
|
5
|
-
|
5
|
+
hasher = RingSig::Hasher::Secp256k1_Sha256
|
6
|
+
signature = RingSig::Signature.new(group.generator, [10], [20], hasher)
|
6
7
|
sig_hex = '302d04210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798300302010a3003020114'
|
7
8
|
sig_der = "0-\x04!\x02y\xBEf~\xF9\xDC\xBB\xACU\xA0b\x95\xCE\x87\v\a\x02\x9B\xFC\xDB-\xCE(\xD9Y\xF2\x81[\x16\xF8\x17\x980\x03\x02\x01\n0\x03\x02\x01\x14".force_encoding('binary')
|
8
9
|
|
@@ -36,13 +37,13 @@ describe RingSig::Signature do
|
|
36
37
|
|
37
38
|
describe '#from_hex' do
|
38
39
|
it 'converts from hex correctly' do
|
39
|
-
expect(RingSig::Signature.from_hex(sig_hex).components).to eq signature.components
|
40
|
+
expect(RingSig::Signature.from_hex(sig_hex, hasher).components).to eq signature.components
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
44
|
describe '#from_der' do
|
44
45
|
it 'converts from der correctly' do
|
45
|
-
expect(RingSig::Signature.from_der(sig_der).components).to eq signature.components
|
46
|
+
expect(RingSig::Signature.from_der(sig_der, hasher).components).to eq signature.components
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end
|
metadata
CHANGED
@@ -1,127 +1,127 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ring_sig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen McCarthy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '10'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '3.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: simplecov
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: markdown
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - ~>
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '1'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - ~>
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '1'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: redcarpet
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - ~>
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '3'
|
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
110
|
version: '3'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: ecdsa
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - ~>
|
115
|
+
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '1.
|
117
|
+
version: '1.2'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - ~>
|
122
|
+
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '1.
|
124
|
+
version: '1.2'
|
125
125
|
description: Ring Signatures allow someone to non-interactively sign a message which
|
126
126
|
can be verified against a set of chosen public keys.
|
127
127
|
email: sjmccarthy@gmail.com
|
@@ -129,16 +129,15 @@ executables: []
|
|
129
129
|
extensions: []
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
|
-
- .gitignore
|
133
|
-
- .travis.yml
|
134
|
-
- .yardopts
|
132
|
+
- ".gitignore"
|
133
|
+
- ".travis.yml"
|
134
|
+
- ".yardopts"
|
135
135
|
- CHANGELOG.md
|
136
136
|
- Gemfile
|
137
137
|
- LICENSE
|
138
138
|
- README.md
|
139
139
|
- Rakefile
|
140
140
|
- lib/ring_sig.rb
|
141
|
-
- lib/ring_sig/ecdsa/point.rb
|
142
141
|
- lib/ring_sig/hasher.rb
|
143
142
|
- lib/ring_sig/private_key.rb
|
144
143
|
- lib/ring_sig/public_key.rb
|
@@ -160,12 +159,12 @@ require_paths:
|
|
160
159
|
- lib
|
161
160
|
required_ruby_version: !ruby/object:Gem::Requirement
|
162
161
|
requirements:
|
163
|
-
- -
|
162
|
+
- - ">="
|
164
163
|
- !ruby/object:Gem::Version
|
165
164
|
version: '0'
|
166
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
166
|
requirements:
|
168
|
-
- -
|
167
|
+
- - ">="
|
169
168
|
- !ruby/object:Gem::Version
|
170
169
|
version: '0'
|
171
170
|
requirements: []
|