btcruby 1.4 → 1.5
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/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
|