secretsharing 1.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|