tss 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +8 -0
- data/README.md +70 -99
- data/lib/custom_contracts.rb +3 -4
- data/lib/tss/cli_combine.rb +8 -1
- data/lib/tss/cli_split.rb +14 -13
- data/lib/tss/combiner.rb +9 -14
- data/lib/tss/splitter.rb +18 -14
- data/lib/tss/tss.rb +14 -15
- data/lib/tss/util.rb +33 -11
- data/lib/tss/version.rb +1 -1
- data/tss.gemspec +3 -1
- metadata +7 -6
- metadata.gz.sig +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3597bdbe0559f746e7f6b44c9e15b493cf48d92e
|
4
|
+
data.tar.gz: b049be29b2c0f1a1360e3114133f0524ad361562
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37dc3d8473236a57165d3e12c2accd5e66b9dd769ad80c6e401f73e261227ac3b3db93749f3188878a77b65512fc3d011384f4e07f37f177e13490a41ab5bd28
|
7
|
+
data.tar.gz: 3a6842d643b9ccb6121bcef80d15453ae26a5ea3fd8db926d9d1a0384008e7089dd5ed232ecc2bc4df74b18c5fc6e2b460a4b9fca85f1421ad27a3c046d555d3
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/.rubocop.yml
CHANGED
@@ -743,7 +743,7 @@ Style/LineEndConcatenation:
|
|
743
743
|
line end.
|
744
744
|
Enabled: false
|
745
745
|
|
746
|
-
Style/
|
746
|
+
Style/MethodCallWithoutArgsParentheses:
|
747
747
|
Description: 'Do not use parentheses for method calls with no arguments.'
|
748
748
|
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens'
|
749
749
|
Enabled: false
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.4.0
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## v0.5.0 (1/28/2017)
|
4
|
+
|
5
|
+
* Breaking refactor to use automatic PKCS#7 padding on secrets w/ 16 byte block size.
|
6
|
+
* Update Copyright year
|
7
|
+
* Ruby 2.4.0 testing
|
8
|
+
* Update version of sysrandom gem
|
9
|
+
* Fixed minitest spec warning
|
10
|
+
|
3
11
|
## v0.4.2 (10/12/2016)
|
4
12
|
|
5
13
|
* Sign the gem with a new cert that expires in 10 years.
|
data/README.md
CHANGED
@@ -74,29 +74,29 @@ secret unicode characters ½ ♥ 💩
|
|
74
74
|
|
75
75
|
```ruby
|
76
76
|
$ bundle exec bin/console
|
77
|
-
|
77
|
+
> require 'tss'
|
78
78
|
=> false
|
79
|
-
|
80
|
-
=> ["tss~v1~
|
81
|
-
"tss~v1~
|
82
|
-
"tss~v1~
|
83
|
-
"tss~v1~
|
84
|
-
"tss~v1~
|
85
|
-
|
79
|
+
> shares = TSS.split(secret: 'my deep dark secret')
|
80
|
+
=> ["tss~v1~506168fade769236~3~NTA2MTY4ZmFkZTc2OTIzNgIDAEEBIM39jPGXFz4zKCObWgp2zQmCuUx92-VUf48FWQFqnLF3bw6VtVjYK7JRfESZIREdzhWcQuTQVuGKazxWRK27Tg==",
|
81
|
+
"tss~v1~506168fade769236~3~NTA2MTY4ZmFkZTc2OTIzNgIDAEEC1E8YyDhp5NeZvF6vHeUT6HoiU0AgoF69jyjNRbtcIi1YoymJTau1rJP-3nQXOofaB2LgnAhJpbB8vrID9WTKgQ==",
|
82
|
+
"tss~v1~506168fade769236~3~NTA2MTY4ZmFkZTc2OTIzNgIDAEEDmfvFIKybg8nO9Q9fZ5wARgHFngFQdrbk_arFEbc7s5HedTjzkoZYLlV8xnywt4AVAHAO0nSLY3C7iJPifH5VYA==",
|
83
|
+
"tss~v1~506168fade769236~3~NTA2MTY4ZmFkZTc2OTIzNgIDAEEEiBoCoHycMNTS5yQEU8_Sc7eVlIZOJP1-ka_7MPTlC1p2DyNdGvQxy3pBFZyH8WXAY9ICBxiZRDCJisFrebviAg==",
|
84
|
+
"tss~v1~506168fade769236~3~NTA2MTY4ZmFkZTc2OTIzNgIDAEEFxa7fSOhuV8qFrnX0KbbB3cxyWcc-8hUn4y3zZPiCmubw2TInxdncSbzDDZQgfGIPZMDsSWRbgvBOvOCK8KF94w=="]
|
85
|
+
> secret = TSS.combine(shares: shares)
|
86
86
|
=> {:hash=>"f1b91fef6a7535a974d3644c3eac16d2c907720c981290214d5d1db7cdb724af",
|
87
87
|
:hash_alg=>"SHA256",
|
88
|
-
:identifier=>"
|
89
|
-
:process_time=>0.
|
88
|
+
:identifier=>"506168fade769236",
|
89
|
+
:process_time=>0.94,
|
90
90
|
:secret=>"my deep dark secret",
|
91
91
|
:threshold=>3}
|
92
|
-
|
92
|
+
> puts secret[:secret]
|
93
93
|
my deep dark secret
|
94
94
|
=> nil
|
95
95
|
```
|
96
96
|
|
97
97
|
## Is it any good?
|
98
98
|
|
99
|
-
While this implementation has not had a formal security review, the cryptographic
|
99
|
+
While this implementation has not yet had a formal security review, the cryptographic
|
100
100
|
underpinnings were carefully specified in an IETF draft document authored by a
|
101
101
|
noted cryptographer. I have reached out to individuals respected in the field
|
102
102
|
for their work in implementing cryptographic solutions to help review this code.
|
@@ -128,13 +128,14 @@ nothing to slow down an attacker if they have access to enough shares.
|
|
128
128
|
|
129
129
|
* If you send keys by email, or some other insecure channel, then your email
|
130
130
|
provider, or any entity with access to their data, now also has the keys to
|
131
|
-
your data. They just need to collect enough keys to meet the threshold.
|
131
|
+
your data. They just need to collect enough keys to meet the threshold. Sending
|
132
|
+
enough shares to recreate a secret through any single provider offers no
|
133
|
+
more security than sending the key itself.
|
132
134
|
|
133
135
|
* Use public key cryptography to encrypt secret shares with the public key of
|
134
136
|
each individual recipient. This can protect the share data from unwanted use while
|
135
|
-
in transit or at rest.
|
136
|
-
|
137
|
-
or [TweetNaCl.js](https://github.com/dchest/tweetnacl-js).
|
137
|
+
in transit or at rest. OpenPGP would be one such tool for encrypting shares to
|
138
|
+
send safely.
|
138
139
|
|
139
140
|
* Put careful thought into how you want to distribute shares. It often makes
|
140
141
|
sense to give individuals more than one share.
|
@@ -144,15 +145,10 @@ sense to give individuals more than one share.
|
|
144
145
|
There is pretty extensive inline documentation. You can view the latest
|
145
146
|
auto-generated docs at [http://www.rubydoc.info/gems/tss](http://www.rubydoc.info/gems/tss)
|
146
147
|
|
147
|
-
## Supported
|
148
|
+
## Supported Ruby Versions
|
148
149
|
|
149
|
-
TSS is continuously integration tested on
|
150
|
-
|
151
|
-
* MRI 2.2.5
|
152
|
-
* MRI 2.3.1
|
153
|
-
* jruby-9.0.5.0
|
154
|
-
|
155
|
-
It may work on others as well.
|
150
|
+
TSS is continuously integration tested on a number of Ruby versions. See the file
|
151
|
+
`.travis.yml` in the root of this repository for the currently tested versions.
|
156
152
|
|
157
153
|
## Installation
|
158
154
|
|
@@ -261,12 +257,14 @@ cautioned that storing the secret on a filesystem may expose you to certain
|
|
261
257
|
attacks since it can be hard to fully erase files once written.
|
262
258
|
|
263
259
|
```text
|
260
|
+
$ cat /tmp/secret.txt
|
261
|
+
my secret
|
264
262
|
$ tss split -I /tmp/secret.txt
|
265
|
-
tss~v1~
|
266
|
-
tss~v1~
|
267
|
-
tss~v1~
|
268
|
-
tss~v1~
|
269
|
-
tss~v1~
|
263
|
+
tss~v1~8b66eb89ee25a46c~3~OGI2NmViODllZTI1YTQ2YwIDACsBqgQvwFhKboLMAmYwF5_CvaUwM8pmqUipbMRzakdbP53WJa-E6tf2nl2M
|
264
|
+
tss~v1~8b66eb89ee25a46c~3~OGI2NmViODllZTI1YTQ2YwIDACsCk1EU-HwvC6pjvQ5wDas221Qs4A7TtJNpi-Su8hxOqrsCSQ8t11aiQUpm
|
265
|
+
tss~v1~8b66eb89ee25a46c~3~OGI2NmViODllZTI1YTQ2YwIDACsDVCwbS0EGF03btYwqqVuk7S0z-nSinHtPpsFaFm5dys85j3JlK-yCVNyP
|
266
|
+
tss~v1~8b66eb89ee25a46c~3~OGI2NmViODllZTI1YTQ2YwIDACsEPUzgi8CDn4ix1dLQTQDj2yTdeeQcZAvGuMyQ_H7EepN6WO_KB1DuqTxm
|
267
|
+
tss~v1~8b66eb89ee25a46c~3~OGI2NmViODllZTI1YTQ2YwIDACsF-jHvOP2qg28J3VCK6fBx7V3CY55tTOPglelkGAzXGudBnpKC--rOvKqP
|
270
268
|
```
|
271
269
|
|
272
270
|
**Example : `interactive`**
|
@@ -282,11 +280,11 @@ Enter your secret, enter a dot (.) on a line by itself to finish :
|
|
282
280
|
secret > the vault password is:
|
283
281
|
secret > V0ulT!
|
284
282
|
secret > .
|
285
|
-
tss~v1~
|
286
|
-
tss~v1~
|
287
|
-
tss~v1~
|
288
|
-
tss~v1~
|
289
|
-
tss~v1~
|
283
|
+
tss~v1~1f8532a9d185efc4~3~MWY4NTMyYTlkMTg1ZWZjNAIDAD8BJkMvkHUGPQk1HQr_jVj9JkhavJVkdeFDEtRAf8O6vjksCjMMjiyuUL0bOD7vDnmdrzHK8QVymXU5vnjAREs=
|
284
|
+
tss~v1~1f8532a9d185efc4~3~MWY4NTMyYTlkMTg1ZWZjNAIDAD8CJpiKCEtSfmugr_gbvEIBs2M2sZfHxuZsBuPpB35OGeyWmGZCyJCNu0W2z3abkV1Q8uTPvT75YYRpw6BcdvQ=
|
285
|
+
tss~v1~1f8532a9d185efc4~3~MWY4NTMyYTlkMTg1ZWZjNAIDAD8DdLPAuEg1Ng7hkoKFQmmL-lkILWvQiQ15JELFLJz-PvdZucDCqS-X6QAIbwWE3u2XrTgsH1kmIvpMeZhzfPk=
|
286
|
+
tss~v1~1f8532a9d185efc4~3~MWY4NTMyYTlkMTg1ZWZjNAIDAD8EJT1XJ-DeOXuE3JD6VpZk79945_peSk1ij1Mk5ql-l2jkv85yGBbyH0VIBmJp2WsEMmESZqTsQ9kKB-0Ljq8=
|
287
|
+
tss~v1~1f8532a9d185efc4~3~MWY4NTMyYTlkMTg1ZWZjNAIDAD8FdxYdl-O5cR7F4epkqL3upuVGewZJBaZ3rfIIzUvOsHMrnmjyeanoTQD2phF2ltvDbb3xxMMzAKcvvdUkhKI=
|
290
288
|
```
|
291
289
|
|
292
290
|
### CLI Share Combining
|
@@ -339,29 +337,29 @@ a secret
|
|
339
337
|
```text
|
340
338
|
$ cat /tmp/shares.txt
|
341
339
|
# THRESHOLD SECRET SHARING SHARES
|
342
|
-
#
|
340
|
+
# 2017-01-29T02:01:00Z
|
343
341
|
# https://github.com/grempe/tss-rb
|
344
342
|
|
345
343
|
|
346
|
-
tss~v1~
|
347
|
-
tss~v1~
|
348
|
-
tss~v1~
|
349
|
-
tss~v1~
|
350
|
-
tss~v1~
|
344
|
+
tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoBbga2N__A9QOleLhC5R5b7stJ26iMPNpQ95YpmK-tWIrd-CYcrXGmcys=
|
345
|
+
tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoCGXsZkLOG7uDOVN1Zn46pqftX4noA8LfXugg14KBfSggYP9fw4Ce10YA=
|
346
|
+
tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoDFl3cwi80fpdh-I9eK3kNa8V9OlXX1Wx8y5a6bk2S0TDJzocr-1C3TWs=
|
347
|
+
tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoEEspmyzmbnrSr7v41FFlHVTqQ6dx4aho8q5T1CBHQbNimdCv3gVXS50I=
|
348
|
+
tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoFHeyjmaUpDsMEQqwyoK7jlwS6MfOvT8GX2gp6hvwd9-B3hXssmiLQe6k=
|
351
349
|
|
352
350
|
$ tss combine
|
353
351
|
Enter shares, one per line, and a dot (.) on a line by itself to finish :
|
354
|
-
share> tss~v1~
|
355
|
-
share> tss~v1~
|
356
|
-
share> tss~v1~
|
352
|
+
share> tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoBbga2N__A9QOleLhC5R5b7stJ26iMPNpQ95YpmK-tWIrd-CYcrXGmcys=
|
353
|
+
share> tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoCGXsZkLOG7uDOVN1Zn46pqftX4noA8LfXugg14KBfSggYP9fw4Ce10YA=
|
354
|
+
share> tss~v1~b9f7f87bc83fd89b~3~YjlmN2Y4N2JjODNmZDg5YgIDACoDFl3cwi80fpdh-I9eK3kNa8V9OlXX1Wx8y5a6bk2S0TDJzocr-1C3TWs=
|
357
355
|
share> .
|
358
356
|
|
359
357
|
RECOVERED SECRET METADATA
|
360
358
|
*************************
|
361
359
|
hash : d4ea4551e9ff2cf56303875b1901fb8608a6164260c3b20c0976c7b606a4efc0
|
362
360
|
hash_alg : SHA256
|
363
|
-
identifier :
|
364
|
-
process_time :
|
361
|
+
identifier : b9f7f87bc83fd89b
|
362
|
+
process_time : 1.22ms
|
365
363
|
threshold : 3
|
366
364
|
secret :
|
367
365
|
a secret
|
@@ -373,11 +371,11 @@ The basic usage is as follows using the arguments described below.
|
|
373
371
|
|
374
372
|
```ruby
|
375
373
|
shares = TSS.split(secret: secret,
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
374
|
+
threshold: threshold,
|
375
|
+
num_shares: num_shares,
|
376
|
+
identifier: identifier,
|
377
|
+
hash_alg: hash_alg,
|
378
|
+
padding: true)
|
381
379
|
```
|
382
380
|
|
383
381
|
### Arguments
|
@@ -385,7 +383,7 @@ shares = TSS.split(secret: secret,
|
|
385
383
|
All arguments are passed as keys in a single Hash.
|
386
384
|
|
387
385
|
The `secret` (required) value must be provided as a String with either
|
388
|
-
a `UTF-8` or `US-ASCII` encoding. The Byte length must be `<= 65,
|
386
|
+
a `UTF-8` or `US-ASCII` encoding. The Byte length must be `<= 65,486`. You can
|
389
387
|
test this beforehand with `'my string secret'.bytes.to_a.length`. Keep in mind
|
390
388
|
that this length also includes padding and the verification hash so your
|
391
389
|
secret may need to be shorter depending on the settings you choose.
|
@@ -426,44 +424,17 @@ The `HUMAN` format can be easily shared in a tweet, email, or even a URL. The
|
|
426
424
|
easier to visually compare shares and see if they have matching identifiers and
|
427
425
|
if you have enough shares to reach the threshold.
|
428
426
|
|
429
|
-
The `
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
`pad_blocksize` defaults to no padding (0). For example:
|
435
|
-
|
436
|
-
```ruby
|
437
|
-
padding_blocksize: 8
|
438
|
-
(padded with zeros for illustration purposes)
|
439
|
-
|
440
|
-
# a single char, padded up to 8
|
441
|
-
'a' -> "0000000a"
|
442
|
-
|
443
|
-
# 8 chars, no padding needed to get to 8
|
444
|
-
'aaaaaaaa' -> "aaaaaaaa"
|
445
|
-
|
446
|
-
# 9 chars, bumps blocksize up to 16 and pads
|
447
|
-
'aaaaaaaaa' -> "0000000aaaaaaaaa"
|
448
|
-
```
|
427
|
+
The `padding` arg accepts a Boolean to indicate whether to apply PKCS#7
|
428
|
+
padding to the secret string. This is applied and removed automatically
|
429
|
+
by default and padding defaults to a block size of 16 bytes. You probably
|
430
|
+
never need to use this option to turn it off unless you are trying to
|
431
|
+
trade shares with the Python implementation.
|
449
432
|
|
450
433
|
Since TSS share data is essentially the same size as the original secret
|
451
|
-
(with a known size header), padding smaller secrets may help
|
452
|
-
of the secret itself from an attacker. Padding is not part of
|
453
|
-
so other TSS clients won't strip off the padding and may fail
|
454
|
-
shares.
|
455
|
-
the `pad_blocksize` padding and just pad the secret yourself prior to splitting
|
456
|
-
it. You need to pad using a character other than `"\u001F"`.
|
457
|
-
|
458
|
-
If you want to do padding this way, there is a utility method you can use
|
459
|
-
to do that. This is the same method used internally.
|
460
|
-
|
461
|
-
```ruby
|
462
|
-
# Util.left_pad(byte_multiple, input_string, pad_char = "\u001F")
|
463
|
-
|
464
|
-
> Util.left_pad(16, 'abc', "0")
|
465
|
-
=> "0000000000000abc"
|
466
|
-
```
|
434
|
+
(with a known size header), the padding applied to smaller secrets may help
|
435
|
+
mask the exact size of the secret itself from an attacker. Padding is not part of
|
436
|
+
the RTSS spec so other TSS clients won't strip off the padding and may fail
|
437
|
+
when recombining shares.
|
467
438
|
|
468
439
|
### Example Usage
|
469
440
|
|
@@ -475,20 +446,20 @@ identifier = SecureRandom.hex(8)
|
|
475
446
|
hash_alg = 'SHA256'
|
476
447
|
format = 'HUMAN'
|
477
448
|
|
478
|
-
s = TSS.split(secret: secret, threshold: threshold, num_shares: num_shares, identifier: identifier, hash_alg: 'SHA256',
|
449
|
+
s = TSS.split(secret: secret, threshold: threshold, num_shares: num_shares, identifier: identifier, hash_alg: 'SHA256', format: format)
|
479
450
|
|
480
|
-
=> ["tss~v1~
|
481
|
-
"tss~v1~
|
482
|
-
"tss~v1~
|
483
|
-
"tss~v1~
|
484
|
-
"tss~v1~
|
451
|
+
=> ["tss~v1~79923b087dab7fa2~3~Nzk5MjNiMDg3ZGFiN2ZhMgIDADEB2qA6IYq8yOGlPAl0B4MgRsVazZMWGLwRNgGMPKutOYbB0gjkVHNqbNYl-0l1f98W",
|
452
|
+
"tss~v1~79923b087dab7fa2~3~Nzk5MjNiMDg3ZGFiN2ZhMgIDADECvjwdUHc8MzqvIllR2Rj9TnnlN_2eRUzH6MUsd8ncua4jpXQ3FgM1hUmLHmrgHq0u",
|
453
|
+
"tss~v1~79923b087dab7fa2~3~Nzk5MjNiMDg3ZGFiN2ZhMgIDADEDAvNIUZ_hiftofyog257YDWds4q9MP14-rDCxQsauUyxqBtzur6Ch5-rSCHRPt4Dv",
|
454
|
+
"tss~v1~79923b087dab7fa2~3~Nzk5MjNiMDg3ZGFiN2ZhMgIDADEEF7zGEx0GSC6YLgVD6xcQispDCO_JTUSDFbsbpalopakh0FmTfmO-JJKGQSlJb1il",
|
455
|
+
"tss~v1~79923b087dab7fa2~3~Nzk5MjNiMDg3ZGFiN2ZhMgIDADEFq3OTEvXb8u9fc3Yy6ZE1ydTK3b0bN1Z6UU6GkKYaTytoc_FKx8AqRjHfVzfmxnVk"]
|
485
456
|
|
486
|
-
|
457
|
+
secret = TSS.combine(shares: s)
|
487
458
|
|
488
|
-
|
459
|
+
=> {:hash=>"dbd318c1c462aee872f41109a4dfd3048871a03dedd0fe0e757ced57dad6f2d7",
|
489
460
|
:hash_alg=>"SHA256",
|
490
|
-
:identifier=>"
|
491
|
-
:process_time=>0.
|
461
|
+
:identifier=>"79923b087dab7fa2",
|
462
|
+
:process_time=>0.92,
|
492
463
|
:secret=>"foo bar baz",
|
493
464
|
:threshold=>3}
|
494
465
|
```
|
@@ -558,7 +529,7 @@ many combinations (`2.88 * 10^75`) as there are Atoms in the Universe (`10^80`).
|
|
558
529
|
If the combine operation does not result in a secret being successfully
|
559
530
|
extracted, then a `TSS::Error` exception will be raised.
|
560
531
|
|
561
|
-
A great short read on
|
532
|
+
A great short read on big numbers is
|
562
533
|
[On the (Small) Number of Atoms in the Universe](http://norvig.com/atoms.html)
|
563
534
|
|
564
535
|
### Exception Handling
|
@@ -702,7 +673,7 @@ contributors are expected to adhere to the
|
|
702
673
|
|
703
674
|
### Copyright
|
704
675
|
|
705
|
-
(c) 2016 Glenn Rempe <[glenn@rempe.us](mailto:glenn@rempe.us)> ([https://www.rempe.us/](https://www.rempe.us/))
|
676
|
+
(c) 2016-2017 Glenn Rempe <[glenn@rempe.us](mailto:glenn@rempe.us)> ([https://www.rempe.us/](https://www.rempe.us/))
|
706
677
|
|
707
678
|
### License
|
708
679
|
|
data/lib/custom_contracts.rb
CHANGED
@@ -18,13 +18,12 @@ module Contracts
|
|
18
18
|
class SecretArg
|
19
19
|
def self.valid? val
|
20
20
|
val.is_a?(String) &&
|
21
|
-
val.length.between?(1,
|
22
|
-
['UTF-8', 'US-ASCII'].include?(val.encoding.name)
|
23
|
-
val.slice(0) != "\u001F"
|
21
|
+
val.length.between?(1,TSS::MAX_UNPADDED_SECRET_SIZE) &&
|
22
|
+
['UTF-8', 'US-ASCII'].include?(val.encoding.name)
|
24
23
|
end
|
25
24
|
|
26
25
|
def self.to_s
|
27
|
-
|
26
|
+
"must be a UTF-8 or US-ASCII String between 1 and #{TSS::MAX_UNPADDED_SECRET_SIZE} characters in length"
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
data/lib/tss/cli_combine.rb
CHANGED
@@ -6,6 +6,7 @@ module TSS
|
|
6
6
|
|
7
7
|
method_option :input_file, :aliases => '-I', :banner => 'input_file', :type => :string, :desc => 'A filename to read shares from'
|
8
8
|
method_option :output_file, :aliases => '-O', :banner => 'output_file', :type => :string, :desc => 'A filename to write the recovered secret to'
|
9
|
+
method_option :padding, :type => :boolean, :default => true, :desc => 'Whether PKCS#7 padding is expected in the secret and should be removed'
|
9
10
|
|
10
11
|
desc 'combine', 'Enter shares to recover a split secret'
|
11
12
|
|
@@ -35,6 +36,12 @@ module TSS
|
|
35
36
|
on the output file should provide a digest matching that of the secret
|
36
37
|
when it was originally split.
|
37
38
|
|
39
|
+
padding/no-padding :
|
40
|
+
Whether or not PKCS#7 padding should be removed from secret data. By
|
41
|
+
default padding is applied to shared secrets when created. Turning this
|
42
|
+
off may be helpful if you need to combine shares created with a third-party
|
43
|
+
library.
|
44
|
+
|
38
45
|
Example w/ options:
|
39
46
|
|
40
47
|
$ tss combine -I shares.txt -O secret.txt
|
@@ -104,7 +111,7 @@ module TSS
|
|
104
111
|
end
|
105
112
|
|
106
113
|
begin
|
107
|
-
sec = TSS.combine(shares: shares)
|
114
|
+
sec = TSS.combine(shares: shares, padding: options[:padding])
|
108
115
|
|
109
116
|
say('')
|
110
117
|
say('RECOVERED SECRET METADATA')
|
data/lib/tss/cli_split.rb
CHANGED
@@ -9,7 +9,7 @@ module TSS
|
|
9
9
|
method_option :identifier, :aliases => '-i', :banner => 'identifier', :type => :string, :desc => 'A unique identifier string, 0-16 Bytes, [a-zA-Z0-9.-_]'
|
10
10
|
method_option :hash_alg, :aliases => '-h', :banner => 'hash_alg', :type => :string, :desc => 'A hash type for verification, NONE, SHA1, SHA256'
|
11
11
|
method_option :format, :aliases => '-f', :banner => 'format', :type => :string, :default => 'HUMAN', :desc => 'Share output format, BINARY or HUMAN'
|
12
|
-
method_option :
|
12
|
+
method_option :padding, :type => :boolean, :default => true, :desc => 'Whether to apply PKCS#7 padding to the secret'
|
13
13
|
method_option :input_file, :aliases => '-I', :banner => 'input_file', :type => :string, :desc => 'A filename to read the secret from'
|
14
14
|
method_option :output_file, :aliases => '-O', :banner => 'output_file', :type => :string, :desc => 'A filename to write the shares to'
|
15
15
|
|
@@ -20,8 +20,8 @@ module TSS
|
|
20
20
|
a SECRET provided. A secret to be split can be provided using one of three
|
21
21
|
different input methods; STDIN, a path to a file, or when prompted
|
22
22
|
for it interactively. In all cases the secret should be UTF-8 or
|
23
|
-
US-ASCII encoded text and be no larger than
|
24
|
-
|
23
|
+
US-ASCII encoded text and be no larger than #{TSS::MAX_UNPADDED_SECRET_SIZE}
|
24
|
+
bytes.
|
25
25
|
|
26
26
|
Optional Params:
|
27
27
|
|
@@ -41,8 +41,8 @@ module TSS
|
|
41
41
|
hash_alg :
|
42
42
|
One of NONE, SHA1, SHA256. The algorithm to use for a one-way hash of the secret that will be split along with the secret.
|
43
43
|
|
44
|
-
|
45
|
-
|
44
|
+
padding/no-padding :
|
45
|
+
Whether to apply PKCS#7 padding to secret. By default padding is applied. Turning this off may be helpful if you need to interoperate with a third party library.
|
46
46
|
|
47
47
|
format :
|
48
48
|
Whether to output the shares as a binary octet string (RTSS), or as more human friendly URL safe Base 64 encoded text with some metadata.
|
@@ -55,18 +55,19 @@ module TSS
|
|
55
55
|
|
56
56
|
Example w/ options:
|
57
57
|
|
58
|
-
$ tss split -t 3 -n 6 -i abc123 -h SHA256 -
|
58
|
+
$ tss split -t 3 -n 6 -i abc123 -h SHA256 -f HUMAN
|
59
59
|
|
60
60
|
Enter your secret:
|
61
61
|
|
62
62
|
secret > my secret
|
63
63
|
|
64
|
-
tss~v1~abc123~3~
|
65
|
-
tss~v1~abc123~3~
|
66
|
-
tss~v1~abc123~3~
|
67
|
-
tss~v1~abc123~3~
|
68
|
-
tss~v1~abc123~3~
|
69
|
-
tss~v1~abc123~3~
|
64
|
+
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEB113xpF37jGHm5QGhXKD8mgK2897MIQkSWri6ksNnAODn0efXznuBsSUnhlDIqQFU
|
65
|
+
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEC4tZegQrC3z6-02er3FZaWMadtlvxPb1EI_FNjG0dFrcdEDj4V7Cmcw___SesJHHP
|
66
|
+
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEDWPKPVjJaITosPGAMhvCgxCBB9uptl2h5UPngnw71V7Z9T-pnxiLKIfgUbRqyBrv-
|
67
|
+
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEExY3ti8ckAIQC02OKCrpEVVnUmyg3NXO9oG3PNw3PlgbbKdFRi9gBCNN_tjkhT3An
|
68
|
+
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEFf6k8XP-8_oCQPGQtUBy-yb8I25mrn6aA02ViJG4n1we7dgPOGkptWiSUJgQ_bboW
|
69
|
+
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEGSiKTeaiFrd_ICgIn0OoYC3sjnhyWgxLWqiyVOsBdwVBBt9zhg4FKmA5MXXNb4MqN
|
70
|
+
|
70
71
|
LONGDESC
|
71
72
|
|
72
73
|
# rubocop:disable CyclomaticComplexity
|
@@ -124,8 +125,8 @@ module TSS
|
|
124
125
|
args[:num_shares] = options[:num_shares] if options[:num_shares]
|
125
126
|
args[:identifier] = options[:identifier] if options[:identifier]
|
126
127
|
args[:hash_alg] = options[:hash_alg] if options[:hash_alg]
|
127
|
-
args[:pad_blocksize] = options[:pad_blocksize] if options[:pad_blocksize]
|
128
128
|
args[:format] = options[:format] if options[:format]
|
129
|
+
args[:padding] = options[:padding]
|
129
130
|
|
130
131
|
begin
|
131
132
|
log("Calling : TSS.split(#{args.inspect})")
|
data/lib/tss/combiner.rb
CHANGED
@@ -12,14 +12,15 @@ module TSS
|
|
12
12
|
|
13
13
|
C = Contracts
|
14
14
|
|
15
|
-
attr_reader :shares, :select_by
|
15
|
+
attr_reader :shares, :select_by, :padding
|
16
16
|
|
17
|
-
Contract ({ :shares => C::ArrayOfShares, :select_by => C::Maybe[C::SelectByArg] }) => C::Any
|
17
|
+
Contract ({ :shares => C::ArrayOfShares, :select_by => C::Maybe[C::SelectByArg], :padding => C::Maybe[C::Bool] }) => C::Any
|
18
18
|
def initialize(opts = {})
|
19
19
|
# clone the incoming shares so the object passed to this
|
20
20
|
# function doesn't get modified.
|
21
21
|
@shares = opts.fetch(:shares).clone
|
22
22
|
@select_by = opts.fetch(:select_by, 'FIRST')
|
23
|
+
@padding = opts.fetch(:padding, true)
|
23
24
|
end
|
24
25
|
|
25
26
|
# Warning, you probably don't want to use this directly. Instead
|
@@ -150,8 +151,6 @@ module TSS
|
|
150
151
|
secret << Util.lagrange_interpolation(u, v)
|
151
152
|
end
|
152
153
|
|
153
|
-
strip_left_pad(secret)
|
154
|
-
|
155
154
|
hash_alg = Hasher.key_from_code(hash_id)
|
156
155
|
|
157
156
|
# Run the hash digest checks if the shares were created with a digest
|
@@ -161,6 +160,10 @@ module TSS
|
|
161
160
|
orig_hash_bytes = secret.pop(Hasher.bytesize(hash_alg))
|
162
161
|
orig_hash_hex = Util.bytes_to_hex(orig_hash_bytes)
|
163
162
|
|
163
|
+
# Remove PKCS#7 padding from the secret now that the hash
|
164
|
+
# has been extracted from the data
|
165
|
+
secret = Util.unpad(secret) if padding
|
166
|
+
|
164
167
|
# RTSS : verify that the recombined secret computes the same hash
|
165
168
|
# digest now as when it was originally created.
|
166
169
|
new_hash_bytes = Hasher.byte_array(hash_alg, Util.bytes_to_utf8(secret))
|
@@ -169,6 +172,8 @@ module TSS
|
|
169
172
|
unless Util.secure_compare(orig_hash_hex, new_hash_hex)
|
170
173
|
raise TSS::InvalidSecretHashError, 'invalid shares, hash of secret does not equal embedded hash'
|
171
174
|
end
|
175
|
+
else
|
176
|
+
secret = Util.unpad(secret) if padding
|
172
177
|
end
|
173
178
|
|
174
179
|
if secret.present?
|
@@ -178,16 +183,6 @@ module TSS
|
|
178
183
|
end
|
179
184
|
end
|
180
185
|
|
181
|
-
# Strip off leading padding chars ("\u001F", decimal 31)
|
182
|
-
#
|
183
|
-
# @param secret the secret to be stripped
|
184
|
-
# @return returns the secret, stripped of the leading padding char
|
185
|
-
# @raise [ParamContractError] if secret appears invalid
|
186
|
-
Contract C::ArrayOf[C::Num] => C::Maybe[Array]
|
187
|
-
def strip_left_pad(secret)
|
188
|
-
secret.shift while secret.first == 31
|
189
|
-
end
|
190
|
-
|
191
186
|
# Do all of the shares match the pattern expected of human style shares?
|
192
187
|
#
|
193
188
|
# @param shares the shares to be evaluated
|
data/lib/tss/splitter.rb
CHANGED
@@ -9,9 +9,9 @@ module TSS
|
|
9
9
|
|
10
10
|
C = Contracts
|
11
11
|
|
12
|
-
attr_reader :secret, :threshold, :num_shares, :identifier, :hash_alg, :format, :
|
12
|
+
attr_reader :secret, :threshold, :num_shares, :identifier, :hash_alg, :format, :padding
|
13
13
|
|
14
|
-
Contract ({ :secret => C::SecretArg, :threshold => C::Maybe[C::ThresholdArg], :num_shares => C::Maybe[C::NumSharesArg], :identifier => C::Maybe[C::IdentifierArg], :hash_alg => C::Maybe[C::HashAlgArg], :format => C::Maybe[C::FormatArg], :
|
14
|
+
Contract ({ :secret => C::SecretArg, :threshold => C::Maybe[C::ThresholdArg], :num_shares => C::Maybe[C::NumSharesArg], :identifier => C::Maybe[C::IdentifierArg], :hash_alg => C::Maybe[C::HashAlgArg], :format => C::Maybe[C::FormatArg], :padding => C::Maybe[C::Bool] }) => C::Any
|
15
15
|
def initialize(opts = {})
|
16
16
|
@secret = opts.fetch(:secret)
|
17
17
|
@threshold = opts.fetch(:threshold, 3)
|
@@ -19,7 +19,7 @@ module TSS
|
|
19
19
|
@identifier = opts.fetch(:identifier, SecureRandom.hex(8))
|
20
20
|
@hash_alg = opts.fetch(:hash_alg, 'SHA256')
|
21
21
|
@format = opts.fetch(:format, 'HUMAN')
|
22
|
-
@
|
22
|
+
@padding = opts.fetch(:padding, true)
|
23
23
|
end
|
24
24
|
|
25
25
|
SHARE_HEADER_STRUCT = BinaryStruct.new([
|
@@ -61,15 +61,19 @@ module TSS
|
|
61
61
|
def split
|
62
62
|
num_shares_not_less_than_threshold!(threshold, num_shares)
|
63
63
|
|
64
|
-
#
|
65
|
-
|
66
|
-
# correct secret was returned. secret || hash(secret). You can also
|
67
|
-
# optionally pad the secret first.
|
68
|
-
padded_secret = Util.left_pad(pad_blocksize, secret)
|
69
|
-
hashed_secret = Hasher.byte_array(hash_alg, secret)
|
70
|
-
secret_bytes = Util.utf8_to_bytes(padded_secret) + hashed_secret
|
64
|
+
# Append needed PKCS#7 padding to the string
|
65
|
+
secret_padded = padding ? Util.pad(secret) : secret
|
71
66
|
|
72
|
-
|
67
|
+
# Calculate the cryptographic hash of the secret string
|
68
|
+
secret_hash = Hasher.byte_array(hash_alg, secret)
|
69
|
+
|
70
|
+
# RTSS : Combine the secret with a hash digest before splitting. When
|
71
|
+
# recombine the two will be separated again and the hash will be used
|
72
|
+
# to validate the correct secret was returned.
|
73
|
+
# secret || padding || hash(secret)
|
74
|
+
secret_pad_hash_bytes = Util.utf8_to_bytes(secret_padded) + secret_hash
|
75
|
+
|
76
|
+
secret_bytes_is_smaller_than_max_size!(secret_pad_hash_bytes)
|
73
77
|
|
74
78
|
# For each share, a distinct Share Index is generated. Each Share
|
75
79
|
# Index is an octet other than the all-zero octet. All of the Share
|
@@ -101,7 +105,7 @@ module TSS
|
|
101
105
|
# of M octets; A[0] is equal to the first octet of the secret, B[0] is
|
102
106
|
# equal to the second octet of the secret, and so on.
|
103
107
|
#
|
104
|
-
|
108
|
+
secret_pad_hash_bytes.each do |byte|
|
105
109
|
# Unpack random Byte String into Byte Array of 8 bit unsigned Integers
|
106
110
|
r = SecureRandom.random_bytes(threshold - 1).unpack('C*')
|
107
111
|
|
@@ -148,8 +152,8 @@ module TSS
|
|
148
152
|
# @raise [ParamContractError, TSS::ArgumentError] if invalid
|
149
153
|
Contract C::ArrayOf[C::Int] => C::Bool
|
150
154
|
def secret_bytes_is_smaller_than_max_size!(secret_bytes)
|
151
|
-
if secret_bytes.size
|
152
|
-
raise TSS::ArgumentError, 'invalid secret, combined padded
|
155
|
+
if secret_bytes.size > TSS::MAX_SECRET_SIZE
|
156
|
+
raise TSS::ArgumentError, 'invalid secret, combined padded and hashed secret is too large'
|
153
157
|
else
|
154
158
|
return true
|
155
159
|
end
|
data/lib/tss/tss.rb
CHANGED
@@ -16,6 +16,16 @@ module TSS
|
|
16
16
|
include Contracts::Core
|
17
17
|
C = Contracts
|
18
18
|
|
19
|
+
# Defined in TSS spec, two less than 2^16
|
20
|
+
MAX_SECRET_SIZE = 64_534
|
21
|
+
|
22
|
+
# Max size minus up to 16 bytes PKCS#7 padding
|
23
|
+
# and 32 bytes of cryptographic hash
|
24
|
+
MAX_UNPADDED_SECRET_SIZE = MAX_SECRET_SIZE - 48
|
25
|
+
|
26
|
+
# When applying PKCS#7 padding, what block size in bytes should be used
|
27
|
+
PADDING_BLOCK_SIZE_BYTES = 16
|
28
|
+
|
19
29
|
# An unexpected error has occurred.
|
20
30
|
class Error < StandardError; end
|
21
31
|
|
@@ -59,23 +69,11 @@ module TSS
|
|
59
69
|
# who are recombining the shares to verify if they have in fact recovered
|
60
70
|
# the correct secret.
|
61
71
|
# @option opts [String] :format ('BINARY') the format of the String share output, 'BINARY' or 'HUMAN'
|
62
|
-
# @option opts [
|
63
|
-
# to left pad the secret to. Defaults to not adding any padding (0). Padding
|
64
|
-
# is done with the "\u001F" character (decimal 31 in a Byte Array).
|
65
|
-
#
|
66
|
-
# Since TSS share data (minus the header) is essentially the same size as the
|
67
|
-
# original secret, padding smaller secrets may help mask the size of the
|
68
|
-
# contents from an attacker. Padding is not part of the RTSS spec so other
|
69
|
-
# TSS clients won't strip off the padding and may not validate correctly.
|
70
|
-
#
|
71
|
-
# If you need this interoperability you should probably pad the secret
|
72
|
-
# yourself prior to splitting it and leave the default zero-length pad in
|
73
|
-
# place. You would also need to manually remove the padding you added after
|
74
|
-
# the share is recombined, or instruct recipients to ignore it.
|
72
|
+
# @option opts [Boolean] :padding Whether to apply PKCS#7 padding to secret
|
75
73
|
#
|
76
74
|
# @return an Array of formatted String shares
|
77
75
|
# @raise [ParamContractError, TSS::ArgumentError] if the options Types or Values are invalid
|
78
|
-
Contract ({ :secret => C::SecretArg, :threshold => C::Maybe[C::ThresholdArg], :num_shares => C::Maybe[C::NumSharesArg], :identifier => C::Maybe[C::IdentifierArg], :hash_alg => C::Maybe[C::HashAlgArg], :format => C::Maybe[C::FormatArg], :
|
76
|
+
Contract ({ :secret => C::SecretArg, :threshold => C::Maybe[C::ThresholdArg], :num_shares => C::Maybe[C::NumSharesArg], :identifier => C::Maybe[C::IdentifierArg], :hash_alg => C::Maybe[C::HashAlgArg], :format => C::Maybe[C::FormatArg], :padding => C::Maybe[C::Bool] }) => C::ArrayOfShares
|
79
77
|
def self.split(opts)
|
80
78
|
TSS::Splitter.new(opts).split
|
81
79
|
end
|
@@ -86,6 +84,7 @@ module TSS
|
|
86
84
|
#
|
87
85
|
# @param [Hash] opts the options to create a message with.
|
88
86
|
# @option opts [Array<String>] :shares an Array of String shares to try to recombine into a secret
|
87
|
+
# @option opts [Boolean] :padding Whether PKCS#7 padding is expected in the secret and should be removed
|
89
88
|
# @option opts [String] :select_by ('FIRST') the method to use for selecting
|
90
89
|
# shares from the Array if more then threshold shares are provided. Can be
|
91
90
|
# upper case 'FIRST', 'SAMPLE', or 'COMBINATIONS'.
|
@@ -122,7 +121,7 @@ module TSS
|
|
122
121
|
# @raise [TSS::NoSecretError] if the secret cannot be re-created from the shares provided
|
123
122
|
# @raise [TSS::InvalidSecretHashError] if the embedded hash of the secret does not match the hash of the recreated secret
|
124
123
|
# @raise [ParamContractError, TSS::ArgumentError] if the options Types or Values are invalid
|
125
|
-
Contract ({ :shares => C::ArrayOfShares, :select_by => C::Maybe[C::SelectByArg] }) => ({ :hash => C::Maybe[String], :hash_alg => C::HashAlgArg, :identifier => C::IdentifierArg, :process_time => C::Num, :secret => C::SecretArg, :threshold => C::ThresholdArg})
|
124
|
+
Contract ({ :shares => C::ArrayOfShares, :padding => C::Maybe[C::Bool], :select_by => C::Maybe[C::SelectByArg] }) => ({ :hash => C::Maybe[String], :hash_alg => C::HashAlgArg, :identifier => C::IdentifierArg, :process_time => C::Num, :secret => C::SecretArg, :threshold => C::ThresholdArg })
|
126
125
|
def self.combine(opts)
|
127
126
|
TSS::Combiner.new(opts).combine
|
128
127
|
end
|
data/lib/tss/util.rb
CHANGED
@@ -271,18 +271,40 @@ module TSS
|
|
271
271
|
bytes_to_hex(utf8_to_bytes(str))
|
272
272
|
end
|
273
273
|
|
274
|
-
#
|
274
|
+
# Pad a String with PKCS#7 (RFC5652)
|
275
|
+
# See : https://tools.ietf.org/html/rfc5652#section-6.3
|
275
276
|
#
|
276
|
-
# @param
|
277
|
-
# @param
|
278
|
-
# @
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
277
|
+
# @param str the String or Array of bytes to pad
|
278
|
+
# @param k pad blocksize (0-255), default 16
|
279
|
+
# @return a PKCS#7 padded String or Array of bytes
|
280
|
+
Contract C::Or[Array, String], C::PadBlocksizeArg => C::Or[Array, String]
|
281
|
+
def self.pad(str, k = TSS::PADDING_BLOCK_SIZE_BYTES)
|
282
|
+
return str if k.zero?
|
283
|
+
str_bytes = str.is_a?(Array) ? str : TSS::Util.utf8_to_bytes(str)
|
284
|
+
l = str_bytes.length
|
285
|
+
val = k - (l % k)
|
286
|
+
pad_bytes = [val] * val
|
287
|
+
padded_str_bytes = str_bytes + pad_bytes
|
288
|
+
str.is_a?(Array) ? padded_str_bytes : TSS::Util.bytes_to_utf8(padded_str_bytes)
|
289
|
+
end
|
290
|
+
|
291
|
+
# Remove padding from a String previously padded with PKCS#7 (RFC5652)
|
292
|
+
#
|
293
|
+
# @param str the String to remove padding from
|
294
|
+
# @param k pad blocksize (0-255)
|
295
|
+
# @return an unpadded String or Array of bytes
|
296
|
+
Contract C::Or[Array, String], C::PadBlocksizeArg => C::Or[Array, String]
|
297
|
+
def self.unpad(str, k = TSS::PADDING_BLOCK_SIZE_BYTES)
|
298
|
+
return str if k.zero?
|
299
|
+
str_bytes = str.is_a?(Array) ? str : TSS::Util.utf8_to_bytes(str)
|
300
|
+
val = str_bytes.last
|
301
|
+
raise 'Input is not padded or padding is corrupt' if val > k
|
302
|
+
# Verify that the proper number of PKCS#7 padding bytes are present
|
303
|
+
# and match the last byte value in both value and number of bytes present.
|
304
|
+
raise 'Padding bytes are invalid' unless str_bytes.last(val).all? {|b| b == val}
|
305
|
+
l = str_bytes.length - val
|
306
|
+
unpadded_str_bytes = str_bytes.take(l)
|
307
|
+
str.is_a?(Array) ? unpadded_str_bytes : TSS::Util.bytes_to_utf8(unpadded_str_bytes)
|
286
308
|
end
|
287
309
|
|
288
310
|
# Constant time string comparison.
|
data/lib/tss/version.rb
CHANGED
data/tss.gemspec
CHANGED
@@ -48,8 +48,10 @@ Gem::Specification.new do |spec|
|
|
48
48
|
spec.executables << 'tss'
|
49
49
|
spec.require_paths = ['lib']
|
50
50
|
|
51
|
+
spec.metadata["yard.run"] = "yri" # use "yard" to build full HTML docs.
|
52
|
+
|
51
53
|
spec.add_dependency 'activesupport', '>= 4.0.0'
|
52
|
-
spec.add_dependency 'sysrandom', '>= 1.0.3', '~> 1.0.
|
54
|
+
spec.add_dependency 'sysrandom', '>= 1.0.3', '~> 1.0.4'
|
53
55
|
spec.add_dependency 'contracts', '~> 0.14'
|
54
56
|
spec.add_dependency 'binary_struct', '~> 2.1'
|
55
57
|
spec.add_dependency 'thor', '~> 0.19'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Glenn Rempe
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
vprF5QiDz8HshVP9DjJT2I1wyGyvxEdU3cTRo0upMP/VZLcgyBVFy90N2XYWWk2D
|
31
31
|
GIxGSw==
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date:
|
33
|
+
date: 2017-01-29 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: activesupport
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: 1.0.3
|
56
56
|
- - "~>"
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version: 1.0.
|
58
|
+
version: 1.0.4
|
59
59
|
type: :runtime
|
60
60
|
prerelease: false
|
61
61
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -65,7 +65,7 @@ dependencies:
|
|
65
65
|
version: 1.0.3
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.0.
|
68
|
+
version: 1.0.4
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: contracts
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -281,7 +281,8 @@ files:
|
|
281
281
|
homepage: https://github.com/grempe/tss-rb
|
282
282
|
licenses:
|
283
283
|
- MIT
|
284
|
-
metadata:
|
284
|
+
metadata:
|
285
|
+
yard.run: yri
|
285
286
|
post_install_message:
|
286
287
|
rdoc_options: []
|
287
288
|
require_paths:
|
@@ -298,7 +299,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
298
299
|
version: '0'
|
299
300
|
requirements: []
|
300
301
|
rubyforge_project:
|
301
|
-
rubygems_version: 2.
|
302
|
+
rubygems_version: 2.6.8
|
302
303
|
signing_key:
|
303
304
|
specification_version: 4
|
304
305
|
summary: A Ruby gem implementing Threshold Secret Sharing. This code can be used in
|
metadata.gz.sig
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
<��'
|