tss 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,9 +1,14 @@
1
1
  # TSS - Threshold Secret Sharing
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/tss.svg)](https://badge.fury.io/rb/tss)
4
+ [![Dependency Status](https://gemnasium.com/badges/github.com/grempe/tss-rb.svg)](https://gemnasium.com/github.com/grempe/tss-rb)
4
5
  [![Build Status](https://travis-ci.org/grempe/tss-rb.svg?branch=master)](https://travis-ci.org/grempe/tss-rb)
5
6
  [![Coverage Status](https://coveralls.io/repos/github/grempe/tss-rb/badge.svg?branch=master)](https://coveralls.io/github/grempe/tss-rb?branch=master)
6
7
  [![Code Climate](https://codeclimate.com/github/grempe/tss-rb/badges/gpa.svg)](https://codeclimate.com/github/grempe/tss-rb)
8
+ [![Inline docs](http://inch-ci.org/github/grempe/tss-rb.svg?branch=master)](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 10 seconds or less with the
50
- CLI or in Ruby. The CLI defaults to using `human` shares, and Ruby defaults
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
- Secret Recovered and Verified!
57
+ ### Command Line Interface (CLI)
76
58
 
77
- identifier : 4a993275528d5ec7
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 (Binary Octet Shares)
74
+ ### Ruby
87
75
 
88
- ```text
89
- ~/src$ irb
90
- irb(main):001:0> require 'tss'
91
- => true
92
- irb(main):002:0> shares = TSS.split(secret: 'my deep dark secret')
93
- => ["ab87eb60ae14dd87\x02\x03\x004\x01\xC6+\xC8\x9F\xE4\x7F\x85\x17\xBD\xF6\xE6\xE3m\xB9\xFF\x8CGoS\x90\xB0{\xAB\x04N\xE2\x8F\xA0\xDC\x06\xC7Y\xBE\xCD?\xBDe9\xF3\xDF\xEA\xC9s\x105\xA4\xD8TZw\x9E", "ab87eb60ae14dd87\x02\x03\x004\x02T\xBB\xEF\x12\x81\xE2\xD2\x8Et\x95\x8Eg\xE6x=HD8\xAD\xE5\xF2'OdBO4vL\xF90\xA5c\x82\xE8\x11\x94\x8E\xEEV\xB3\xAFh\xB7\x80Ac\x15\xD9\xC7\x93", "ab87eb60ae14dd87\x02\x03\x004\x03\xFF\xE9\a\xE9\x00\xF8'\xB9\xAD\x02\x1A\xEF\xAB\xB2\xA7\xA7q2\x8A\x84\xFBC\v\ny\x98\x12\xA2C\x9B\xBB\xC2qY\x05e\xF6\xC5\x11\x11K\xF6:\xEA\xE8\xF8\f\x8C4\x94\xA2", "ab87eb60ae14dd87\x02\x03\x004\x04\xD4e\xB5\xD2o\x8AxJ\x96\xBB\x80o\xDCC\x12\xA0u\xE0\xB7\xACP\x82\x14\x13\x04\xD0\xE1\x82\xC4:k\\\xA8\xC1g\xA2}\"\xCF\x04x\xEC*\xB9\xC8q,\x8F\xE1\xF6\xB4", "ab87eb60ae14dd87\x02\x03\x004\x05\x7F7])\xEE\x90\x8D}O,\x14\xE7\x91\x89\x88O@\xEA\x90\xCDY\xE6P}?\a\xC7V\xCBX\xE0;\xBA\x1A\x8A\xD6\x1Fi0C\x80\xB5x\xE4\xA0\xC8C\x16\f\xA5\x85"]
94
- irb(main):003:0> secret = TSS.combine(shares: shares)
95
- => {:hash_alg=>"SHA256", :identifier=>"ab87eb60ae14dd87", :num_shares_provided=>5, :num_shares_used=>3, :processing_started_at=>"2016-04-13T19:37:14Z", :processing_finished_at=>"2016-04-13T19:37:14Z", :processing_time_ms=>0.63, :secret=>"my deep dark secret", :shares_select_by=>"first", :combinations=>nil, :threshold=>3}
96
- irb(main):004:0> puts secret[:secret]
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 MediumSecurity
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 simple interface for splitting and combining secrets. You can
228
- see the options available with `tss help`, `tss help split`, or `tss help combine`.
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
- $ tss help split
234
- Usage:
235
- tss split SECRET
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
- Optional Params:
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
- num_shares : The number of total shares that will be generated.
249
+ **Example : `STDIN`**
253
250
 
254
- threshold : The threshold is the number of shares required to recreate a secret. This is always a subset of the total shares.
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
- identifier : A unique identifier string that will be attached to each share. It can be 0-16 Bytes long and use the characters
257
- [a-zA-Z0-9.-_]
255
+ ```text
256
+ echo 'a secret' | bundle exec bin/tss split -O /tmp/shares.txt
257
+ ```
258
258
 
259
- hash_alg : 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.
259
+ **Example : `--input-file`**
260
260
 
261
- pad_blocksize : An Integer, 0-255, that represents a multiple to which the secret will be padded. For example if pad_blocksize is set to
262
- 8, the secret 'abc' would be left-padded to '00000abc' (the padding char is not zero, that is just for illustration).
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
- format : Whether to output the shares as a binary octet string (RTSS), or the same encoded as more human friendly Base 64 text with some
265
- metadata prefixed.
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
- Example using all options:
274
+ **Example : `interactive`**
268
275
 
269
- $ tss split -t 3 -n 6 -i abc123 -h SHA256 -p 8 -f human
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
- Enter your secret:
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
- secret > my secret
294
+ ### CLI Share Combining
274
295
 
275
- tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEBQ-AQG3PuU4oT4qHOh2oJmu-vQwGE6O5hsGRBNtdAYauTIi7VoIdi5imWSrswDdRy
276
- tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADECM0OK5TSamH3nubH3FJ2EGZ4Yux4eQC-mvcYY85oOe6ae3kpvVXjuRUDU1m6sX20X
277
- tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEDb7yF4Vhr1JqNe2Nc8IXo98hmKAxsqC3c_Mn3r3t60NxQMC22ate51StDOM-BImch
278
- tss~v1~abc123~3~YWJjMTIzAAAAAAAAAAAAAAIDADEEIXU0FajldnRtEQMLK-ZYMO2MRa0NmkBFfNAOx7olbgXLkVbP9txXMDsdokblVwke
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
- **Example CLI Split Usage**
304
+ Here are some simple examples of using each:
285
305
 
286
- For security purposes you will be prompted for your secret and cannot enter it
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 CLI Combine Usage**
322
+ **Example : `--input-file`**
303
323
 
304
- For security purposes you will be prompted for your shares and cannot them
305
- on the command line.
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
- ```sh
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
- Secret Recovered and Verified!
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
- identifier : abc
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. They can be Strings if directly coercible to Ints.
356
- The `num_shares` value must be greater-than-or-equal-to the `threshold` value.
357
- If you don't pass in these options they will be set to `threshold = 3` and
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 `'binary'` or `'human'` values.
379
- This instructs the output of a split to either provide an array of binary octet
380
- strings (standard RTSS format for interoperability), or a human friendly
381
- URL Safe Base 64 encoded version of that same binary output. The `human` format
382
- can be easily shared in a tweet, email, or even a URL. The `human` format is
383
- prefixed with `tss-VERSION-IDENTIFIER-THRESHOLD-` to make it easier to visually
384
- compare shares and see if they have matching identifiers and if you have
385
- enough shares to reach the threshold. Note, this prefix is not parsed
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
- => ["c70963b2e20fccfd\x02\x03\x001\x01\x1Fg4\xDC\xAA\x96\x9D3\xCB\xFB\xF7\xB0\x91}\xCA\xB7\x0E\xB0\xF3.}O\xD0&Z\x11\xB0\xAB\xF48f#*\xBA\xB7)l\x05\xAF4\xFA\x95\x9C\xF2\x8E\xA6\xB9=",
439
- "c70963b2e20fccfd\x02\x03\x001\x02Y|\x1F\x1Co\x8BW\f^\xFE\xA5\x92G\xA4\xD0K\xC6@G\xDC\x02\xBF\xF1\xAE\xE7\vP\xF1*\x9C\xA5$\edM#\xB0\xEBy\a}\xA18\rBZ\x8A\xEE",
440
- "c70963b2e20fccfd\x02\x03\x001\x03Y\x044\xDF\xDA{\xA5P\xB5g3P\xF6\xBB{\x86\x13#\xAC3\xBB\x92\x8F`\xCF\xEE\xF1Sz{\x10\x03\xB9\xAFZ71>(=\xF2HI\xA8\x16*\xC1\x04",
441
- "c70963b2e20fccfd\x02\x03\x001\x04\x90\xA3\\W\xFB\xFF.\xE8&\xA3\x13N\x968\xC5\xEEg\xA1\xD8\xB6\xD9\xE9\xAAMz\xA9\xF3H\e7#\xE7\xA8\r@\xD9\\\xB8\x7F\xF3Q\x8D\x80\xCF1~\x97P",
442
- "c70963b2e20fccfd\x02\x03\x001\x05\x90\xDBw\x94N\x0F\xDC\xB4\xCD:\x85\x8C''n#\xB2\xC23Y`\xC4\xD4\x83RLR\xEAK\xD0\x96\xC0\n\xC6W\xCD\xDDm.\xC9\xDEd\xF1je\x0E\xDC\xBA"]
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
- => {:identifier=>"c70963b2e20fccfd",
446
- :num_shares_provided=>5,
447
- :num_shares_used=>3,
448
- :processing_started_at=>"2016-04-10T00:58:04Z",
449
- :processing_finished_at=>"2016-04-10T00:58:04Z",
450
- :processing_time_ms=>0.37,
451
- :secret=>"foo bar baz",
452
- :shares_select_by=>"first",
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 then the an Exception will be raised before processing has started.
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 `Dry::Types::ConstraintError` Exception will be raised.
571
+ a `TSS::ArgumentError` Exception will be raised.
519
572
 
520
- The splitting and combining operations may also raise `TSS::ArgumentError`
521
- or `TSS::Error` exceptions as they are run.
573
+ The splitting and combining operations may also raise the following
574
+ exception types:
522
575
 
523
- All Exception messages should include hints as to what went wrong in the
524
- `ex.messages` attribute.
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 code has been tested for binary compatibility with the
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` more friendly to use when sending shares to others an enhanced
584
- version of the RTSS binary data format is provided that is more human friendly.
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 the following tilde `~`
590
- separated elements. The `~` is used to ensure the share remains URL Safe.
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`. To
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