btcruby 1.4 → 1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/RELEASE_NOTES.md +5 -0
- data/lib/btcruby/ssss.rb +109 -35
- data/lib/btcruby/version.rb +1 -1
- data/spec/ssss_spec.rb +81 -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: b28e8aae378a1e3a925ccb7acdb05b68e2e1987c
|
4
|
+
data.tar.gz: a134759a151e238011207ea52d7ff0a2bbbbf92e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a0b2f8cbfc3cb5fba98cc1844beae30410db5da37fcc2decbe91190c41c571ef9be5c16c86d1e496d6ffa46afbb5d5c92c1c9d4fdb494714bc3c531505dd4c3
|
7
|
+
data.tar.gz: 5e2edf87ad3704f45acd614a67763325e73aaf85ab61fdc52c3ac6827e09bc7273a5c48a66764fd1b38836b88888f21e3680d8330750ec8c76c7a653a8b3dbfa
|
data/RELEASE_NOTES.md
CHANGED
data/lib/btcruby/ssss.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# Author: Oleg Andreev <oleganza@gmail.com>
|
3
3
|
#
|
4
4
|
# * Deterministic, extensible algorithm: every combination of secret and threshold produces exactly the same shares on each run. More shares can be generated without invalidating the first ones.
|
5
|
-
# * This algorithm splits and restores 128-bit secrets with up to 16 shares and up to 16 shares threshold.
|
5
|
+
# * This algorithm splits and restores 96/104/128-bit secrets with up to 16 shares and up to 16 shares threshold.
|
6
6
|
# * Secret is a binary 16-byte string below ffffffffffffffffffffffffffffff61.
|
7
7
|
# * Shares are 17-byte binary strings with first byte indicating threshold and share index (these are necessary for recovery).
|
8
8
|
#
|
@@ -10,34 +10,37 @@
|
|
10
10
|
require 'digest/sha2'
|
11
11
|
require 'securerandom'
|
12
12
|
module BTC
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
pad = pad + "\x00".b
|
13
|
+
class SecretSharing
|
14
|
+
|
15
|
+
Order96 = 0xffffffffffffffffffffffef # Largest prime below 2**96: (2**96 - 17)
|
16
|
+
Order104 = 0xffffffffffffffffffffffffef # Largest prime below 2**104: (2**104 - 17)
|
17
|
+
Order128 = 0xffffffffffffffffffffffffffffff61 # Largest prime below 2**128: (2**128 - 159)
|
18
|
+
|
19
|
+
def initialize(bitlength = 128)
|
20
|
+
if bitlength == 128
|
21
|
+
@order = Order128
|
22
|
+
elsif bitlength == 104
|
23
|
+
@order = Order104
|
24
|
+
elsif bitlength == 96
|
25
|
+
@order = Order96
|
26
|
+
else
|
27
|
+
raise ArgumentError, "Unsupported bit length #{bitlength}"
|
29
28
|
end
|
30
|
-
|
29
|
+
@bitlength = bitlength
|
30
|
+
end
|
31
|
+
|
32
|
+
def random
|
33
|
+
be_from_int(SecureRandom.random_number(@order))
|
31
34
|
end
|
32
35
|
|
33
36
|
# Returns N strings, any M of them are enough to retrieve a secret.
|
34
37
|
# Each string encodes X and Y coordinates and also M. X & M takes one byte, Y takes 16 bytes:
|
35
38
|
# MMMMXXXX YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY YYYYYYYY
|
36
39
|
def split(secret, m, n)
|
37
|
-
prime =
|
40
|
+
prime = @order
|
38
41
|
secret_num = int_from_be(secret)
|
39
|
-
if secret_num >=
|
40
|
-
raise "Secret cannot be encoded with
|
42
|
+
if secret_num >= @order
|
43
|
+
raise "Secret cannot be encoded with #{@bitlength}-bit SSSS"
|
41
44
|
end
|
42
45
|
if !(n >= 1 && n <= 16)
|
43
46
|
raise "N must be between 1 and 16"
|
@@ -68,7 +71,7 @@ module BTC
|
|
68
71
|
# Transforms M 17-byte binary strings into original secret 16-byte binary string.
|
69
72
|
# Each share string must be well-formed.
|
70
73
|
def restore(shares)
|
71
|
-
prime =
|
74
|
+
prime = @order
|
72
75
|
shares = shares.dup.uniq
|
73
76
|
raise "No shares provided" if shares.size == 0
|
74
77
|
points = shares.map{|s| point_from_string(s) } # [[m,x,y],...]
|
@@ -97,7 +100,19 @@ module BTC
|
|
97
100
|
end
|
98
101
|
return be_from_int(y)
|
99
102
|
end
|
100
|
-
|
103
|
+
|
104
|
+
def prng(seed)
|
105
|
+
x = @order
|
106
|
+
s = nil
|
107
|
+
pad = "".b
|
108
|
+
while x >= @order
|
109
|
+
s = Digest::SHA2.digest(Digest::SHA2.digest(seed + pad))[0,@bitlength/8]
|
110
|
+
x = int_from_be(s)
|
111
|
+
pad = pad + "\x00".b
|
112
|
+
end
|
113
|
+
s
|
114
|
+
end
|
115
|
+
|
101
116
|
# Returns mmmmxxxx yyyyyyyy yyyyyyyy ... (16 bytes of y)
|
102
117
|
def string_from_point(m, x, y)
|
103
118
|
m = to_nibble(m)
|
@@ -154,7 +169,7 @@ module BTC
|
|
154
169
|
r[:total]
|
155
170
|
end
|
156
171
|
|
157
|
-
def be_from_int(i, pad =
|
172
|
+
def be_from_int(i, pad = @bitlength)
|
158
173
|
a = []
|
159
174
|
while i > 0
|
160
175
|
a.unshift(i % 256)
|
@@ -168,21 +183,21 @@ end
|
|
168
183
|
|
169
184
|
if $0 == __FILE__
|
170
185
|
|
171
|
-
|
186
|
+
ssss = BTC::SecretSharing.new(128)
|
172
187
|
require_relative 'data.rb'
|
173
188
|
|
174
189
|
# Usage
|
175
|
-
secret =
|
190
|
+
secret = ssss.random
|
176
191
|
puts "Secret: #{BTC.to_hex(secret)}"
|
177
|
-
shares =
|
192
|
+
shares = ssss.split(secret, 2, 3)
|
178
193
|
shares.each do |share|
|
179
194
|
puts "Share: #{BTC.to_hex(share)}"
|
180
195
|
end
|
181
|
-
restored_secret =
|
196
|
+
restored_secret = ssss.restore([shares[1], shares[0]])
|
182
197
|
puts "Recovered secret with shares 2 and 1: #{BTC.to_hex(restored_secret)}"
|
183
|
-
restored_secret =
|
198
|
+
restored_secret = ssss.restore([shares[0], shares[2]])
|
184
199
|
puts "Recovered secret with shares 1 and 3: #{BTC.to_hex(restored_secret)}"
|
185
|
-
restored_secret =
|
200
|
+
restored_secret = ssss.restore([shares[1], shares[2]])
|
186
201
|
puts "Recovered secret with shares 2 and 3: #{BTC.to_hex(restored_secret)}"
|
187
202
|
|
188
203
|
# Output:
|
@@ -232,16 +247,49 @@ if $0 == __FILE__
|
|
232
247
|
"2-of-2" => ["2125df3f1da76af07c37689382bc8201a6", "224bbe7e3b4ed5e0f86ed127057904034c"],
|
233
248
|
"2-of-3" => ["2125df3f1da76af07c37689382bc8201a6", "224bbe7e3b4ed5e0f86ed127057904034c", "23719dbd58f640d174a639ba88358604f2"],
|
234
249
|
"3-of-3" => ["31651161eeddabb39134be97908f0d7d9e", "32671d1a7e6d7ef24037990a5285a75164", "33062329aeaf79bc0d088f5845e3cd7b52"],
|
235
|
-
}
|
250
|
+
},
|
251
|
+
{
|
252
|
+
"secret" => "31415926535897932384626433", # 104 bits
|
253
|
+
"1-of-1" => ["1131415926535897932384626433"],
|
254
|
+
"1-of-2" => ["1131415926535897932384626433", "1231415926535897932384626433"],
|
255
|
+
"2-of-2" => ["21a8453099fb8ae36aab2c1b6000", "221f49080da3bd2f4232d3d45bde"],
|
256
|
+
"1-of-3" => ["1131415926535897932384626433", "1231415926535897932384626433", "1331415926535897932384626433"],
|
257
|
+
"2-of-3" => ["21a8453099fb8ae36aab2c1b6000", "221f49080da3bd2f4232d3d45bde", "23964cdf814bef7b19ba7b8d57ab"],
|
258
|
+
"3-of-3" => ["312b1880cc54fa4f009a4828f7d1", "3229a1cb3a58caea9c2bf0a31cb3", "332cdd38705eca6a65d87dd0d2d9"],
|
259
|
+
"4-of-6" => ["414dc7bfe7e209630e44617d9737", "422da138cfafb6fa65f2556740c0", "43bd57245c5ccd2a2b2018645fa5", "44e972e30c89b7beeec062b9f2df", "459e7dd55ed6e28541c5ecacf956", "46c9015bd1e4b949b5236e8271e1"],
|
260
|
+
"10-of-16"=>["a1b7a1ae5c3b1de94a8f4b8f7e05", "a25906c43a8969f6b5bf4be06006", "a3e97beb27daf0e2f81e0346a327", "a4d1a2cbee6be940edf213ccbc5f", "a50810074c61f554e9790453f951", "a629b4cf2ee2e5692af73337a0ca", "a7902bbc8ad42f8f9d15128e8758", "a8e6e7bce215a6f69d903a756a02", "a9834eca7f01f1a00215cf0ab33c", "aaa7b73a49f876d11a0b258fec2f", "abde0dc1d5af02f828197e7e0ac7", "acbc9befd7052707b1821140074e", "adadfaa8b410696a0d9089baaf84", "aebcb2502c16b5afd4f377c98514", "afeb62a04f2c15fa2f540d669b95", "a04b86c51029a5de8538e14edf9e"],
|
261
|
+
},
|
262
|
+
{
|
263
|
+
"secret" => "deadbeefcafebabedeadbeefca",
|
264
|
+
"1-of-1" => ["11deadbeefcafebabedeadbeefca"],
|
265
|
+
"2-of-2" => ["210833159d705e79f32a1c8cea96", "2231b86c4b15be3927758b5ae551"],
|
266
|
+
"2-of-3" => ["210833159d705e79f32a1c8cea96", "2231b86c4b15be3927758b5ae551", "235b3dc2f8bb1df85bc0fa28e00c"],
|
267
|
+
"3-of-3" => ["3112462cb0571d40f6e704adf5b7", "320841c292cc488c414627a293e1", "33c0a080972a809c9dfc169cca48"],
|
268
|
+
},
|
269
|
+
{
|
270
|
+
"secret" => "ffffffffffffffffffffffffee",
|
271
|
+
"1-of-1" => ["11ffffffffffffffffffffffffee"],
|
272
|
+
"2-of-2" => ["21b47b7bca3c91cfa72ec99d9ded", "2268f6f79479239f4e5d933b3bec"],
|
273
|
+
"2-of-3" => ["21b47b7bca3c91cfa72ec99d9ded", "2268f6f79479239f4e5d933b3bec", "231d72735eb5b56ef58c5cd8d9eb"],
|
274
|
+
"3-of-3" => ["31354043caf86f780c8d306fa32b", "32fc8f21351fc80c54a2b8604700", "3355ec983e7609bcd84097d1eba0"],
|
275
|
+
},
|
276
|
+
{
|
277
|
+
"secret" => "00000000000000000000000000",
|
278
|
+
"1-of-1" => ["1100000000000000000000000000"],
|
279
|
+
"2-of-2" => ["219aa26f55d8a706cb6801023e74", "223544deabb14e0d96d002047cf9"],
|
280
|
+
"2-of-3" => ["219aa26f55d8a706cb6801023e74", "223544deabb14e0d96d002047cf9", "23cfe74e0189f51462380306bb6d"],
|
281
|
+
"3-of-3" => ["315a50b9d324cbf8cf4546d9e085", "32ca50d93a5f8028070814b77faa", "3350005e35b01c8da7486998dd80"],
|
282
|
+
},
|
236
283
|
]
|
237
284
|
|
238
285
|
test_vectors.each do |test|
|
239
286
|
hexsecret = test.delete("secret")
|
240
287
|
secret = BTC.from_hex(hexsecret)
|
288
|
+
ssss = BTC::SecretSharing.new(secret.bytesize*8)
|
241
289
|
test.each do |rule, defined_shares|
|
242
290
|
m, n = rule.split("-of-").map{|x|x.to_i}
|
243
291
|
puts "Testing #{hexsecret} #{rule}:"
|
244
|
-
shares =
|
292
|
+
shares = ssss.split(secret, m, n)
|
245
293
|
hexshares = shares.map{|s| BTC.to_hex(s)}
|
246
294
|
failed = false
|
247
295
|
if hexshares != defined_shares
|
@@ -250,11 +298,11 @@ if $0 == __FILE__
|
|
250
298
|
puts " Expected: #{defined_shares.inspect}"
|
251
299
|
puts " Generated: #{hexshares.inspect}"
|
252
300
|
end
|
253
|
-
subshares =
|
254
|
-
restored_secret =
|
301
|
+
subshares = shares[0...m] # TODO: iterate over various combinations
|
302
|
+
restored_secret = ssss.restore(subshares)
|
255
303
|
if restored_secret != secret
|
256
304
|
failed = true
|
257
|
-
puts "Failed #{hexsecret} #{rule} test: failed to restore secret using #{subshares.inspect}"
|
305
|
+
puts "Failed #{hexsecret} #{rule} test: failed to restore secret using #{subshares.map{|s| BTC.to_hex(s)}.inspect}"
|
258
306
|
end
|
259
307
|
if !failed
|
260
308
|
puts "Ok."
|
@@ -262,4 +310,30 @@ if $0 == __FILE__
|
|
262
310
|
end
|
263
311
|
end
|
264
312
|
|
313
|
+
|
314
|
+
begin
|
315
|
+
require_relative 'base58'
|
316
|
+
payload_length = 13
|
317
|
+
lengths = {}
|
318
|
+
(0..255).each do |ver|
|
319
|
+
prefixes = []
|
320
|
+
s = nil
|
321
|
+
(0..255).each do |i|
|
322
|
+
s = BTC::Base58.base58_from_data(ver.chr + (i.chr*payload_length))
|
323
|
+
#lengths[s.length] = 1
|
324
|
+
prefixes << s[0,1]
|
325
|
+
s = BTC::Base58.base58_from_data(ver.chr + Digest::SHA2.digest(ver.to_s + i.to_s)[0,payload_length])
|
326
|
+
lengths[s.length] = 1
|
327
|
+
prefixes << s[0,1]
|
328
|
+
end
|
329
|
+
prefixes = prefixes.uniq
|
330
|
+
puts "Ver: #{ver} => #{prefixes}"
|
331
|
+
if prefixes.size == 1
|
332
|
+
puts " " + s
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
puts "Lengths: #{lengths.keys.sort.inspect}"
|
337
|
+
rescue => e
|
338
|
+
end
|
265
339
|
end
|
data/lib/btcruby/version.rb
CHANGED
data/spec/ssss_spec.rb
CHANGED
@@ -4,8 +4,11 @@ describe BTC::SecretSharing do
|
|
4
4
|
SSSS = BTC::SecretSharing
|
5
5
|
|
6
6
|
test_vectors = [
|
7
|
+
|
8
|
+
# 128-bit secrets
|
9
|
+
|
7
10
|
{
|
8
|
-
"secret" => "31415926535897932384626433832795",
|
11
|
+
"secret" => "31415926535897932384626433832795", # 128 bits
|
9
12
|
"1-of-1" => ["1131415926535897932384626433832795"],
|
10
13
|
"1-of-2" => ["1131415926535897932384626433832795", "1231415926535897932384626433832795"],
|
11
14
|
"2-of-2" => ["215af384f05d9b45f0e4e348f95b371acd", "2284a5b0ba67ddf44ea6422f8e82eb0e05"],
|
@@ -39,21 +42,93 @@ describe BTC::SecretSharing do
|
|
39
42
|
"2-of-2" => ["2125df3f1da76af07c37689382bc8201a6", "224bbe7e3b4ed5e0f86ed127057904034c"],
|
40
43
|
"2-of-3" => ["2125df3f1da76af07c37689382bc8201a6", "224bbe7e3b4ed5e0f86ed127057904034c", "23719dbd58f640d174a639ba88358604f2"],
|
41
44
|
"3-of-3" => ["31651161eeddabb39134be97908f0d7d9e", "32671d1a7e6d7ef24037990a5285a75164", "33062329aeaf79bc0d088f5845e3cd7b52"],
|
42
|
-
}
|
45
|
+
},
|
46
|
+
|
47
|
+
|
48
|
+
# 104-bit secrets
|
49
|
+
|
50
|
+
{
|
51
|
+
"secret" => "31415926535897932384626433",
|
52
|
+
"1-of-1" => ["1131415926535897932384626433"],
|
53
|
+
"1-of-2" => ["1131415926535897932384626433", "1231415926535897932384626433"],
|
54
|
+
"2-of-2" => ["21a8453099fb8ae36aab2c1b6000", "221f49080da3bd2f4232d3d45bde"],
|
55
|
+
"1-of-3" => ["1131415926535897932384626433", "1231415926535897932384626433", "1331415926535897932384626433"],
|
56
|
+
"2-of-3" => ["21a8453099fb8ae36aab2c1b6000", "221f49080da3bd2f4232d3d45bde", "23964cdf814bef7b19ba7b8d57ab"],
|
57
|
+
"3-of-3" => ["312b1880cc54fa4f009a4828f7d1", "3229a1cb3a58caea9c2bf0a31cb3", "332cdd38705eca6a65d87dd0d2d9"],
|
58
|
+
"4-of-6" => ["414dc7bfe7e209630e44617d9737", "422da138cfafb6fa65f2556740c0", "43bd57245c5ccd2a2b2018645fa5", "44e972e30c89b7beeec062b9f2df", "459e7dd55ed6e28541c5ecacf956", "46c9015bd1e4b949b5236e8271e1"],
|
59
|
+
"10-of-16"=>["a1b7a1ae5c3b1de94a8f4b8f7e05", "a25906c43a8969f6b5bf4be06006", "a3e97beb27daf0e2f81e0346a327", "a4d1a2cbee6be940edf213ccbc5f", "a50810074c61f554e9790453f951", "a629b4cf2ee2e5692af73337a0ca", "a7902bbc8ad42f8f9d15128e8758", "a8e6e7bce215a6f69d903a756a02", "a9834eca7f01f1a00215cf0ab33c", "aaa7b73a49f876d11a0b258fec2f", "abde0dc1d5af02f828197e7e0ac7", "acbc9befd7052707b1821140074e", "adadfaa8b410696a0d9089baaf84", "aebcb2502c16b5afd4f377c98514", "afeb62a04f2c15fa2f540d669b95", "a04b86c51029a5de8538e14edf9e"],
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"secret" => "deadbeefcafebabedeadbeefca",
|
63
|
+
"1-of-1" => ["11deadbeefcafebabedeadbeefca"],
|
64
|
+
"2-of-2" => ["210833159d705e79f32a1c8cea96", "2231b86c4b15be3927758b5ae551"],
|
65
|
+
"2-of-3" => ["210833159d705e79f32a1c8cea96", "2231b86c4b15be3927758b5ae551", "235b3dc2f8bb1df85bc0fa28e00c"],
|
66
|
+
"3-of-3" => ["3112462cb0571d40f6e704adf5b7", "320841c292cc488c414627a293e1", "33c0a080972a809c9dfc169cca48"],
|
67
|
+
},
|
68
|
+
{
|
69
|
+
"secret" => "ffffffffffffffffffffffffee",
|
70
|
+
"1-of-1" => ["11ffffffffffffffffffffffffee"],
|
71
|
+
"2-of-2" => ["21b47b7bca3c91cfa72ec99d9ded", "2268f6f79479239f4e5d933b3bec"],
|
72
|
+
"2-of-3" => ["21b47b7bca3c91cfa72ec99d9ded", "2268f6f79479239f4e5d933b3bec", "231d72735eb5b56ef58c5cd8d9eb"],
|
73
|
+
"3-of-3" => ["31354043caf86f780c8d306fa32b", "32fc8f21351fc80c54a2b8604700", "3355ec983e7609bcd84097d1eba0"],
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"secret" => "00000000000000000000000000",
|
77
|
+
"1-of-1" => ["1100000000000000000000000000"],
|
78
|
+
"2-of-2" => ["219aa26f55d8a706cb6801023e74", "223544deabb14e0d96d002047cf9"],
|
79
|
+
"2-of-3" => ["219aa26f55d8a706cb6801023e74", "223544deabb14e0d96d002047cf9", "23cfe74e0189f51462380306bb6d"],
|
80
|
+
"3-of-3" => ["315a50b9d324cbf8cf4546d9e085", "32ca50d93a5f8028070814b77faa", "3350005e35b01c8da7486998dd80"],
|
81
|
+
},
|
82
|
+
|
83
|
+
|
84
|
+
# 96-bit secrets
|
85
|
+
|
86
|
+
{
|
87
|
+
"secret" => "314159265358979323846264",
|
88
|
+
"1-of-1" => ["11314159265358979323846264"],
|
89
|
+
"1-of-2" => ["11314159265358979323846264", "12314159265358979323846264"],
|
90
|
+
"2-of-2" => ["219c6d2fc2303e0a64e380b5a8", "220799065e0d237d36a37d08fd"],
|
91
|
+
"1-of-3" => ["11314159265358979323846264", "12314159265358979323846264", "13314159265358979323846264"],
|
92
|
+
"2-of-3" => ["219c6d2fc2303e0a64e380b5a8", "220799065e0d237d36a37d08fd", "2372c4dcf9ea08f00863795c41"],
|
93
|
+
"3-of-3" => ["318934eda6285292a6b6f2fd0a", "321f6b0d5fe662e2dec79d1572", "33f3e3b8538d89883b5582ab7a"],
|
94
|
+
"4-of-6" => ["4174b316d14c485cf444325100", "4273da5159c33a43335df79a53", "4337969f2f75a6c630f732b1a1", "44c8c796c2210661cd96420a1d", "45304cce8182d191e9c184172d", "467705dcdd5880d265ff574bf3"],
|
95
|
+
"10-of-16"=>["a1090ba03f98fe44fb0c9cbc92", "a28a63d4872a1372ba8bcaa0d9", "a3a6970d6bf596f299b7eea31b", "a43c1da6ae60d076ed901e8853", "a591259cce1d7845820d77ff69", "a685b97fb8b78b4a60fddc7e8c", "a77f135e267940f39c0eb82fb0", "a8586914b4373d3485c68cb2b7", "a9838f54e6dc7e957ebe2c0af8", "aaf53281e124ae4daa376055fc", "ab7d182aacdc5f0d7f3629e66b", "acc2e1748f396e5c4183c7122f", "ad4b1e32f36a2436f87f5f6eb7", "aea729b60757d4fd78576f54f4", "af44458534c9b2a98538f06161", "a033b3472c9623ccff2db82f42"],
|
96
|
+
},
|
97
|
+
{
|
98
|
+
"secret" => "deadbeefcafebabedeadbeef",
|
99
|
+
"1-of-1" => ["11deadbeefcafebabedeadbeef"],
|
100
|
+
"2-of-2" => ["21b7d008c40782c660de3f2759", "2290f252984406d202ddd08fc3"],
|
101
|
+
"2-of-3" => ["21b7d008c40782c660de3f2759", "2290f252984406d202ddd08fc3", "236a149c6c808adda4dd61f82d"],
|
102
|
+
"3-of-3" => ["31f0e31071c238b0b8edf3e099", "32bc5fadd11bda67369fbdfebe", "334123970dd7e3de37f40c195e"],
|
103
|
+
},
|
104
|
+
{
|
105
|
+
"secret" => "ffffffffffffffffffffffee",
|
106
|
+
"1-of-1" => ["11ffffffffffffffffffffffee"],
|
107
|
+
"2-of-2" => ["21177a5ce6e086a40df2a3892c", "222ef4b9cdc10d481be5471259"],
|
108
|
+
"2-of-3" => ["21177a5ce6e086a40df2a3892c", "222ef4b9cdc10d481be5471259", "23466f16b4a193ec29d7ea9b86"],
|
109
|
+
"3-of-3" => ["315adf89c7779b2169a341572a", "32ea101e87f4972984b102f614", "33ad91be4176f418512944dcce"],
|
110
|
+
},
|
111
|
+
{
|
112
|
+
"secret" => "000000000000000000000000",
|
113
|
+
"1-of-1" => ["11000000000000000000000000"],
|
114
|
+
"2-of-2" => ["21197de3ef5aae4f1df4e98384", "2232fbc7deb55c9e3be9d30708"],
|
115
|
+
"2-of-3" => ["21197de3ef5aae4f1df4e98384", "2232fbc7deb55c9e3be9d30708", "234c79abce100aed59debc8a8c"],
|
116
|
+
"3-of-3" => ["317119aa02f2a7f1fccb38a7f7", "324dc572966cb5fdac97a47389", "33960359ba6e2a230f654362a5"],
|
117
|
+
},
|
43
118
|
]
|
44
119
|
|
45
120
|
test_vectors.each do |test|
|
46
121
|
hexsecret = test.delete("secret")
|
47
122
|
secret = BTC.from_hex(hexsecret)
|
123
|
+
ssss = BTC::SecretSharing.new(secret.bytesize*8)
|
48
124
|
test.each do |rule, defined_shares|
|
49
125
|
m, n = rule.split("-of-").map{|x|x.to_i}
|
50
126
|
it "Should split and restore #{rule} shares for #{hexsecret}" do
|
51
|
-
shares =
|
127
|
+
shares = ssss.split(secret, m, n)
|
52
128
|
hexshares = shares.map{|s| BTC.to_hex(s)}
|
53
|
-
failed = false
|
54
129
|
hexshares.must_equal defined_shares
|
55
|
-
subshares =
|
56
|
-
restored_secret =
|
130
|
+
subshares = shares[0...m] # TODO: iterate over various combinations
|
131
|
+
restored_secret = ssss.restore(subshares)
|
57
132
|
BTC.to_hex(restored_secret).must_equal hexsecret
|
58
133
|
end
|
59
134
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: btcruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '1.
|
4
|
+
version: '1.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Andreev
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-11-
|
12
|
+
date: 2015-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|