ring_sig 0.3.0 → 0.4.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/CHANGELOG.md +21 -0
- data/lib/ring_sig/hasher.rb +20 -8
- data/lib/ring_sig/version.rb +1 -1
- data/spec/hasher_spec.rb +42 -8
- data/spec/private_key_spec.rb +6 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e795d6a45bee9ade9568ff3585a5571860ee23a4
|
4
|
+
data.tar.gz: 226ad82f45cd1c0037c7e0b91b7c0704308433a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20d0ea38c3d96edc5cb36675ebf32e7319a24bbac4c97667c52fc0ebfcb6c5c7deef20a5079ba92f84f002bc95404d27dcb94f064d1e1eef03fa12317542a58c
|
7
|
+
data.tar.gz: a8b6ece0da50a41ebee70fd6d4405f1c7a48347d0a235c76efbd008fcaf26bae16333b02b8d4f4c03c55741c9bf1efd374368db0deeae2aa76f68119a65ce42b
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,27 @@ 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.4.0
|
9
|
+
----
|
10
|
+
Release on 2014-09-18
|
11
|
+
|
12
|
+
This release maintains API compatibility with version 0.3.0, except for the two
|
13
|
+
constants that were removed.
|
14
|
+
|
15
|
+
Signatures produced with prior versions may be incompatible with signatures from
|
16
|
+
this version.
|
17
|
+
|
18
|
+
- Change the `Hasher#hash_string` method so that it can handle ECDSA groups
|
19
|
+
that have a much smaller order than the number of bits they have (such as
|
20
|
+
Curve25519).
|
21
|
+
- `Hasher` now validates that its group's byte-length is equal to its hash
|
22
|
+
algorithm's byte-length.
|
23
|
+
- Remove support for ECDSA groups that have an order larger than the number of
|
24
|
+
bits they have. Secp160k1 and Secp160r1 fall into this category because their
|
25
|
+
order is larger than 2^160.
|
26
|
+
- Remove the `Secp160k1_Ripemd160` and `Secp160r1_Ripemd160` constants, since
|
27
|
+
their groups are no longer supported.
|
28
|
+
|
8
29
|
0.3.0
|
9
30
|
----
|
10
31
|
Released on 2014-09-15
|
data/lib/ring_sig/hasher.rb
CHANGED
@@ -18,20 +18,32 @@ module RingSig
|
|
18
18
|
def initialize(group, algorithm)
|
19
19
|
@group = group
|
20
20
|
@algorithm = algorithm
|
21
|
+
|
22
|
+
algorithm_byte_length = algorithm.digest('a').size
|
23
|
+
if group.byte_length != algorithm_byte_length
|
24
|
+
raise ArgumentError, "Group's byte length (#{group.byte_length}), does not match hash algorithm's byte length (#{algorithm_byte_length})"
|
25
|
+
end
|
26
|
+
|
27
|
+
digest_max = 2 ** (algorithm_byte_length * 8) - 1
|
28
|
+
if digest_max < group.order
|
29
|
+
raise ArgumentError, "Invalid ECDSA group. Group's order must be less than the hash algorithm's maximum value"
|
30
|
+
end
|
31
|
+
|
32
|
+
@hash_cieling = digest_max - digest_max % group.order
|
21
33
|
end
|
22
34
|
|
23
|
-
#
|
35
|
+
# Uniformly hashes a string to a number between 0 and the group's order.
|
24
36
|
#
|
25
|
-
# @param s (String) The
|
37
|
+
# @param s (String) The string to be hashed.
|
26
38
|
# @return (Integer) A number between 0 and the group's order.
|
27
39
|
def hash_string(s)
|
28
40
|
n = nil
|
29
41
|
loop do
|
30
42
|
s = algorithm.digest(s)
|
31
43
|
n = s.unpack('H*').first.to_i(16)
|
32
|
-
break if n < @
|
44
|
+
break if n < @hash_cieling
|
33
45
|
end
|
34
|
-
n
|
46
|
+
n % group.order
|
35
47
|
end
|
36
48
|
|
37
49
|
# Hashes an array. Converts the Array to an OpenSSL::ASN1::Sequence der
|
@@ -59,7 +71,8 @@ module RingSig
|
|
59
71
|
# Hashes a point to another point.
|
60
72
|
#
|
61
73
|
# @param point [ECDSA::Point] The point to be hashed.
|
62
|
-
# @return [ECDSA::Point] A new point, deterministically computed from the
|
74
|
+
# @return [ECDSA::Point] A new point, deterministically computed from the
|
75
|
+
# input point.
|
63
76
|
def hash_point(point)
|
64
77
|
@group.generator * hash_array(point.coords)
|
65
78
|
end
|
@@ -67,7 +80,8 @@ module RingSig
|
|
67
80
|
# Shuffles an array in a deterministic manner.
|
68
81
|
#
|
69
82
|
# @param array (Array) The array to be shuffled.
|
70
|
-
# @param seed (Integer) A random seed which determines the outcome of the
|
83
|
+
# @param seed (Integer) A random seed which determines the outcome of the
|
84
|
+
# shuffle.
|
71
85
|
# @return (Array) The shuffled array.
|
72
86
|
def shuffle(array, seed)
|
73
87
|
seed_array = [seed, 0]
|
@@ -102,7 +116,5 @@ module RingSig
|
|
102
116
|
Secp256k1_Sha256 = new(ECDSA::Group::Secp256k1, OpenSSL::Digest::SHA256)
|
103
117
|
Secp256r1_Sha256 = new(ECDSA::Group::Secp256r1, OpenSSL::Digest::SHA256)
|
104
118
|
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)
|
107
119
|
end
|
108
120
|
end
|
data/lib/ring_sig/version.rb
CHANGED
data/spec/hasher_spec.rb
CHANGED
@@ -50,10 +50,10 @@ describe RingSig::Hasher do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
context 'Simple
|
53
|
+
context 'Simple hash algorithm, simple group' do
|
54
54
|
let(:group) do
|
55
|
-
# A simple group with order equal to 200
|
56
|
-
ECDSA::Group.new(name: 'simple', p:
|
55
|
+
# A simple 8-bit group with order equal to 200
|
56
|
+
ECDSA::Group.new(name: 'simple', p: 211, a: 1, b: 1, g: [0, 1], n: 200, h: 1)
|
57
57
|
end
|
58
58
|
|
59
59
|
let(:hash_algorithm) do
|
@@ -61,7 +61,7 @@ describe RingSig::Hasher do
|
|
61
61
|
stub_const 'SimpleHashAlgorithm', Class.new
|
62
62
|
SimpleHashAlgorithm.class_eval do
|
63
63
|
def self.digest(s)
|
64
|
-
[
|
64
|
+
[OpenSSL::Digest::SHA256.hexdigest(s)[-2,2]].pack('H*')
|
65
65
|
end
|
66
66
|
end
|
67
67
|
SimpleHashAlgorithm
|
@@ -77,17 +77,51 @@ describe RingSig::Hasher do
|
|
77
77
|
end
|
78
78
|
it_behaves_like 'hash algorithm', 'a', "\xBB" # 187
|
79
79
|
it_behaves_like 'hash algorithm', '0', "\xE9" # 233
|
80
|
-
it_behaves_like 'hash algorithm', "\xE9", "\
|
81
|
-
it_behaves_like 'hash algorithm', "\xD0", "\x15" # 21
|
80
|
+
it_behaves_like 'hash algorithm', "\xE9", "\r" # 13
|
82
81
|
|
83
82
|
describe '#hash_string' do
|
84
83
|
it 'hashes "a" to 187' do
|
85
84
|
expect(hasher.hash_string('a')).to eq 187
|
86
85
|
end
|
87
86
|
|
88
|
-
it 'hashes "0" to
|
89
|
-
expect(hasher.hash_string('0')).to eq
|
87
|
+
it 'hashes "0" to 13' do
|
88
|
+
expect(hasher.hash_string('0')).to eq 13
|
90
89
|
end
|
91
90
|
end
|
92
91
|
end
|
92
|
+
|
93
|
+
context 'Curve25519-like group' do
|
94
|
+
# This gem is not yet compatible with Curve25519, but we still test the
|
95
|
+
# hasher against it. Curve25519 has a distinct characteristic: its
|
96
|
+
# order is much smaller than its prime.
|
97
|
+
let(:group) do
|
98
|
+
ECDSA::Group.new(name: 'Curve25519-like', p: 2**255-19, a: 1, b: 1, g: [0, 1], n: 2**252+27742317777372353535851937790883648493, h: 1)
|
99
|
+
end
|
100
|
+
|
101
|
+
let(:hasher) { RingSig::Hasher.new(group, OpenSSL::Digest::SHA256) }
|
102
|
+
|
103
|
+
describe '#hash_string' do
|
104
|
+
it 'hashes "a"' do
|
105
|
+
expect(hasher.hash_string('a')).to eq 4790813224456470967164382530524007151295684942355166730955189790754105481631
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'hashes "0"' do
|
109
|
+
expect(hasher.hash_string('0')).to eq 7203293323279838689554303289673273753938185156274697627287051646710131340360
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'Non-matching byte-lengths' do
|
116
|
+
it 'raises an ArgumentError if group byte length does not match the hash algorithm byte length' do
|
117
|
+
expect { RingSig::Hasher.new(ECDSA::Group::Secp256k1, OpenSSL::Digest::SHA224) }.to raise_error(ArgumentError)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'ECDSA group with an order larger than the maximum digest size' do
|
122
|
+
it 'raises an ArgumentError' do
|
123
|
+
expect { RingSig::Hasher.new(ECDSA::Group::Secp160k1, OpenSSL::Digest::RIPEMD160) }.to raise_error(ArgumentError)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
93
127
|
end
|
data/spec/private_key_spec.rb
CHANGED
@@ -106,12 +106,12 @@ describe RingSig::PrivateKey do
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
context '
|
109
|
+
context 'Secp384r1_Sha384 hasher' do
|
110
110
|
before(:all) do
|
111
|
-
@key = RingSig::PrivateKey.new(1, RingSig::Hasher::
|
111
|
+
@key = RingSig::PrivateKey.new(1, RingSig::Hasher::Secp384r1_Sha384)
|
112
112
|
@foreign_keys = [
|
113
|
-
RingSig::PrivateKey.new(2, RingSig::Hasher::
|
114
|
-
RingSig::PrivateKey.new(3, RingSig::Hasher::
|
113
|
+
RingSig::PrivateKey.new(2, RingSig::Hasher::Secp384r1_Sha384).public_key,
|
114
|
+
RingSig::PrivateKey.new(3, RingSig::Hasher::Secp384r1_Sha384).public_key,
|
115
115
|
]
|
116
116
|
end
|
117
117
|
|
@@ -119,9 +119,9 @@ describe RingSig::PrivateKey do
|
|
119
119
|
it 'signs and verifies' do
|
120
120
|
sig, public_keys = @key.sign(message, @foreign_keys)
|
121
121
|
|
122
|
-
expect(sig.to_hex).to eq '
|
122
|
+
expect(sig.to_hex).to eq '3082016904310303c438f3cfc6d9b4d3da7ee4f23429387a3e9da42f87ac611ee390c007a81662e146a865f288111b758231917ce94436308197023100811608759c6a1a0afb245ffa6f15bcea8e6e02e6364371a232f74afbec60874770f66c2f87ad9dd9c851b80d38809bbe023063f90482db5f68dae8c8a45354189103ba3ff6c96d2114f1591300e17845e81e859dfb6996ae6ba9a011a20f820522b102307cb090c3788667d0bbf612853b2fb80856af833a26197a16df9b14a02e734a7bd8539e7d21e4ffd355a39dd9286e4898308199023100a803ebf9a67eb5fa91907d70bb53d93b192a206961e920afc99d8f3e3bbb8a8a2ece89c5a3dcd24dbc9a08a8f61c40bf02310097f561a1c60e7692a50c6e5be6a1ce8b52d88e228de552492351c845bc96180d9ac1578e0dc3b2a775a33d87b58f6155023100f670b730d0b719f1aced4dfbeeb027299f2b58b3297563b50dfb7e0e0fa67b04ce5a8c15b163227b7bdcd42bf8b6f572'
|
123
123
|
|
124
|
-
expected_public_keys = [2,
|
124
|
+
expected_public_keys = [2, 0, 1].map{|i| ([@key] + @foreign_keys)[i].public_key}
|
125
125
|
expect(public_keys).to eq expected_public_keys
|
126
126
|
|
127
127
|
expect(sig.verify(message, public_keys)).to be true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ring_sig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|