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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a9a8ff4b8548f802c19f9529c15034fc4c1329ab
4
- data.tar.gz: 56e3a1befb6c39b8c8205e49f167598fd3fc0bfa
3
+ metadata.gz: e795d6a45bee9ade9568ff3585a5571860ee23a4
4
+ data.tar.gz: 226ad82f45cd1c0037c7e0b91b7c0704308433a8
5
5
  SHA512:
6
- metadata.gz: d07e37c8ea67cceb18a6eca210cb03ce3c29381a3fe627ed24994a83e3b1093107521cc2b9588f76d26c4469aad9cd9eb266f80e34edfadb80b999d986fb1434
7
- data.tar.gz: 594217e061216f7e336827112e9ed01bb35772ba6b6547173eb673d3d79dd385bdd920a6c38231b21134a2e4333a8375440130d6e28b044aa95a3f4d32867305
6
+ metadata.gz: 20d0ea38c3d96edc5cb36675ebf32e7319a24bbac4c97667c52fc0ebfcb6c5c7deef20a5079ba92f84f002bc95404d27dcb94f064d1e1eef03fa12317542a58c
7
+ data.tar.gz: a8b6ece0da50a41ebee70fd6d4405f1c7a48347d0a235c76efbd008fcaf26bae16333b02b8d4f4c03c55741c9bf1efd374368db0deeae2aa76f68119a65ce42b
@@ -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
@@ -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
- # Continuously hashes until a value less than the group's order is found.
35
+ # Uniformly hashes a string to a number between 0 and the group's order.
24
36
  #
25
- # @param s (String) The value to be hashed.
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 < @group.order
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 input point.
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 suffle.
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
@@ -1,4 +1,4 @@
1
1
  module RingSig
2
2
  # This gem's version.
3
- VERSION = '0.3.0'
3
+ VERSION = '0.4.0'
4
4
  end
@@ -50,10 +50,10 @@ describe RingSig::Hasher do
50
50
  end
51
51
  end
52
52
 
53
- context 'Simple hasher, simple group' do
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: 1, a: 1, b: 1, g: [0, 1], n: 200, h: 1)
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
- [(OpenSSL::Digest::SHA256.hexdigest(s).to_i(16) % 256).to_s(16)].pack('H*')
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", "\xD0" # 208
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 21' do
89
- expect(hasher.hash_string('0')).to eq 21
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
@@ -106,12 +106,12 @@ describe RingSig::PrivateKey do
106
106
  end
107
107
  end
108
108
 
109
- context 'alternate hasher' do
109
+ context 'Secp384r1_Sha384 hasher' do
110
110
  before(:all) do
111
- @key = RingSig::PrivateKey.new(1, RingSig::Hasher::Secp160k1_Ripemd160)
111
+ @key = RingSig::PrivateKey.new(1, RingSig::Hasher::Secp384r1_Sha384)
112
112
  @foreign_keys = [
113
- RingSig::PrivateKey.new(2, RingSig::Hasher::Secp160k1_Ripemd160).public_key,
114
- RingSig::PrivateKey.new(3, RingSig::Hasher::Secp160k1_Ripemd160).public_key,
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 '3081a004150335d6eb01d7c658c2aae34e1e910e1b44c993069d30430214685baa33eacec37ff3530d710ca852731e1ac7b0021500881bf1e9c67d05c7a8a6ef93552a7852466034360214211b72b5e3a934d0e096441c5208b4322a83b7a130420214098d90e6e0a5e08186815be4a20a41480d55d7c202141cd9f8cc0df48519ecd6ad6e354ca634c8b604c2021415019f51cc2480ef6148dcd35a4be28037bf8899'
122
+ expect(sig.to_hex).to eq '3082016904310303c438f3cfc6d9b4d3da7ee4f23429387a3e9da42f87ac611ee390c007a81662e146a865f288111b758231917ce94436308197023100811608759c6a1a0afb245ffa6f15bcea8e6e02e6364371a232f74afbec60874770f66c2f87ad9dd9c851b80d38809bbe023063f90482db5f68dae8c8a45354189103ba3ff6c96d2114f1591300e17845e81e859dfb6996ae6ba9a011a20f820522b102307cb090c3788667d0bbf612853b2fb80856af833a26197a16df9b14a02e734a7bd8539e7d21e4ffd355a39dd9286e4898308199023100a803ebf9a67eb5fa91907d70bb53d93b192a206961e920afc99d8f3e3bbb8a8a2ece89c5a3dcd24dbc9a08a8f61c40bf02310097f561a1c60e7692a50c6e5be6a1ce8b52d88e228de552492351c845bc96180d9ac1578e0dc3b2a775a33d87b58f6155023100f670b730d0b719f1aced4dfbeeb027299f2b58b3297563b50dfb7e0e0fa67b04ce5a8c15b163227b7bdcd42bf8b6f572'
123
123
 
124
- expected_public_keys = [2, 1, 0].map{|i| ([@key] + @foreign_keys)[i].public_key}
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.3.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-15 00:00:00.000000000 Z
11
+ date: 2014-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler