tss 0.1.1 → 0.2.0
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
- checksums.yaml.gz.sig +2 -4
- data/.coco.yml +7 -0
- data/.editorconfig +12 -0
- data/.hound.yml +10 -0
- data/.inch.yml +9 -0
- data/.rubocop.yml +129 -40
- data/.ruby-version +1 -1
- data/.travis.yml +4 -3
- data/CHANGELOG.md +22 -0
- data/README.md +218 -162
- data/RELEASE.md +105 -0
- data/Rakefile +9 -0
- data/bin/tss +4 -1
- data/lib/tss/cli_combine.rb +136 -0
- data/lib/tss/cli_common.rb +40 -0
- data/lib/tss/cli_split.rb +156 -0
- data/lib/tss/cli_version.rb +17 -0
- data/lib/tss/combiner.rb +156 -72
- data/lib/tss/hasher.rb +4 -2
- data/lib/tss/splitter.rb +71 -33
- data/lib/tss/tss.rb +4 -5
- data/lib/tss/util.rb +4 -12
- data/lib/tss/version.rb +1 -1
- data/tss.gemspec +7 -4
- data.tar.gz.sig +0 -0
- metadata +64 -14
- metadata.gz.sig +0 -0
- data/lib/tss/cli.rb +0 -107
- data/lib/tss/types.rb +0 -4
data/README.md
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
# TSS - Threshold Secret Sharing
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/tss)
|
4
|
+
[](https://gemnasium.com/github.com/grempe/tss-rb)
|
4
5
|
[](https://travis-ci.org/grempe/tss-rb)
|
5
6
|
[](https://coveralls.io/github/grempe/tss-rb?branch=master)
|
6
7
|
[](https://codeclimate.com/github/grempe/tss-rb)
|
8
|
+
[](http://inch-ci.org/github/grempe/tss-rb)
|
9
|
+
|
10
|
+
Ruby Docs : [http://www.rubydoc.info/gems/tss](http://www.rubydoc.info/gems/tss)
|
11
|
+
|
7
12
|
|
8
13
|
## WARNING : BETA CODE
|
9
14
|
|
@@ -46,54 +51,46 @@ advanced error correction schemes. These extras are not currently implemented.
|
|
46
51
|
|
47
52
|
## TL;DR
|
48
53
|
|
49
|
-
No time for docs? Here is how to get going in
|
50
|
-
|
51
|
-
to a binary octet string representation. The default is `3 out of 5` threshold
|
52
|
-
sharing.
|
53
|
-
|
54
|
-
### CLI (Human Shares)
|
55
|
-
|
56
|
-
```text
|
57
|
-
~/src$ gem install tss
|
58
|
-
Successfully installed tss-0.1.0
|
59
|
-
1 gem installed
|
60
|
-
~/src$ tss split
|
61
|
-
Enter your secret:
|
62
|
-
secret > my deep dark secret
|
63
|
-
tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQBDoW7GJ66g6nQHQZVM_iUxMVEO7NHlwDaEM5FYsVwhBSfio-WF-w2gqSKRjBp6YyqTQKR
|
64
|
-
tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQCxKBLxPsXuW4e7xE0zKiso49aEyuMKNIhjISe7ga865KDnBBpE1iZ6ESUkaWojKE3yNbc
|
65
|
-
tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQDp1zQuADISueqk2UK3yNdBDh7XGlyoD2R6X9y-BCoI7iwAE02A8aj8vKO9ticeJpQMvDi
|
66
|
-
tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQEgzj1RJXwKbu0pa5Z5qssmoX0cz22gVg8UCc6tasiqbDNi7bq_xKUczpYuc7utwDyPxV1
|
67
|
-
tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQF4MRuOG4v2jIA2dpn9SDdPTLVPH9ICbeMNdzWo702YZr-F-u174yuaYxC3rPaQzuVxTNL
|
68
|
-
~/src$ tss combine
|
69
|
-
Enter shares, one per line, blank line or dot (.) to finish:
|
70
|
-
share> tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQBDoW7GJ66g6nQHQZVM_iUxMVEO7NHlwDaEM5FYsVwhBSfio-WF-w2gqSKRjBp6YyqTQKR
|
71
|
-
share> tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQCxKBLxPsXuW4e7xE0zKiso49aEyuMKNIhjISe7ga865KDnBBpE1iZ6ESUkaWojKE3yNbc
|
72
|
-
share> tss~v1~4a993275528d5ec7~3~NGE5OTMyNzU1MjhkNWVjNwIDADQDp1zQuADISueqk2UK3yNdBDh7XGlyoD2R6X9y-BCoI7iwAE02A8aj8vKO9ticeJpQMvDi
|
73
|
-
share> .
|
54
|
+
No time for docs? Here is how to get going in a minute, using the
|
55
|
+
command line or Ruby, with the default `3 out of 5` secret sharing.
|
74
56
|
|
75
|
-
|
57
|
+
### Command Line Interface (CLI)
|
76
58
|
|
77
|
-
|
59
|
+
```sh
|
60
|
+
$ echo 'secret unicode characters ½ ♥ 💩' | bundle exec bin/tss split -O /tmp/shares.txt
|
61
|
+
$ bundle exec bin/tss combine -I /tmp/shares.txt
|
62
|
+
|
63
|
+
RECOVERED SECRET METADATA
|
64
|
+
*************************
|
65
|
+
hash : 6d1bc4242998bc170d35d374ebdf39295b271db900de25d249563a4622f113e0
|
66
|
+
hash_alg : SHA256
|
67
|
+
identifier : 6b02cfcfc24a2b50
|
68
|
+
process_time : 0.55ms
|
78
69
|
threshold : 3
|
79
|
-
processing time (ms) : 0.64
|
80
70
|
secret :
|
81
|
-
|
82
|
-
my deep dark secret
|
83
|
-
**************************************************
|
71
|
+
secret unicode characters ½ ♥ 💩
|
84
72
|
```
|
85
73
|
|
86
|
-
### Ruby
|
74
|
+
### Ruby
|
87
75
|
|
88
|
-
```
|
89
|
-
|
90
|
-
|
91
|
-
=>
|
92
|
-
|
93
|
-
=> ["
|
94
|
-
|
95
|
-
|
96
|
-
|
76
|
+
```ruby
|
77
|
+
$ bundle exec bin/console
|
78
|
+
[1] pry(main)> require 'tss'
|
79
|
+
=> false
|
80
|
+
[2] pry(main)> shares = TSS.split(secret: 'my deep dark secret')
|
81
|
+
=> ["tss~v1~72e84cd688bf24fc~3~NzJlODRjZDY4OGJmMjRmYwIDADQBVLUhLlOvz_VWjEge2gH7PtqTsnSCpbfmMSFX98XUp0BmQAeeOTGDL0GVeGATWjbBZvOm",
|
82
|
+
"tss~v1~72e84cd688bf24fc~3~NzJlODRjZDY4OGJmMjRmYwIDADQCmlZ_CZSBPk6m2-0WMEmcdzCsB8lH1oDalELd9VhlFPqby08kjm9tZBtONqXucgcnuFlQ",
|
83
|
+
"tss~v1~72e84cd688bf24fc~3~NzJlODRjZDY4OGJmMjRmYwIDADQDo5p-Q6JLgZuUNtdjyjsCKphawUx8bNhW0FYjdk7V_4RRnZpzsCzi00hLb4igNYYraY5Z",
|
84
|
+
"tss~v1~72e84cd688bf24fc~3~NzJlODRjZDY4OGJmMjRmYwIDADQEuqHxd94BQK1V-db70VLZxdIULyVIOGDrE7w7K3SVnk0UaEMf9xJFaYpKrXical7nR9PT",
|
85
|
+
"tss~v1~72e84cd688bf24fc~3~NzJlODRjZDY4OGJmMjRmYwIDADQFg23wPejL_3hnFOyOKyBHmHri6aBzgjhnV6jFqGIldTPePpZIyVHK3tlP9FXSLd_rlgTa"]
|
86
|
+
[3] pry(main)> secret = TSS.combine(shares: shares)
|
87
|
+
=> {:hash=>"f1b91fef6a7535a974d3644c3eac16d2c907720c981290214d5d1db7cdb724af",
|
88
|
+
:hash_alg=>"SHA256",
|
89
|
+
:identifier=>"72e84cd688bf24fc",
|
90
|
+
:process_time=>0.58,
|
91
|
+
:secret=>"my deep dark secret",
|
92
|
+
:threshold=>3}
|
93
|
+
[4] pry(main)> puts secret[:secret]
|
97
94
|
my deep dark secret
|
98
95
|
=> nil
|
99
96
|
```
|
@@ -143,6 +140,14 @@ or [TweetNaCl.js](https://github.com/dchest/tweetnacl-js).
|
|
143
140
|
* Put careful thought into how you want to distribute shares. It often makes
|
144
141
|
sense to give individuals more than one share.
|
145
142
|
|
143
|
+
## Documentation
|
144
|
+
|
145
|
+
There is pretty extensive inline documentation. You can view the latest
|
146
|
+
auto-generated docs at [http://www.rubydoc.info/gems/tss](http://www.rubydoc.info/gems/tss)
|
147
|
+
|
148
|
+
You can check my documentation quality score at
|
149
|
+
[http://inch-ci.org/github/grempe/tss-rb](http://inch-ci.org/github/grempe/tss-rb?branch=master)
|
150
|
+
|
146
151
|
## Supported Platforms
|
147
152
|
|
148
153
|
TSS is continuously integration tested on the following Ruby VMs:
|
@@ -190,7 +195,7 @@ if any signed gem does not match its signature.
|
|
190
195
|
|
191
196
|
```
|
192
197
|
# All dependent gems must be signed and verified.
|
193
|
-
gem install tss -P
|
198
|
+
gem install tss -P HighSecurity
|
194
199
|
```
|
195
200
|
|
196
201
|
```
|
@@ -219,108 +224,149 @@ You can also clone the repository and verify the signatures locally using your
|
|
219
224
|
own GnuPG installation. You can find my certificates and read about how to conduct
|
220
225
|
this verification at [https://www.rempe.us/keys/](https://www.rempe.us/keys/).
|
221
226
|
|
222
|
-
## Command Line Interface
|
227
|
+
## Command Line Interface (CLI)
|
223
228
|
|
224
229
|
When you install the gem a simple `tss` command-line interface (CLI)
|
225
|
-
is also installed and should be available on your PATH
|
230
|
+
is also installed and should be available on your `$PATH`.
|
226
231
|
|
227
|
-
The CLI is a
|
228
|
-
see the options available with `tss help`, `tss help split`,
|
232
|
+
The CLI is a user interface for splitting and combining secrets. You can
|
233
|
+
see the full set of options available with `tss help`, `tss help split`,
|
234
|
+
or `tss help combine`.
|
229
235
|
|
230
236
|
### CLI Secret Splitting
|
231
237
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
Options:
|
238
|
-
-t, [--threshold=threshold] # # of shares, of total, required to reconstruct a secret
|
239
|
-
-n, [--num-shares=num_shares] # # of shares total that will be generated
|
240
|
-
-i, [--identifier=identifier] # A unique identifier string, 0-16 Bytes, [a-zA-Z0-9.-_]
|
241
|
-
-h, [--hash-alg=hash_alg] # A hash type for verification, NONE, SHA1, SHA256
|
242
|
-
-f, [--format=format] # Share output format, binary or human
|
243
|
-
# Default: human
|
244
|
-
-p, [--pad-blocksize=pad_blocksize] # Block size # secrets will be left-padded to, 0-255
|
245
|
-
|
246
|
-
Description:
|
247
|
-
`tss split` will generate a set of Threshold Secret Sharing shares from the SECRET provided. To protect your secret from being saved in
|
248
|
-
your shell history you will be prompted for the single-line secret.
|
238
|
+
A secret to be split can be provided using one of three
|
239
|
+
different input methods; `STDIN`, a path to a file, or when prompted
|
240
|
+
interactively. In all cases the secret should be `UTF-8` or
|
241
|
+
`US-ASCII` encoded text and be no larger than 65,535 Bytes
|
242
|
+
(including header and hash verification bytes).
|
249
243
|
|
250
|
-
|
244
|
+
Each method for entering a secret may have pros and cons from a security
|
245
|
+
perspective. You need to understand what threat model you want to protect
|
246
|
+
against in order to choose wisely. Here are a few examples for how to
|
247
|
+
split a secret.
|
251
248
|
|
252
|
-
|
249
|
+
**Example : `STDIN`**
|
253
250
|
|
254
|
-
|
251
|
+
Can read the secret from `STDIN` and write the split shares to a file. Be
|
252
|
+
cautioned that this method may leave command history which may contain your
|
253
|
+
secret.
|
255
254
|
|
256
|
-
|
257
|
-
|
255
|
+
```text
|
256
|
+
echo 'a secret' | bundle exec bin/tss split -O /tmp/shares.txt
|
257
|
+
```
|
258
258
|
|
259
|
-
|
259
|
+
**Example : `--input-file`**
|
260
260
|
|
261
|
-
|
262
|
-
|
261
|
+
Can read the secret from a file and write the split shares to `STDOUT`. Be
|
262
|
+
cautioned that storing the secret on a filesystem may expose you to certain
|
263
|
+
attacks since it can be hard to fully erase files once written.
|
263
264
|
|
264
|
-
|
265
|
-
|
265
|
+
```text
|
266
|
+
$ bundle exec bin/tss split -I /tmp/secret.txt
|
267
|
+
tss~v1~3f784d9d04dff796~3~M2Y3ODRkOWQwNGRmZjc5NgIDACsBvAVAo1dH3QrsYl0S30j2VVTu6dZLRe9EEk6zLtPTwZNYk-t1e4SAA41D
|
268
|
+
tss~v1~3f784d9d04dff796~3~M2Y3ODRkOWQwNGRmZjc5NgIDACsCMfy6YlI-CQrd-l93Xtw8YqOWSP5ToolKTaZyO2fPYzceaaVmB30ycdVr
|
269
|
+
tss~v1~3f784d9d04dff796~3~M2Y3ODRkOWQwNGRmZjc5NgIDACsD4IDasmAapmVFkuYPMvuavCtXiJgPZsaBHglGm4FU_U2rGZzfapRk-ZNN
|
270
|
+
tss~v1~3f784d9d04dff796~3~M2Y3ODRkOWQwNGRmZjc5NgIDACsEbId8z1yNfEkDcezJpstkYenGLhJCMRglx2c0arPDS-YuXyiiNQQ-jYlq
|
271
|
+
tss~v1~3f784d9d04dff796~3~M2Y3ODRkOWQwNGRmZjc5NgIDACsFvfscH26p0yabGVWxyuzCv2EH7nQe9VfulMgAylVY1ZybLxEbWO1oBc9M
|
272
|
+
```
|
266
273
|
|
267
|
-
|
274
|
+
**Example : `interactive`**
|
268
275
|
|
269
|
-
|
276
|
+
Can read the secret interactively from a terminal and write the split shares
|
277
|
+
to `STDOUT`. This method is more secure since the secret will not be stored
|
278
|
+
in the command shell history or in a file on a filesystem that is hard to
|
279
|
+
erase securely. It does not protect you from simple keylogger attacks though.
|
270
280
|
|
271
|
-
|
281
|
+
```text
|
282
|
+
$ bundle exec bin/tss split
|
283
|
+
Enter your secret, enter a dot (.) on a line by itself to finish :
|
284
|
+
secret > the vault password is:
|
285
|
+
secret > V0ulT!
|
286
|
+
secret > .
|
287
|
+
tss~v1~546604c0b5e9138b~3~NTQ2NjA0YzBiNWU5MTM4YgIDAD8BK-9qlyxRFFQypFLwzM_tLWOv-NRziwnc6blqFP8eh8wLro4qiQwBKfI0KuuvM0u1C6th1vxsyW8vyolXQ-4=
|
288
|
+
tss~v1~546604c0b5e9138b~3~NTQ2NjA0YzBiNWU5MTM4YgIDAD8CEjeK01kAwE1wb7-wvLLlHoe6FGzhl7Hg9TCz_Npw7u0b31OpijFIKdxELfbnhvius7vGqn6KqQKqq69s4Co=
|
289
|
+
tss~v1~546604c0b5e9138b~3~NTQ2NjA0YzBiNWU5MTM4YgIDAD8DTbCFZAMwoXU2650hAw5_XJZxzNHhJrJqLPy1vARk8APzWkgP7K79AtbVn1C49HpBSP2OL-BLumaZZWbU7YI=
|
290
|
+
tss~v1~546604c0b5e9138b~3~NTQ2NjA0YzBiNWU5MTM4YgIDAD8E9eVJ83Knw3Fq1e9VaFSKdPKUAugyBqXzCsqov6etQIfEYe8Vt-ZVu3Ax7L1MWBNt-AQLN7YtczAG4QZ_7wI=
|
291
|
+
tss~v1~546604c0b5e9138b~3~NTQ2NjA0YzBiNWU5MTM4YgIDAD8FqmJGRCiXokksUc3E1-gQNuNf2lUyt6Z50wau_3m5Xmks5PSz0XngkHqgXhsTKpGCA0JDsijsYFQ1L8_H4qo=
|
292
|
+
```
|
272
293
|
|
273
|
-
|
294
|
+
### CLI Share Combining
|
274
295
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEFfYo7EcQUOpMH09Ggz_403rvy1r9_ckI_Pd_hm1tRxX8FfzEWyXMAoFCKTOfIKgMo
|
280
|
-
tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEGDSmh74Ng8WTziMGZXAm5XcpFLqDl2oP4MH24XhYf33IIg1WsPIyMAznI0DJUeLpN
|
296
|
+
You can use the CLI to enter shares in order to recover a secret. Of course
|
297
|
+
you will need at least the number of shares necessary as determined
|
298
|
+
by the threshold when your shares were created. The `threshold` is visible
|
299
|
+
as the third field in every `human` formatted share.
|
281
300
|
|
282
|
-
|
301
|
+
As with splitting a secret, there are also three methods of getting the shares
|
302
|
+
into the CLI. `STDIN`, a path to a file containing shares, or interactively.
|
283
303
|
|
284
|
-
|
304
|
+
Here are some simple examples of using each:
|
285
305
|
|
286
|
-
|
287
|
-
on the command line.
|
306
|
+
**Example : `STDIN`**
|
288
307
|
|
308
|
+
```text
|
309
|
+
$ echo 'a secret' | bundle exec bin/tss split | bundle exec bin/tss combine
|
310
|
+
|
311
|
+
RECOVERED SECRET METADATA
|
312
|
+
*************************
|
313
|
+
hash : d4ea4551e9ff2cf56303875b1901fb8608a6164260c3b20c0976c7b606a4efc0
|
314
|
+
hash_alg : SHA256
|
315
|
+
identifier : fff58c38b14734f3
|
316
|
+
process_time : 0.34ms
|
317
|
+
threshold : 3
|
318
|
+
secret :
|
319
|
+
a secret
|
289
320
|
```
|
290
|
-
$ tss split -i abc
|
291
|
-
Enter your secret:
|
292
|
-
secret > abc
|
293
|
-
tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQB4zjuAvBL1P2AJciAHdicf6I2qxMkLGo2Hhr4dhI_v1CSKrE=
|
294
|
-
tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQCNAFhHSQd8nDgihYUrdM_IsMJqYZicLuk8jBS06kUJLZTU2g=
|
295
|
-
tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQDtlvspaxAmQJhYDTV8Ut9AM8dISVFPXIE-1A2EavU-hTBbHQ=
|
296
|
-
tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQE-NVr8ofyfwYVW9_2yauIT7t4Hmt9WeFNN_ADt7vpThYNeeU=
|
297
|
-
tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQFeo_mSg-vFHSUsf03lTPKbbdslshaFCjtPpBndbkpkLSfRvk=
|
298
|
-
```
|
299
|
-
|
300
|
-
### CLI Share Combining
|
301
321
|
|
302
|
-
**Example
|
322
|
+
**Example : `--input-file`**
|
303
323
|
|
304
|
-
|
305
|
-
|
324
|
+
```text
|
325
|
+
$ echo 'a secret' | bundle exec bin/tss split -O /tmp/shares.txt
|
326
|
+
$ bundle exec bin/tss combine -I /tmp/shares.txt
|
327
|
+
|
328
|
+
RECOVERED SECRET METADATA
|
329
|
+
*************************
|
330
|
+
hash : d4ea4551e9ff2cf56303875b1901fb8608a6164260c3b20c0976c7b606a4efc0
|
331
|
+
hash_alg : SHA256
|
332
|
+
identifier : ae2983e30e0471fe
|
333
|
+
process_time : 0.47ms
|
334
|
+
threshold : 3
|
335
|
+
secret :
|
336
|
+
a secret
|
337
|
+
```
|
306
338
|
|
307
|
-
|
308
|
-
tss combine
|
309
|
-
Enter shares, one per line, blank line or dot (.) to finish:
|
310
|
-
share> tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQB4zjuAvBL1P2AJciAHdicf6I2qxMkLGo2Hhr4dhI_v1CSKrE=
|
311
|
-
share> tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQCNAFhHSQd8nDgihYUrdM_IsMJqYZicLuk8jBS06kUJLZTU2g=
|
312
|
-
share> tss~v1~abc~3~YWJjAAAAAAAAAAAAAAAAAAIDACQDtlvspaxAmQJhYDTV8Ut9AM8dISVFPXIE-1A2EavU-hTBbHQ=
|
313
|
-
share>
|
339
|
+
**Example : `interactive`**
|
314
340
|
|
315
|
-
|
341
|
+
```text
|
342
|
+
$ cat /tmp/shares.txt
|
343
|
+
# THRESHOLD SECRET SHARING SHARES
|
344
|
+
# 2016-04-19T23:57:17Z
|
345
|
+
# https://github.com/grempe/tss-rb
|
346
|
+
|
347
|
+
|
348
|
+
tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoBRjAH7wA0ncxJr3GliBqKxedf3bGaQH6AscuLqxtrKxxtxuC7A7a5Sqk=
|
349
|
+
tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoClWVu75w-XHhoUgkbV5XaJ11stZCB5Z8HTArpv4QsIYDBpNO9DHQTbQ4=
|
350
|
+
tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoDsnUaZf94pMArKZL7jmavzk9Qa6ZAvOB8e8nEAt0nyS6ga0XBucQOyGc=
|
351
|
+
tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoETCWwSGLHcutzGCLb1yOkH7i6MF7j2b0wr0ZsUh6LuBmx6FkN2MbTkTc=
|
352
|
+
tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoFazXEwgGBilMwY7k7DtDR9qqG7mgigMJLmIVB70eAULfQJ89xbXbONF4=
|
353
|
+
|
354
|
+
$ bundle exec bin/tss combine
|
355
|
+
Enter shares, one per line, and a dot (.) on a line by itself to finish :
|
356
|
+
share> tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoBRjAH7wA0ncxJr3GliBqKxedf3bGaQH6AscuLqxtrKxxtxuC7A7a5Sqk=
|
357
|
+
share> tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoClWVu75w-XHhoUgkbV5XaJ11stZCB5Z8HTArpv4QsIYDBpNO9DHQTbQ4=
|
358
|
+
share> tss~v1~ae2983e30e0471fe~3~YWUyOTgzZTMwZTA0NzFmZQIDACoDsnUaZf94pMArKZL7jmavzk9Qa6ZAvOB8e8nEAt0nyS6ga0XBucQOyGc=
|
359
|
+
share> .
|
316
360
|
|
317
|
-
|
361
|
+
RECOVERED SECRET METADATA
|
362
|
+
*************************
|
363
|
+
hash : d4ea4551e9ff2cf56303875b1901fb8608a6164260c3b20c0976c7b606a4efc0
|
364
|
+
hash_alg : SHA256
|
365
|
+
identifier : ae2983e30e0471fe
|
366
|
+
process_time : 0.7ms
|
318
367
|
threshold : 3
|
319
|
-
processing time (ms) : 0.48
|
320
368
|
secret :
|
321
|
-
|
322
|
-
abc
|
323
|
-
**************************************************
|
369
|
+
a secret
|
324
370
|
```
|
325
371
|
|
326
372
|
## Ruby : Splitting a Secret
|
@@ -352,10 +398,9 @@ of Bytes. e.g. `'foo'.bytes.to_a`
|
|
352
398
|
The `num_shares` and `threshold` values are Integers representing the total
|
353
399
|
number of shares desired, and how many of those shares are required to
|
354
400
|
re-create a `secret`. Both arguments must be Integers with a value
|
355
|
-
between `1-255` inclusive.
|
356
|
-
|
357
|
-
|
358
|
-
`num_shares = 5` by default.
|
401
|
+
between `1-255` inclusive. The `num_shares` value must be
|
402
|
+
greater-than-or-equal-to the `threshold` value. If you don't pass in
|
403
|
+
these options they will be set to `threshold = 3` and `num_shares = 5` by default.
|
359
404
|
|
360
405
|
The `identifier` is a `0-16` Byte String that will be embedded in
|
361
406
|
each output share and should uniquely identify a secret. All shares output
|
@@ -375,15 +420,14 @@ and then combined with it prior to secret splitting. This means that the hash
|
|
375
420
|
is protected the same way as the secret. The algorithm used is
|
376
421
|
`secret || hash(secret)`. You can use one of `NONE`, `SHA1`, or `SHA256`.
|
377
422
|
|
378
|
-
The `format` arg takes a String Enum with either `'
|
379
|
-
This instructs the output of a split to either provide an
|
380
|
-
strings (standard RTSS format for interoperability), or
|
381
|
-
URL Safe Base 64 encoded version of that same binary output.
|
382
|
-
can be easily shared in a tweet, email, or even a URL. The
|
383
|
-
prefixed with `tss
|
384
|
-
compare shares and see if they have matching identifiers and
|
385
|
-
enough shares to reach the threshold.
|
386
|
-
or used by the `tss` combiner code at all. It is only for user convenience.
|
423
|
+
The `format` arg takes a String Enum with either `'human'` (default) or
|
424
|
+
`'binary'` values. This instructs the output of a split to either provide an
|
425
|
+
array of binary octet strings (a standard RTSS format for interoperability), or
|
426
|
+
a human friendly URL Safe Base 64 encoded version of that same binary output.
|
427
|
+
The `human` format can be easily shared in a tweet, email, or even a URL. The
|
428
|
+
`human` format is prefixed with `tss~VERSION~IDENTIFIER~THRESHOLD~` to make it
|
429
|
+
easier to visually compare shares and see if they have matching identifiers and
|
430
|
+
if you have enough shares to reach the threshold.
|
387
431
|
|
388
432
|
The `pad_blocksize` arg takes an Integer between 0..255 inclusive. Your secret
|
389
433
|
**MUST NOT** *begin* with this character (which was chosen to make less likely).
|
@@ -432,27 +476,25 @@ threshold = 3
|
|
432
476
|
num_shares = 5
|
433
477
|
identifier = SecureRandom.hex(8)
|
434
478
|
hash_alg = 'SHA256'
|
479
|
+
format = 'human'
|
435
480
|
|
436
|
-
s = TSS.split(secret: secret, threshold: threshold, num_shares: num_shares, identifier: identifier, hash_alg: 'SHA256', pad_blocksize: 16)
|
481
|
+
s = TSS.split(secret: secret, threshold: threshold, num_shares: num_shares, identifier: identifier, hash_alg: 'SHA256', pad_blocksize: 16, format: format)
|
437
482
|
|
438
|
-
=> ["
|
439
|
-
"
|
440
|
-
"
|
441
|
-
"
|
442
|
-
"
|
483
|
+
=> ["tss~v1~9fdfe2516240737e~3~OWZkZmUyNTE2MjQwNzM3ZQIDADEBe1METAFZDbpq7yHIFRvxr1PjBOLRnHzDyzDGrnDvYp90jMKPLWwo3eiWiuafRaYJ",
|
484
|
+
"tss~v1~9fdfe2516240737e~3~OWZkZmUyNTE2MjQwNzM3ZQIDADECOeQaLXYx99N2SDKutj0_smSonMdMMzeJc_CWPRT8nppHkdsUc7hW6cSw_RDcaKMF",
|
485
|
+
"tss~v1~9fdfe2516240737e~3~OWZkZmUyNTE2MjQwNzM3ZQIDADEDXagBfmgOlQY8xXIUg0SvZ-yYgORZzeWiyjRBmsDMLwG7bLmmswSAOllamqGZ-_fb",
|
486
|
+
"tss~v1~9fdfe2516240737e~3~OWZkZmUyNTE2MjQwNzM3ZQIDADEExmXZHYJsLzipmqYryl5SDlhJzdZxLh_2y5bM_tOOmdm9rpws3izJqHrzmCHQi5mn",
|
487
|
+
"tss~v1~9fdfe2516240737e~3~OWZkZmUyNTE2MjQwNzM3ZQIDADEFoinCTpxTTe3jF-aR_yfC29B50fVk0M3dclIbWQe-KEJBU_6eHpAfe-cZ_5CVGM15"]
|
443
488
|
|
444
489
|
secret = TSS.combine(shares: s)
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
:combinations=>nil,
|
454
|
-
:threshold=>3}
|
455
|
-
```
|
490
|
+
|
491
|
+
=> {:hash=>"dbd318c1c462aee872f41109a4dfd3048871a03dedd0fe0e757ced57dad6f2d7",
|
492
|
+
:hash_alg=>"SHA256",
|
493
|
+
:identifier=>"9fdfe2516240737e",
|
494
|
+
:process_time=>0.77,
|
495
|
+
:secret=>"foo bar baz",
|
496
|
+
:threshold=>3}
|
497
|
+
```
|
456
498
|
|
457
499
|
## Ruby : Combining Shares to Recreate a Secret
|
458
500
|
|
@@ -506,28 +548,43 @@ in many times the life of the Universe. This option can only be used if the
|
|
506
548
|
possible combinations for the number of shares and the threshold needed to
|
507
549
|
reconstruct a secret result in a number of combinations that is small enough
|
508
550
|
to have a chance at being processed. If the number of combinations will be too
|
509
|
-
large
|
551
|
+
large an Exception will be raised before processing has even started. The default
|
552
|
+
maximum number of combinations that will be tried is 1,000,000.
|
553
|
+
|
554
|
+
**Fun Fact**
|
555
|
+
|
556
|
+
If 255 total shares are available, and the threshold value is 128, it would result in
|
557
|
+
`2884329411724603169044874178931143443870105850987581016304218283632259375395`
|
558
|
+
possible combinations of 128 shares that could be tried. That is *almost* as
|
559
|
+
many combinations (`2.88 * 10^75`) as there are Atoms in the Universe (`10^80`).
|
510
560
|
|
511
561
|
If the combine operation does not result in a secret being successfully
|
512
562
|
extracted, then a `TSS::Error` exception will be raised.
|
513
563
|
|
564
|
+
A great short read on this is
|
565
|
+
[On the (Small) Number of Atoms in the Universe](http://norvig.com/atoms.html)
|
566
|
+
|
514
567
|
### Exception Handling
|
515
568
|
|
516
569
|
Initial validation of options is done when the `TSS.split` or `TSS.combine`
|
517
570
|
methods are called. If the arguments passed are of the wrong Type or value
|
518
|
-
a `
|
571
|
+
a `TSS::ArgumentError` Exception will be raised.
|
519
572
|
|
520
|
-
The splitting and combining operations may also raise
|
521
|
-
|
573
|
+
The splitting and combining operations may also raise the following
|
574
|
+
exception types:
|
522
575
|
|
523
|
-
|
524
|
-
`
|
576
|
+
`TSS::NoSecretError`, `TSS::InvalidSecretHashError`,
|
577
|
+
`TSS::ArgumentError`, `TSS::Error`
|
578
|
+
|
579
|
+
All Exceptions should include hints as to what went wrong in the
|
580
|
+
`#message` attribute.
|
525
581
|
|
526
582
|
## Share Data Formats
|
527
583
|
|
528
584
|
### RTSS Binary
|
529
585
|
|
530
|
-
TSS provides shares in a binary data format with the following fields
|
586
|
+
TSS provides shares in a binary data format with the following fields, and
|
587
|
+
by default this binary data is wrapped in a `'human'` text format:
|
531
588
|
|
532
589
|
`Identifier`. This field contains 16 octets. It identifies the secret
|
533
590
|
with which a share is associated. All of the shares associated
|
@@ -574,20 +631,21 @@ octets. It contains the actual share data.
|
|
574
631
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
575
632
|
```
|
576
633
|
|
577
|
-
This
|
634
|
+
This data format has been tested for binary compatibility with the
|
578
635
|
[seb-m/tss](https://github.com/seb-m/tss) Python implementation of TSS. There
|
579
636
|
are test cases to ensure it remains compatible.
|
580
637
|
|
581
638
|
### RTSS Human Friendly Wrapper
|
582
639
|
|
583
|
-
To make `tss`
|
584
|
-
|
640
|
+
To make `tss` friendlier to use when sending shares to others, an enhanced
|
641
|
+
text wrapper around the RTSS binary data format is provided.
|
585
642
|
|
586
|
-
Shares formatted this way can easily be shared via any communication channel.
|
643
|
+
Shares formatted this way can easily be shared via most any communication channel.
|
587
644
|
|
588
645
|
The `human` data format is simply the same RTSS binary data, URL Safe Base64
|
589
|
-
encoded, and prefixed with a String thet contains
|
590
|
-
|
646
|
+
encoded, and prefixed with a String thet contains tilde `~` separated elements.
|
647
|
+
The `~` is used as it is compatible with the URL Safe data and the allowed
|
648
|
+
characters in the rest of the human format string.
|
591
649
|
|
592
650
|
```text
|
593
651
|
tss~VERSION~IDENTIFIER~THRESHOLD~BASE64_ENCODED_BINARY_SHARE
|
@@ -624,15 +682,13 @@ After checking out the repo, run `bin/setup` to install dependencies. Then,
|
|
624
682
|
run `rake test` to run the tests. You can also run `bin/console` for an
|
625
683
|
interactive prompt that will allow you to experiment.
|
626
684
|
|
627
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
628
|
-
release a new version, update the version number in `version.rb`, and then
|
629
|
-
run `bundle exec rake release`, which will create a git tag for the version,
|
630
|
-
push git commits and tags, and push the `.gem` file
|
631
|
-
to [rubygems.org](https://rubygems.org).
|
685
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
632
686
|
|
633
687
|
You can run the Command Line Interface (CLI) in development
|
634
688
|
with `bundle exec bin/tss`.
|
635
689
|
|
690
|
+
The formal release process can be found in [RELEASE.md](https://github.com/grempe/tss-rb/blob/master/RELEASE.md)
|
691
|
+
|
636
692
|
### Contributing
|
637
693
|
|
638
694
|
Bug reports and pull requests are welcome on GitHub
|
data/RELEASE.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# Gem Release Process
|
2
|
+
|
3
|
+
Don't use the `bundle exec rake release` task. It is more convenient,
|
4
|
+
but it skips the process of signing the version release task.
|
5
|
+
|
6
|
+
## Run Tests
|
7
|
+
|
8
|
+
```sh
|
9
|
+
$ rake test_all
|
10
|
+
```
|
11
|
+
|
12
|
+
## Git Push
|
13
|
+
|
14
|
+
```sh
|
15
|
+
$ git push
|
16
|
+
```
|
17
|
+
|
18
|
+
Check for regressions in automated tests:
|
19
|
+
|
20
|
+
* [https://travis-ci.org/grempe/tss-rb](https://travis-ci.org/grempe/tss-rb)
|
21
|
+
* [https://coveralls.io/github/grempe/tss-rb?branch=master](https://coveralls.io/github/grempe/tss-rb?branch=master)
|
22
|
+
* [https://codeclimate.com/github/grempe/tss-rb](https://codeclimate.com/github/grempe/tss-rb)
|
23
|
+
* [http://inch-ci.org/github/grempe/tss-rb](http://inch-ci.org/github/grempe/tss-rb)
|
24
|
+
|
25
|
+
## Bump Version Number and edit CHANGELOG.md
|
26
|
+
|
27
|
+
```sh
|
28
|
+
$ vi lib/tss/version.rb
|
29
|
+
$ git add lib/tss/version.rb
|
30
|
+
$ vi CHANGELOG.md
|
31
|
+
$ git add CHANGELOG.md
|
32
|
+
```
|
33
|
+
|
34
|
+
## Local Build and Install w/ Signed Gem
|
35
|
+
|
36
|
+
The `build` step should ask for PEM passphrase to sign gem. If it does
|
37
|
+
not ask it means that the signing cert is not present.
|
38
|
+
|
39
|
+
Build:
|
40
|
+
|
41
|
+
```sh
|
42
|
+
$ rake build
|
43
|
+
Enter PEM pass phrase:
|
44
|
+
tss 0.1.1 built to pkg/tss-0.1.1.gem.
|
45
|
+
```
|
46
|
+
|
47
|
+
Install locally w/ Cert:
|
48
|
+
|
49
|
+
```sh
|
50
|
+
$ gem uninstall tss
|
51
|
+
$ rbenv rehash
|
52
|
+
$ gem install pkg/tss-0.1.1.gem -P MediumSecurity
|
53
|
+
Successfully installed tss-0.1.1
|
54
|
+
1 gem installed
|
55
|
+
```
|
56
|
+
|
57
|
+
## Git Commit Version and CHANGELOG Changes, Tag and push to Github
|
58
|
+
|
59
|
+
```sh
|
60
|
+
$ git add lib/tss/version.rb
|
61
|
+
$ git add CHANGELOG.md
|
62
|
+
$ git commit -m 'Bump version v0.1.1'
|
63
|
+
$ git tag -s v0.1.1 -m "v0.1.1" SHA1_OF_COMMIT
|
64
|
+
```
|
65
|
+
|
66
|
+
Verify last commit and last tag are GPG signed:
|
67
|
+
|
68
|
+
```
|
69
|
+
$ git tag -v v0.1.0
|
70
|
+
...
|
71
|
+
gpg: Good signature from "Glenn Rempe (Code Signing Key) <glenn@rempe.us>" [ultimate]
|
72
|
+
...
|
73
|
+
```
|
74
|
+
|
75
|
+
```
|
76
|
+
$ git log --show-signature
|
77
|
+
...
|
78
|
+
gpg: Good signature from "Glenn Rempe (Code Signing Key) <glenn@rempe.us>" [ultimate]
|
79
|
+
...
|
80
|
+
```
|
81
|
+
|
82
|
+
Push code and tags to GitHub:
|
83
|
+
|
84
|
+
```
|
85
|
+
$ git push
|
86
|
+
$ git push --tags
|
87
|
+
```
|
88
|
+
|
89
|
+
## Push gem to Rubygems.org
|
90
|
+
|
91
|
+
```sh
|
92
|
+
$ gem push pkg/tss-0.1.1.gem
|
93
|
+
```
|
94
|
+
|
95
|
+
Verify Gem Push at [https://rubygems.org/gems/tss](https://rubygems.org/gems/tss)
|
96
|
+
|
97
|
+
## Create a GitHub Release
|
98
|
+
|
99
|
+
Specify the tag we just pushed to attach release to. Copy notes from CHANGELOG.md
|
100
|
+
|
101
|
+
[https://github.com/grempe/tss-rb/releases](https://github.com/grempe/tss-rb/releases)
|
102
|
+
|
103
|
+
## Announce Release on Twitter
|
104
|
+
|
105
|
+
The normal blah, blah, blah.
|
data/Rakefile
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rake/testtask'
|
3
|
+
require 'wwtd/tasks'
|
3
4
|
|
4
5
|
Rake::TestTask.new(:test) do |t|
|
5
6
|
t.libs << 'test'
|
6
7
|
t.libs << 'lib'
|
7
8
|
t.test_files = FileList['test/**/*_test.rb']
|
9
|
+
t.verbose = false
|
10
|
+
t.warning = false
|
8
11
|
end
|
9
12
|
|
10
13
|
Rake::TestTask.new(:bench) do |t|
|
11
14
|
t.libs << 'test'
|
12
15
|
t.libs << 'lib'
|
13
16
|
t.test_files = FileList['test/**/*_benchmark.rb']
|
17
|
+
t.verbose = false
|
18
|
+
t.warning = false
|
14
19
|
end
|
15
20
|
|
16
21
|
# a long running brute force burn-in test
|
@@ -18,6 +23,10 @@ Rake::TestTask.new(:burn) do |t|
|
|
18
23
|
t.libs << 'test'
|
19
24
|
t.libs << 'lib'
|
20
25
|
t.test_files = FileList['test/**/*_brute.rb']
|
26
|
+
t.verbose = false
|
27
|
+
t.warning = false
|
21
28
|
end
|
22
29
|
|
30
|
+
task :test_all => [:test, :bench, :burn]
|
31
|
+
|
23
32
|
task default: :test
|