secretsharing 1.0.0 → 2.0.1
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/.rubocop.yml +3 -0
- data/.travis.yml +12 -9
- data/CHANGES.md +40 -0
- data/README.md +109 -77
- data/Rakefile +3 -3
- data/bin/secretsharing +7 -7
- data/gemfiles/Gemfile.ci +2 -0
- data/lib/secretsharing.rb +2 -2
- data/lib/secretsharing/shamir.rb +111 -44
- data/lib/secretsharing/shamir/secret.rb +52 -32
- data/lib/secretsharing/shamir/share.rb +27 -26
- data/lib/secretsharing/version.rb +1 -1
- data/secretsharing.gemspec +28 -21
- data/spec/shamir_container_spec.rb +13 -25
- data/spec/shamir_secret_spec.rb +34 -27
- data/spec/shamir_share_spec.rb +0 -4
- data/spec/shamir_spec.rb +108 -8
- metadata +47 -18
- data/CHANGES +0 -17
- data/SIGNED.md +0 -99
data/secretsharing.gemspec
CHANGED
@@ -5,27 +5,32 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'secretsharing/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
|
-
s.name =
|
8
|
+
s.name = 'secretsharing'
|
9
9
|
s.version = SecretSharing::VERSION
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
|
-
s.authors = [
|
12
|
-
s.email = [
|
13
|
-
s.homepage =
|
14
|
-
s.summary =
|
15
|
-
s.license =
|
11
|
+
s.authors = ['Alexander Klink', 'Glenn Rempe']
|
12
|
+
s.email = ['glenn@rempe.us']
|
13
|
+
s.homepage = 'https://github.com/grempe/secretsharing'
|
14
|
+
s.summary = 'A Ruby Gem to enable sharing secrets using Shamirs Secret Sharing.'
|
15
|
+
s.license = 'APACHE 2.0'
|
16
16
|
|
17
17
|
s.has_rdoc = 'true'
|
18
18
|
s.extra_rdoc_files = ['README.md']
|
19
19
|
|
20
|
-
s.rubyforge_project =
|
20
|
+
s.rubyforge_project = 'secretsharing'
|
21
21
|
|
22
|
+
# rubocop:disable Style/SpecialGlobalVars
|
22
23
|
s.files = `git ls-files`.split($/)
|
24
|
+
# rubocop:enable Style/SpecialGlobalVars
|
25
|
+
|
23
26
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
24
27
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
25
|
-
s.require_paths = [
|
28
|
+
s.require_paths = ['lib']
|
26
29
|
|
27
|
-
s.add_dependency '
|
28
|
-
s.add_dependency '
|
30
|
+
s.add_dependency 'rbnacl-libsodium', '~> 1.0.8'
|
31
|
+
s.add_dependency 'rbnacl', '~> 3.3.0'
|
32
|
+
s.add_dependency 'highline', '~> 1.7.8'
|
33
|
+
s.add_dependency 'multi_json', '~> 1.11.2'
|
29
34
|
|
30
35
|
s.add_development_dependency 'mocha'
|
31
36
|
s.add_development_dependency 'minitest'
|
@@ -33,15 +38,17 @@ Gem::Specification.new do |s|
|
|
33
38
|
s.add_development_dependency 'rb-fsevent'
|
34
39
|
s.add_development_dependency 'rerun'
|
35
40
|
s.add_development_dependency 'rubocop'
|
36
|
-
s.add_development_dependency 'bundler'
|
37
|
-
s.add_development_dependency 'rake'
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
s.add_development_dependency 'bundler'
|
42
|
+
s.add_development_dependency 'rake'
|
43
|
+
|
44
|
+
# http://rubyquicktips.com/post/4438542511/heredoc-and-indent
|
45
|
+
s.description = <<-EOF.gsub(/^ {4}/, '')
|
46
|
+
4/12/2016 - NO LONGER MAINTAINED - See README.md
|
47
|
+
|
48
|
+
Shamirs Secret Sharing is an algorithm in cryptography. It is a
|
49
|
+
form of secret sharing, where a secret is divided into parts,
|
50
|
+
giving each participant its own unique part, where some of the
|
51
|
+
parts or all of them are needed in order to reconstruct the
|
52
|
+
secret. Holders of a share gain no knowledge of the larger secret.
|
53
|
+
EOF
|
47
54
|
end
|
@@ -17,9 +17,7 @@
|
|
17
17
|
require File.expand_path('../spec_helper', __FILE__)
|
18
18
|
|
19
19
|
describe SecretSharing::Shamir::Container do
|
20
|
-
|
21
20
|
describe 'initialization' do
|
22
|
-
|
23
21
|
it 'will raise when instantiated with no args' do
|
24
22
|
lambda { SecretSharing::Shamir::Container.new }.must_raise(ArgumentError)
|
25
23
|
end
|
@@ -101,15 +99,13 @@ describe SecretSharing::Shamir::Container do
|
|
101
99
|
it 'must return the correct max shares constant value' do
|
102
100
|
SecretSharing::Shamir::Container::MAX_SHARES.must_equal(512)
|
103
101
|
end
|
104
|
-
|
105
102
|
end # describe initialization
|
106
103
|
|
107
104
|
describe 'creating a container and setting a secret' do
|
108
|
-
|
109
105
|
before do
|
110
106
|
@num_shares = 5
|
111
107
|
@c = SecretSharing::Shamir::Container.new(@num_shares)
|
112
|
-
@secret_num =
|
108
|
+
@secret_num = 1234567890
|
113
109
|
@c.secret = SecretSharing::Shamir::Secret.new(:secret => @secret_num)
|
114
110
|
end
|
115
111
|
|
@@ -142,14 +138,12 @@ describe SecretSharing::Shamir::Container do
|
|
142
138
|
it 'must raise an exception if a secret is attempted to be set more than once' do
|
143
139
|
lambda { @c.secret = SecretSharing::Shamir::Secret.new }.must_raise(ArgumentError)
|
144
140
|
end
|
145
|
-
|
146
141
|
end # creating a container and setting a secret
|
147
142
|
|
148
143
|
describe 'generating shares when a secret is provided' do
|
149
|
-
|
150
144
|
it 'should generate unique shares for the min number of shares and a tiny secret' do
|
151
145
|
c1 = SecretSharing::Shamir::Container.new(2)
|
152
|
-
c1.secret = SecretSharing::Shamir::Secret.new(:secret =>
|
146
|
+
c1.secret = SecretSharing::Shamir::Secret.new(:secret => 123)
|
153
147
|
shares = c1.shares
|
154
148
|
shares.size.must_equal(2)
|
155
149
|
uniq_shares = shares.uniq
|
@@ -158,7 +152,7 @@ describe SecretSharing::Shamir::Container do
|
|
158
152
|
|
159
153
|
it 'should generate unique shares for the max number of shares and a tiny secret' do
|
160
154
|
c1 = SecretSharing::Shamir::Container.new(512)
|
161
|
-
c1.secret = SecretSharing::Shamir::Secret.new(:secret =>
|
155
|
+
c1.secret = SecretSharing::Shamir::Secret.new(:secret => 123)
|
162
156
|
shares = c1.shares
|
163
157
|
shares.size.must_equal(512)
|
164
158
|
uniq_shares = shares.uniq
|
@@ -167,8 +161,9 @@ describe SecretSharing::Shamir::Container do
|
|
167
161
|
|
168
162
|
it 'should generate unique shares for the min number of shares and a large secret' do
|
169
163
|
c1 = SecretSharing::Shamir::Container.new(2)
|
170
|
-
# FIXME : Major Perf Issue :
|
171
|
-
|
164
|
+
# FIXME : Major Perf Issue : Large bit length secrets (>4096) cause major perf issue.
|
165
|
+
random_num = RbNaCl::Util.bin2hex(RbNaCl::Random.random_bytes(32).to_s).to_i(16)
|
166
|
+
c1.secret = SecretSharing::Shamir::Secret.new(:secret => random_num)
|
172
167
|
shares = c1.shares
|
173
168
|
shares.size.must_equal(2)
|
174
169
|
uniq_shares = shares.uniq
|
@@ -177,18 +172,17 @@ describe SecretSharing::Shamir::Container do
|
|
177
172
|
|
178
173
|
it 'should generate unique shares for the max number of shares and a large secret' do
|
179
174
|
c1 = SecretSharing::Shamir::Container.new(512)
|
180
|
-
# FIXME : Major Perf Issue :
|
181
|
-
|
175
|
+
# FIXME : Major Perf Issue : Large bit length secrets (>4096) cause major perf issue.
|
176
|
+
random_num = RbNaCl::Util.bin2hex(RbNaCl::Random.random_bytes(32).to_s).to_i(16)
|
177
|
+
c1.secret = SecretSharing::Shamir::Secret.new(:secret => random_num)
|
182
178
|
shares = c1.shares
|
183
179
|
shares.size.must_equal(512)
|
184
180
|
uniq_shares = shares.uniq
|
185
181
|
shares.must_equal(uniq_shares)
|
186
182
|
end
|
187
|
-
|
188
183
|
end
|
189
184
|
|
190
185
|
describe 'recovering a secret from a container' do
|
191
|
-
|
192
186
|
before do
|
193
187
|
@c1 = SecretSharing::Shamir::Container.new(5) # creator
|
194
188
|
@c2 = SecretSharing::Shamir::Container.new(5) # recipient
|
@@ -200,7 +194,6 @@ describe SecretSharing::Shamir::Container do
|
|
200
194
|
end
|
201
195
|
|
202
196
|
describe 'with a mix of valid and invalid shares' do
|
203
|
-
|
204
197
|
before do
|
205
198
|
# set a secret on the 'creators'
|
206
199
|
@c1.secret = SecretSharing::Shamir::Secret.new
|
@@ -258,11 +251,9 @@ describe SecretSharing::Shamir::Container do
|
|
258
251
|
@c2 << @c1.shares[3]
|
259
252
|
lambda { @c2 << @c1.shares[4] }.must_raise(ArgumentError)
|
260
253
|
end
|
261
|
-
|
262
254
|
end
|
263
255
|
|
264
256
|
describe 'with valid shares resulting from a random secret' do
|
265
|
-
|
266
257
|
before do
|
267
258
|
extend SecretSharing::Shamir
|
268
259
|
# set a secret on both of the 'creators'
|
@@ -272,12 +263,12 @@ describe SecretSharing::Shamir::Container do
|
|
272
263
|
|
273
264
|
# This exposed a bug in the prime number generation; for instance 4*8
|
274
265
|
# passes.
|
275
|
-
it 'should be able to recover
|
276
|
-
secret = SecretSharing::Shamir::Secret.new(:secret =>
|
277
|
-
c = SecretSharing::Shamir::Container.new(4,2)
|
266
|
+
it 'should be able to recover 40 bit secret' do
|
267
|
+
secret = SecretSharing::Shamir::Secret.new(:secret => get_random_number_with_bitlength(40))
|
268
|
+
c = SecretSharing::Shamir::Container.new(4, 2)
|
278
269
|
c.secret = secret
|
279
270
|
|
280
|
-
(0...4).to_a.permutation(2).collect
|
271
|
+
(0...4).to_a.permutation(2).collect(&:sort).uniq.each do |indexes|
|
281
272
|
c2 = SecretSharing::Shamir::Container.new(2)
|
282
273
|
indexes.each do |index|
|
283
274
|
c2 << c.shares[index]
|
@@ -365,9 +356,6 @@ describe SecretSharing::Shamir::Container do
|
|
365
356
|
@c4.secret?.must_equal(true)
|
366
357
|
@c4.secret.must_equal(@c3.secret)
|
367
358
|
end
|
368
|
-
|
369
359
|
end
|
370
|
-
|
371
360
|
end # recovering a secret from a container
|
372
|
-
|
373
361
|
end # describe SecretSharing::Shamir::Container
|
data/spec/shamir_secret_spec.rb
CHANGED
@@ -17,11 +17,21 @@
|
|
17
17
|
require File.expand_path('../spec_helper', __FILE__)
|
18
18
|
|
19
19
|
describe SecretSharing::Shamir::Secret do
|
20
|
+
describe 'initialization with Fixnum' do
|
21
|
+
before do
|
22
|
+
@num = 12345
|
23
|
+
@s = SecretSharing::Shamir::Secret.new(:secret => @num)
|
24
|
+
end
|
20
25
|
|
21
|
-
|
26
|
+
it 'must initialize with a random secret and set @secret and @bitlength by default' do
|
27
|
+
@s.secret.is_a?(Integer).must_equal(true)
|
28
|
+
@s.bitlength.is_a?(Integer).must_equal(true)
|
29
|
+
end
|
30
|
+
end # describe initialization with Integer
|
22
31
|
|
32
|
+
describe 'initialization with Bignum' do
|
23
33
|
before do
|
24
|
-
@num =
|
34
|
+
@num = 12345678909123098902183908908213829013
|
25
35
|
@s = SecretSharing::Shamir::Secret.new(:secret => @num)
|
26
36
|
end
|
27
37
|
|
@@ -42,24 +52,26 @@ describe SecretSharing::Shamir::Secret do
|
|
42
52
|
end
|
43
53
|
|
44
54
|
it 'must initialize with a random secret and set @secret and @bitlength by default' do
|
45
|
-
@s.secret.is_a?(
|
55
|
+
@s.secret.is_a?(Integer).must_equal(true)
|
46
56
|
@s.bitlength.is_a?(Integer).must_equal(true)
|
47
57
|
end
|
48
58
|
|
49
|
-
it 'must raise an ArgumentError if
|
50
|
-
|
59
|
+
it 'must not raise an ArgumentError if the bitlength of the secret is equal to MAX_BITLENGTH' do
|
60
|
+
str_bits = '1' * SecretSharing::Shamir::Secret::MAX_BITLENGTH
|
61
|
+
s = SecretSharing::Shamir::Secret.new(:secret => str_bits.to_i(2))
|
62
|
+
s.is_a?(SecretSharing::Shamir::Secret).must_equal(true)
|
51
63
|
end
|
52
64
|
|
53
65
|
it 'must raise an ArgumentError if the bitlength of the secret is greater than MAX_BITLENGTH' do
|
54
|
-
|
55
|
-
lambda { SecretSharing::Shamir::Secret.new(:secret =>
|
66
|
+
str_bits = '1' * (SecretSharing::Shamir::Secret::MAX_BITLENGTH + 1)
|
67
|
+
lambda { SecretSharing::Shamir::Secret.new(:secret => str_bits.to_i(2)) }.must_raise(ArgumentError)
|
56
68
|
end
|
57
69
|
|
58
|
-
it 'must initialize with a fixed secret and set @secret and @bitlength to the same if passed
|
59
|
-
@s.secret.is_a?(
|
70
|
+
it 'must initialize with a fixed secret and set @secret and @bitlength to the same if passed a Bignum' do
|
71
|
+
@s.secret.is_a?(Integer).must_equal(true)
|
60
72
|
@s.secret.must_equal(@num)
|
61
73
|
@s.bitlength.is_a?(Integer).must_equal(true)
|
62
|
-
@s.bitlength.must_equal(@num.
|
74
|
+
@s.bitlength.must_equal(@num.bit_length)
|
63
75
|
end
|
64
76
|
|
65
77
|
it 'must throw an exception if initialized with a String that does not base64 re-hydrate as expected from the output of #to_s' do
|
@@ -74,7 +86,7 @@ describe SecretSharing::Shamir::Secret do
|
|
74
86
|
|
75
87
|
it 'must use Base64.decode64 instead of Base64.urlsafe_decode64 on platform that is not true for Base64.respond_to?(:urlsafe_encode64)' do
|
76
88
|
Base64.stub(:respond_to?, false) do
|
77
|
-
num =
|
89
|
+
num = 1234567890123456789012345678901234567890
|
78
90
|
s1 = SecretSharing::Shamir::Secret.new(:secret => num)
|
79
91
|
s1_str = s1.to_s
|
80
92
|
s1_str.must_equal('MWl6aWJqZjR6dmRibXZxNjZkNndtOGcxY2k=')
|
@@ -86,8 +98,7 @@ describe SecretSharing::Shamir::Secret do
|
|
86
98
|
end
|
87
99
|
|
88
100
|
it 'must decode to the SAME String on mixed platforms that are, or are not, truthy for Base64.respond_to?(:urlsafe_decode64)' do
|
89
|
-
|
90
|
-
# NOTE : OpenSSL::BN.new('1234567890123456789012345678901234567890')
|
101
|
+
# NOTE : 1234567890123456789012345678901234567890
|
91
102
|
str = 'MWl6aWJqZjR6dmRibXZxNjZkNndtOGcxY2k='
|
92
103
|
s2 = nil
|
93
104
|
s3 = nil
|
@@ -115,35 +126,33 @@ describe SecretSharing::Shamir::Secret do
|
|
115
126
|
it 'must throw an ArgumentError if an unknown option hash key is passed in' do
|
116
127
|
lambda { SecretSharing::Shamir::Secret.new(:secret => 'foo\nbar', :unknown_arg => true) }.must_raise(ArgumentError)
|
117
128
|
end
|
118
|
-
|
119
129
|
end # describe initialization
|
120
130
|
|
121
131
|
describe '==' do
|
122
|
-
|
123
132
|
before do
|
124
|
-
@num =
|
133
|
+
@num = 1234567890
|
125
134
|
@s = SecretSharing::Shamir::Secret.new(:secret => @num)
|
126
135
|
end
|
127
136
|
|
128
|
-
it 'must return true if two secrets have the same
|
137
|
+
it 'must return true if two secrets have the same Integer set internally' do
|
129
138
|
s2 = @s
|
130
139
|
(@s == s2).must_equal(true)
|
131
140
|
end
|
132
141
|
|
133
|
-
it 'must return false if two secrets have different
|
134
|
-
s2 = SecretSharing::Shamir::Secret.new(:secret =>
|
142
|
+
it 'must return false if two secrets have different Integers set internally' do
|
143
|
+
s2 = SecretSharing::Shamir::Secret.new(:secret => 987654321)
|
135
144
|
(@s == s2).must_equal(false)
|
136
145
|
end
|
137
146
|
end
|
138
147
|
|
139
148
|
describe 'secret?' do
|
140
149
|
before do
|
141
|
-
@num =
|
150
|
+
@num = 1234567890
|
142
151
|
@s = SecretSharing::Shamir::Secret.new(:secret => @num)
|
143
152
|
end
|
144
153
|
|
145
154
|
it 'must return true if a secret is set' do
|
146
|
-
@s.secret.is_a?(
|
155
|
+
@s.secret.is_a?(Integer).must_equal(true)
|
147
156
|
@s.secret?.must_equal(true)
|
148
157
|
end
|
149
158
|
|
@@ -155,12 +164,12 @@ describe SecretSharing::Shamir::Secret do
|
|
155
164
|
|
156
165
|
describe 'secret()' do
|
157
166
|
before do
|
158
|
-
@num =
|
167
|
+
@num = 1234567890
|
159
168
|
@s = SecretSharing::Shamir::Secret.new(:secret => @num)
|
160
169
|
end
|
161
170
|
|
162
171
|
it 'must return true if a secret is set' do
|
163
|
-
@s.secret.is_a?(
|
172
|
+
@s.secret.is_a?(Integer).must_equal(true)
|
164
173
|
@s.secret?.must_equal(true)
|
165
174
|
end
|
166
175
|
|
@@ -172,7 +181,7 @@ describe SecretSharing::Shamir::Secret do
|
|
172
181
|
|
173
182
|
describe 'to_s' do
|
174
183
|
it 'must return a proper and consistent URL safe encoded String representation of @secret and allow round trip of that String' do
|
175
|
-
num =
|
184
|
+
num = 1234567890123456789012345678901234567890
|
176
185
|
s1 = SecretSharing::Shamir::Secret.new(:secret => num)
|
177
186
|
s1_str = s1.to_s
|
178
187
|
s1_str.must_equal('MWl6aWJqZjR6dmRibXZxNjZkNndtOGcxY2k=')
|
@@ -185,7 +194,7 @@ describe SecretSharing::Shamir::Secret do
|
|
185
194
|
|
186
195
|
describe 'valid_hmac?' do
|
187
196
|
before do
|
188
|
-
@num =
|
197
|
+
@num = 1234567890
|
189
198
|
@s = SecretSharing::Shamir::Secret.new(:secret => @num)
|
190
199
|
end
|
191
200
|
|
@@ -202,7 +211,5 @@ describe SecretSharing::Shamir::Secret do
|
|
202
211
|
@s.hmac = @s.hmac + 'a'
|
203
212
|
@s.valid_hmac?.must_equal(false)
|
204
213
|
end
|
205
|
-
|
206
214
|
end
|
207
|
-
|
208
215
|
end # describe SecretSharing::Shamir::Secret
|
data/spec/shamir_share_spec.rb
CHANGED
@@ -17,9 +17,7 @@
|
|
17
17
|
require File.expand_path('../spec_helper', __FILE__)
|
18
18
|
|
19
19
|
describe SecretSharing::Shamir::Share do
|
20
|
-
|
21
20
|
describe 'initialization' do
|
22
|
-
|
23
21
|
before do
|
24
22
|
@args = { :hmac => 'foo', :k => 3, :n => 4, :x => 1, :y => 1, :prime => 1, :prime_bitlength => 1 }
|
25
23
|
end
|
@@ -53,7 +51,5 @@ describe SecretSharing::Shamir::Share do
|
|
53
51
|
@s2 = SecretSharing::Shamir::Share.new(:hmac => 'foo', :k => 3, :n => 4, :x => 1, :y => 1, :prime => 1, :prime_bitlength => 1)
|
54
52
|
@s1.must_equal(@s2)
|
55
53
|
end
|
56
|
-
|
57
54
|
end
|
58
|
-
|
59
55
|
end
|
data/spec/shamir_spec.rb
CHANGED
@@ -16,20 +16,120 @@
|
|
16
16
|
|
17
17
|
require File.expand_path('../spec_helper', __FILE__)
|
18
18
|
|
19
|
-
|
20
19
|
describe SecretSharing::Shamir do
|
20
|
+
include SecretSharing::Shamir
|
21
|
+
|
22
|
+
describe 'get_random_number' do
|
23
|
+
it 'will return a Bignum' do
|
24
|
+
r = get_random_number(32)
|
25
|
+
r.class.must_equal(Bignum)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'will return a Bignum with a size equaling the requested number of Bytes' do
|
29
|
+
r = get_random_number(32)
|
30
|
+
r.class.must_equal(Bignum)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'get_random_number_with_bitlength' do
|
35
|
+
it 'will return a Bignum' do
|
36
|
+
bitlength = 256
|
37
|
+
r = get_random_number_with_bitlength(bitlength)
|
38
|
+
r.class.must_equal(Bignum)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'will return a random number of bitlength bits when bitlength is evenly divisible by 8' do
|
42
|
+
bitlength = 256
|
43
|
+
r = get_random_number_with_bitlength(bitlength)
|
44
|
+
r.bit_length.must_equal(bitlength)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'will return a random number of bitlength bits when bitlength is not evenly divisible by 8' do
|
48
|
+
bitlength = 257
|
49
|
+
r = get_random_number_with_bitlength(bitlength)
|
50
|
+
r.bit_length.must_equal(bitlength)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'miller_rabin_prime?' do
|
55
|
+
it 'will return true for the known primes <= 100' do
|
56
|
+
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
|
57
|
+
primes.each do |p|
|
58
|
+
miller_rabin_prime?(p, 1000).must_equal(true)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'will return true for 128 bit known primes' do
|
63
|
+
# each generated with: get_prime_number(128)
|
64
|
+
# each was also confirmed to be prime with Wolfram Alpha "Is N prime?"
|
65
|
+
primes = [
|
66
|
+
382767781724287998593870036291756450809,
|
67
|
+
356939410756484930113231794428360705287,
|
68
|
+
629759975992442345994901795062291065567,
|
69
|
+
438321932766749553579901302755893165357,
|
70
|
+
510959605072332037935633647489517878279
|
71
|
+
]
|
72
|
+
|
73
|
+
primes.each do |p|
|
74
|
+
miller_rabin_prime?(p, 1000).must_equal(true)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'will return true for 512 bit known primes' do
|
79
|
+
# each generated with: get_prime_number(512)
|
80
|
+
# each was also confirmed to be prime with Wolfram Alpha "Is N prime?"
|
81
|
+
primes = [
|
82
|
+
23999707866903326489156183307465540658883197873852940711009335379108363305023805329984215621371398530337791438685939745980557830310369653441114726729488047,
|
83
|
+
26264879364280914726387337523874770984938759192907578453587351353319032004165834289093747124468183487116687747810871530759960877154788799650863513281542449,
|
84
|
+
21419943505124415306535132543073126636345087246929370277918349432585089088938166354019597382594479966007308711525355781449302321333323114286893173242617447,
|
85
|
+
15374852860017642027686544538337536903565786542098241857812378775632595902540222017334241111772863426942525633588495075859043584856426724378984665496611453,
|
86
|
+
20279656133141646288468910535277192664988817199276725796792464746874102110167503650047272184232978918686592075892731325814289300758175615144548978275489781
|
87
|
+
]
|
88
|
+
|
89
|
+
primes.each do |p|
|
90
|
+
miller_rabin_prime?(p, 1000).must_equal(true)
|
91
|
+
end
|
92
|
+
end
|
21
93
|
|
22
|
-
|
94
|
+
it 'will return false for 128 bit known non-primes' do
|
95
|
+
# each was also confirmed to NOT be prime with Wolfram Alpha "Is N prime?"
|
96
|
+
# these are the same as the 128 bit primes + 2
|
97
|
+
primes = [
|
98
|
+
382767781724287998593870036291756450809 + 2,
|
99
|
+
356939410756484930113231794428360705287 + 2,
|
100
|
+
629759975992442345994901795062291065567 + 2,
|
101
|
+
438321932766749553579901302755893165357 + 2,
|
102
|
+
510959605072332037935633647489517878279 + 2
|
103
|
+
]
|
23
104
|
|
24
|
-
|
105
|
+
primes.each do |p|
|
106
|
+
miller_rabin_prime?(p, 1000).must_equal(false)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'get_prime_number' do
|
112
|
+
it 'will return a random prime odd number' do
|
113
|
+
p = get_prime_number(128)
|
114
|
+
p.odd?.must_equal(true)
|
115
|
+
end
|
25
116
|
|
26
|
-
it 'will
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
dec.must_equal(str)
|
117
|
+
it 'will return a random prime number of at least the specified bit length + 1' do
|
118
|
+
bit_length = 128
|
119
|
+
p = get_prime_number(bit_length)
|
120
|
+
(p.bit_length >= bit_length + 1).must_equal(true)
|
31
121
|
end
|
32
122
|
|
123
|
+
it 'will return a random prime number that tests prime with the miller-rabin test' do
|
124
|
+
p = get_prime_number(128)
|
125
|
+
miller_rabin_prime?(p).must_equal(true)
|
126
|
+
end
|
33
127
|
end
|
34
128
|
|
129
|
+
describe 'invmod' do
|
130
|
+
it 'will return a known value' do
|
131
|
+
# http://rosettacode.org/wiki/Modular_inverse#Ruby
|
132
|
+
invmod(42, 2017).must_equal(1969)
|
133
|
+
end
|
134
|
+
end
|
35
135
|
end
|