shhh 1.5.4 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a18f2fa8ab3ca75426c0eccec0ddb42ca59c71ee
4
- data.tar.gz: 2459a7f861d35612ab3e607a87999e9c98e071a2
3
+ metadata.gz: 5d5c47820b4c177b5647c092f84686ef74b169fa
4
+ data.tar.gz: 26ae8727ec033817a6b9cb7c9fc834d952138c40
5
5
  SHA512:
6
- metadata.gz: 031191a168e9e6aa553f3950c8a29c2dc26c15ae4f5b8baeb402b0da3a51036268e66aeb90d409c9ecad439ac259e1f04d54cd823f3d3cca380de196f2df392e
7
- data.tar.gz: 76c711a907e9b97ef72c0ac83c30f8f47e24574c3398ec67d246a9fb8270db3c8761abeeed8d0737dbea89aff4d21fe1313da75603a9d92e215605057e8144dd
6
+ metadata.gz: 9b9fbca8b285a087362d86a87b8f596878956a08c288fa34ebb31cf23dc5ef88c02765bce1a8388a713c437c44c40057dd165de2c61d4acd2006ea49e78ca483
7
+ data.tar.gz: 11813a61d0d08a6badebd7363188966226f08c77f1f038e2a49ca69a7b1578b87dd5b3ef3accb0479b7c3779284f7c0be280294879478ad858e9831b1daf2915
data/.travis.yml CHANGED
@@ -4,7 +4,7 @@ env:
4
4
  rvm:
5
5
  - 2.2.5
6
6
  - 2.3.1
7
- script: "bundle exec rspec"
7
+ script: "rake"
8
8
  notifications:
9
9
  email:
10
10
  recipients:
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  # Shhh — Your Encryption Best Friend
2
3
 
3
4
  [![Gem Version](https://badge.fury.io/rb/shhh.svg)](https://badge.fury.io/rb/shhh)
@@ -22,8 +23,8 @@ And finally, in addition to the rich CLI interface of the `shhh` executable, the
22
23
 
23
24
  ### How It Works
24
25
 
25
- 1. You start with a piece of sensitive data, say it's called _X_.
26
- 2. _X_ is currently a file on your file system, unencrypted.
26
+ 1. You start with a piece of sensitive data, say it's called _X_.
27
+ 2. _X_ is currently a file on your file system, unencrypted.
27
28
  2. You use __shhh__ (with `-g` — for "generate") to make a new encryption key. The key is 256 bits, or 32 bytes, or 45 bytes when base64-encoded.
28
29
  3. You must save this key somewhere safe. We'll talk about this further.
29
30
  4. You use __shhh__ (with `-e`) to encrypt _X_ with the key, and save into _Y_.
@@ -35,7 +36,7 @@ And finally, in addition to the rich CLI interface of the `shhh` executable, the
35
36
 
36
37
  The `shhh` executable as well as the Ruby API provide:
37
38
 
38
- * Symmetric data encryption with:
39
+ * Symmetric data encryption with:
39
40
  * the cipher `AES-256-CBC` used by the US Government
40
41
  * 256-bit private key
41
42
  * which can be auto-generated, and is a *base64-encoded* string which is 45 characters long. The *decoded* secret is always 32 characters long (or 256 bytes long).
@@ -44,23 +45,22 @@ The `shhh` executable as well as the Ruby API provide:
44
45
  * Rich command line interface with some innovative features, such as inline editing of an encrypted file, using your favorite `$EDITOR`.
45
46
  * Data handling:
46
47
  * Automatic compression of the data upon encryption
47
- * Automatic base64 encryption to make all encrypted strings fit onto a single line.
48
+ * Automatic base64 encryption to make all encrypted strings fit onto a single line.
48
49
  * This makes the format suitable for YAML or JSON configuration files, where only the values are encrypted.
49
- * Rich Ruby API
50
+ * Rich Ruby API
50
51
  * (OS-X Only): Ability to create, add and delete generic password entries from the Mac OS-X KeyChain, and to leverage the KeyChain to store sensitive private keys.
51
52
 
52
53
  ### Symmetric Encryption
53
54
 
54
- Symmetric encryption simply means that we are using the same private key to encrypt and decrypt.
55
+ Symmetric encryption simply means that we are using the same private key to encrypt and decrypt.
55
56
  In addition to the private key, the encryption uses an IV vector. The library completely hides `iv` from the user, generates one random `iv` per encryption, and stores it together with the field itself (*base64-encoded*).
56
57
 
57
58
  ## Installation
58
59
 
59
60
  If you plan on using the library in your ruby project with Bundler managing its dependencies, just include the following line in your `Gemfile`:
60
61
 
61
- ```ruby
62
- gem 'shhh'
63
- ```
62
+ gem 'shhh'
63
+
64
64
  And then run `bundle`.
65
65
 
66
66
  Or install it into the global namespace with `gem install` command:
@@ -69,6 +69,12 @@ Or install it into the global namespace with `gem install` command:
69
69
  $ shhh -h
70
70
  $ shhh -E # see examples
71
71
 
72
+ ### BASH Completion (Optional Step)
73
+
74
+ After gem installation, an message will tell you to install a shown BASH script to your `~/.bashrc` or equivalent.
75
+
76
+ Should you choose to install it (this part is optional), you will be able to use "tab-tab" after typing `shhh` and you'll be able to choose from all supported flags.
77
+
72
78
  ## Usage
73
79
 
74
80
  ### Private Keys
@@ -76,7 +82,7 @@ Or install it into the global namespace with `gem install` command:
76
82
  This library relies on the existance of the 32-byte private key (aka, *a secret*) to perform encryption and decryption.
77
83
 
78
84
  The key can be easily:
79
-
85
+
80
86
  * generated by this gem and displayed, copied to the clipboard, or saved to the KeyChain
81
87
  * one way or another must be kept very well protected and secure from attackers
82
88
  * can be fetched from the the Keychain in subsequent encryption/decryption steps
@@ -90,8 +96,8 @@ Encrypted private key will be considerably longer, perhaps 200-300 characters lo
90
96
  When the private key is encrypted, `shhh` will request the password every time it is used. We are looking at adding a caching layer with a configuerable timeout, so that the password is only re-entered once per given period.
91
97
 
92
98
  ### Command Line (CLI)
93
-
94
- You can generate using the command line, or in a programmatic way. First we'll discuss the command line usage, and in a later section we'll discuss Ruby API provided by the gem.
99
+
100
+ You can generate using the command line, or in a programmatic way. First we'll discuss the command line usage, and in a later section we'll discuss Ruby API provided by the gem.
95
101
 
96
102
  #### Generating and Using Private Keys
97
103
 
@@ -111,36 +117,36 @@ Or create a password-protected key, and save it to a file:
111
117
 
112
118
  shhh -gcp -o ~/.secret
113
119
  # New Password: ••••••••••
114
- # Confirm Password: ••••••••••
120
+ # Confirm Password: ••••••••••
115
121
 
116
122
  You can subsequently use the private key by either:
117
123
 
118
- 1. passing the `-k [key value]` flag
119
- 2. passing the `-K [key file]` flag3.
124
+ 1. passing the `-k [key value]` flag
125
+ 2. passing the `-K [key file]` flag3.
120
126
  3. pasting or typing the key with the `-i` (interactive) flag
121
127
  4. passing the `-x [keychain access entry name]` flag to read from Mac OS-X KeyChain Access's generic password field.
122
128
 
123
129
  #### Using KeyChain Access on Mac OS-X
124
130
 
125
- On Mac OS-X there is a third option – using the Keychain Access Manager behind the scenes. Apple released a `security` command line tool, which this library uses to securely store a key/value pair of the key name and the actual private key in your OS-X KeyChain. The advantages of this method are numerous:
131
+ On Mac OS-X there is a third option – using the Keychain Access Manager behind the scenes. Apple released a `security` command line tool, which this library uses to securely store a key/value pair of the key name and the actual private key in your OS-X KeyChain. The advantages of this method are numerous:
126
132
 
127
133
  * The private key won't be lying around your file system unencrypted, so if your Mac is ever stolen, you don't need to worry about the keys running wild.
128
134
  * If you sync your keychain with iCloud you will have access to it on other machines
129
135
 
130
- To activate the KeyChain mode on the Mac, use `-x <keyname>` field instead of `-k` or `-K`, and add it to `-g` when generating a key. The `keyname` is what you name this particular key base on where it's going to be used. For example, you may call it `staging`, etc.
136
+ To activate the KeyChain mode on the Mac, use `-x <keyname>` field instead of `-k` or `-K`, and add it to `-g` when generating a key. The `keyname` is what you name this particular key base on where it's going to be used. For example, you may call it `staging`, etc.
131
137
 
132
138
  The following command generates the private key and immediately stores it in the KeyChain access under the name provided:
133
139
 
134
140
  shhh -g -x staging
135
141
 
136
142
  Now, whenever you need to encrypt something, in addition to the `-k` and `-K` you can also choose `-x staging`. This will retrieve the key from the KeyChain access, and use it for encryption/decryption.
137
-
143
+
138
144
  Finally, you can delete a key from KeyChain access by running:
139
-
145
+
140
146
  shhh --keychain-del staging
141
-
147
+
142
148
  #### KeyChain Key Management
143
-
149
+
144
150
  Another tiny executable supplied with this library is called `keychain`
145
151
 
146
152
  ```bash
@@ -152,46 +158,56 @@ You can use this to add an existing key that can be used with the `shhh` later.
152
158
 
153
159
  This may be a good time to take a look at the full help message for the `shhh` tool, shown naturally with a `-h` or `--help` option.
154
160
 
155
- ```bash
156
- shhh -h
161
+ ```
162
+ Shhh (1.6.1) – encrypt/decrypt data with a private key
157
163
 
158
164
  Usage:
159
- shhh [options]
165
+ # Generate a new key:
166
+ shhh -g [ -c ] [ -p ] [ -x keychain ] [ -o keyfile | -q | ]
160
167
 
168
+ # Encrypt/Decrypt
169
+ shhh [ -d | -e ] [ -f <file> | -s <string> ]
170
+ [ -k key | -K keyfile | -x keychain | -i ]
171
+ [ -o <output file> ]
172
+
173
+ # Edit an encrypted file in $EDITOR
174
+ shhh -t -f <file> [ -b ][ -k key | -K keyfile | -x keychain | -i ]
175
+
161
176
  Modes:
162
177
  -e, --encrypt encrypt mode
163
178
  -d, --decrypt decrypt mode
164
- -t, --edit decrypt, open an encr. file in vim
165
-
179
+ -t, --edit edit an encrypted file in an $EDITOR
180
+
166
181
  Create a private key:
167
182
  -g, --generate generate a new private key
168
183
  -p, --password encrypt the key with a password
169
184
  -c, --copy copy the new key to the clipboard
170
-
185
+ -x, --keychain [key-name] add to (or read from) the OS-X Keychain
186
+
171
187
  Provide a private key:
172
188
  -i, --interactive Paste or type the key interactively
173
189
  -k, --private-key [key] private key as a string
174
190
  -K, --keyfile [key-file] private key from a file
175
-
176
- Use your KeyChain password entry to store a private key:
177
- -x, --keychain [key-name] add to, or read the key from Keychain
178
- --keychain-del [key-name] delete keychain entry with that name
179
-
191
+
180
192
  Data:
181
193
  -s, --string [string] specify a string to encrypt/decrypt
182
194
  -f, --file [file] filename to read from
183
195
  -o, --output [file] filename to write to
184
- -b, --backup create a backup file in the edit mode
185
-
196
+
186
197
  Flags:
198
+ --keychain-del [key-name] delete keychain entry with that name
199
+ -b, --backup create a backup file in the edit mode
187
200
  -v, --verbose show additional information
188
- -q, --quiet silence all output
189
201
  -T, --trace print a backtrace of any errors
190
- -E, --examples show several examples
191
- -L, --language natural language examples
202
+ -q, --quiet silence all output
192
203
  -V, --version print library version
193
204
  -N, --no-color disable color output
205
+
206
+ Help & Examples:
207
+ -E, --examples show several examples
208
+ -L, --language natural language examples
194
209
  -h, --help show help
210
+
195
211
  ```
196
212
 
197
213
  ### CLI Usage Examples
@@ -224,7 +240,7 @@ Decrypt a previously encrypted string:
224
240
  Encrypt a file and save it to shhh.enc:
225
241
 
226
242
  shhh -e -f app-shhh.yml -o app-shhh.enc -k $KEY
227
-
243
+
228
244
  Decrypt an encrypted file and print it to STDOUT:
229
245
 
230
246
  shhh -df app-shhh.enc -k $KEY
@@ -237,11 +253,11 @@ In this mode several flags are of importance:
237
253
 
238
254
  -b (--backup) – will create a backup of the original file
239
255
  -v (--verbose) - will show additional info about file sizes
240
-
241
- Here is a full command that opens a file specified by `-f | --file`, using the key specified in `-K | --key-file`, in the editor defined by the `$EDITOR` environment variable (or if not set – defaults to `/bin/vi`)".
256
+
257
+ Here is a full command that opens a file specified by `-f | --file`, using the key specified in `-K | --keyfile`, in the editor defined by the `$EDITOR` environment variable (or if not set – defaults to `/bin/vi`)".
242
258
 
243
259
  NOTE: while much effort has been made to ensure that the gem is bug free, the reality is that no software is bug free. Please make sure to backup your encrypted file before doing it for the first few times to get familiar with the command.
244
-
260
+
245
261
  To edit an encrypted file in $EDITOR, while asking to paste the key (`-i | --interactive`), while creating a backup file (`-b | --backup`):
246
262
 
247
263
  shhh -tibf data.enc
@@ -256,76 +272,85 @@ To edit an encrypted file in $EDITOR, while asking to paste the key (`-i | --int
256
272
 
257
273
  ### Natural Language Processing
258
274
 
259
- When shhh is called, and when none of the arguments contain a dash, then the the NLP (natural language processing) Translator is invoked. The Translator is based on a very simple algorithm:
260
-
261
- * ignore all of the ambiguous words, or words with duplicate meaning
262
- * unambiguously map arguments to the regular options (the double-dash version)
263
- * words that already match double-dash options are double-dashed
264
- * the mapping of words into --options is performed
265
- * the result is parsed
275
+ When shhh is invoked, and the first argument does not begin with a dash,
276
+ then the the NLP (natural language processing) Translator is invoked.
277
+ The Translator is based on a very simple algorithm:
266
278
 
267
- When verbose is provided as an argument, you will additionally see the command line arguments that NLP system had produced following the mapping of the actual arguments. This may be helpful in diagnosis of why a particular sentence is not recognized.
279
+ * ignore any of the words tagged STRIPPED. These are the ambiguous words, or words with duplicate meaning.
280
+ * map the remaining arguments to regular double-dashed options using the DICTIONARY
281
+ * words that are a direct match for a --option are automatically double-dashed
282
+ * remaining words are left as is (these would be file names, key names, etc).
283
+ * finally, the resulting "new" command line is parsed with regular options.
284
+ * When arguments include "verbose", NLP system will print "before" and "after"
285
+ of the arguments, so that any issues can be debugged and corrected.
268
286
 
269
- CURRENTLY IGNORED WORDS:
287
+ #### CURRENTLY IGNORED WORDS:
270
288
 
271
- and, a, the, it, item, to, key, with, about, for, of, new, make
289
+ and, a, the, it, item, to, key, with, about, for, of, new, make, store, in, print
272
290
 
273
- CURRENTLY DICTIONARY
291
+ #### REGULAR WORD MAPPING
274
292
 
275
- clipboard >————————➤ copy
276
- unlock >————————➤ decrypt
277
- open >————————➤ edit
278
- lock >————————➤ encrypt
279
- >————————➤ backup
280
- >————————➤ keychain
281
- read >————————➤ file
282
- create >————————➤ generate
283
- ask enter type >————————➤ interactive
284
- from >————————➤ keyfile
285
- save write >————————➤ output
286
- using private >————————➤ private_key
287
- value >————————➤ string
288
- silently quietly silent shhh >————————➤ quiet
289
- secure secured protected >————————➤ password
293
+ ```
294
+ ________________________________________________________________________
295
+ clipboard ───────➤ --copy
296
+ unlock ───────➤ --decrypt
297
+ open ───────➤ --edit
298
+ lock ───────➤ --encrypt
299
+ ───────➤ --backup
300
+ ───────➤ --keychain
301
+ read ───────➤ --file
302
+ create ───────➤ --generate
303
+ ask enter type ───────➤ --interactive
304
+ from ───────➤ --keyfile
305
+ save write ───────➤ --output
306
+ using private ───────➤ --private_key
307
+ value ───────➤ --string
308
+ silently quietly silent shhh ───────➤ --quiet
309
+ secure secured protected ───────➤ --password
310
+ ________________________________________________________________________
311
+ ```
290
312
 
291
- EXAMPLES
313
+ #### EXAMPLES
292
314
 
293
315
  ```bash
294
- # generate a new private key and copy to the clipboard
295
- shhh make new key and copy it to the clipboard
316
+ # generate a new private key and copy to the clipboard but do not print to terminal
317
+ shhh create new key to clipboard quietly
296
318
 
297
319
  # generate and save to a file a password-protected key, silently
298
320
  shhh create a secure key and save it to "my.key"
299
321
 
300
322
  # encrypt a plain text string with a key, and save the output to a file
301
- shhh encrypt string "secret string" using $KEY save to file.enc
323
+ shhh encrypt string "secret string" using $(cat my.key) save to file.enc
302
324
 
303
325
  # decrypt a previously encrypted string:
304
- shhh decrypt string $ENC using a $KEY
326
+ shhh decrypt string $ENC using $(cat my.key)
305
327
 
306
- # encrypt shhh.yml with key from $KEYFILE and save it to shhh.enc
307
- shhh encrypt shhh.yml with key from $KEYFILE and save it to shhh.enc
328
+ # encrypt "file.txt" with key from my.key and save it to file.enc
329
+ shhh encrypt file file.txt with key from my.key and save it to file.enc
308
330
 
309
331
  # decrypt an encrypted file and print it to STDOUT:
310
- shhh decrypt file data.enc using $KEY
332
+ shhh decrypt file file.enc with key from "my.key"
311
333
 
312
- # edit an encrypted file in $EDITOR, ask for key, create a backup
313
- shhh edit file ecrets.enc ask for a key and make a backup
334
+ # edit an encrypted file in $EDITOR, ask for key, and create a backup upon save
335
+ shhh edit file file.enc ask for a key and make a backup
314
336
 
315
337
  # generate a new password-encrypted key, save it to your Keychain:
316
- shhh generate key with a password to keychain "kyname"
338
+ shhh create a new protected key store in keychain "my-keychain-key"
339
+
340
+ # print the key stored in the keychain item "my-keychain-key"
341
+ shhh print keychain "my-keychain-key"
317
342
 
318
343
  # use the new key to encrypt a file:
319
- shhh encrypt with keychain item "keyname" file password.txt save to passwords.enc
344
+ shhh encrypt with keychain "my-keychain-key" file "password.txt" and write to "passwords.enc"
320
345
  ```
321
346
 
322
347
  ### Ruby API
323
348
 
324
349
  To use this library you must include the main `Shhh` module into your library.
325
350
 
326
- Any class including `Shhh` will be decorated with new class methods `#private_key` and `#create_private_key`, as well as instance methods `#encr`, and `#decr`.
351
+ Any class including `Shhh` will be decorated with new class methods `#private_key` and `#create_private_key`, as well as instance methods `#encr`, and `#decr`.
327
352
 
328
- `#create_private_key` will generate a new key each time it's called, while `#private_key` will either assign an existing key (if a value is passed), or generate and save a new key in the class instance variable. Therefore each class including `Shhh` will use it's own key (unless the key is assigned).
353
+ `#create_private_key` will generate a new key each time it's called, while `#private_key` will either assign an existing key (if a value is passed), or generate and save a new key in the class instance variable. Therefore each class including `Shhh` will use it's own key (unless the key is assigned).
329
354
 
330
355
  The following example illustrates this point:
331
356
 
@@ -360,7 +385,7 @@ require 'shhh'
360
385
  class TestClass
361
386
  include Shhh
362
387
  private_key ENV['SECRET']
363
-
388
+
364
389
  def sensitive_value=(value)
365
390
  @sensitive_value = encr(value, self.class.private_key)
366
391
  end
@@ -370,6 +395,21 @@ class TestClass
370
395
  end
371
396
  ```
372
397
 
398
+ #### Full Application API
399
+
400
+ Since the command line interface offers more than just encryption/decryption, it is available via `Shhh::Application` class.
401
+
402
+ The class is instantiated with a hash that would be otherwise generated by `Slop.parse(argv)` – ie, typical `options`.
403
+
404
+ Here is an example:
405
+
406
+ ```ruby
407
+ require 'shhh/application'
408
+
409
+ key = Shhh::Application.new(generate: true).execute
410
+ # => returns a new private key
411
+ ```
412
+
373
413
  ### Configuration
374
414
 
375
415
  The library offers a typical `Shhh::Configuration` class which can be used to tweak some of the internals of the gem. This is really meant for a very advanced user who knows what she is doing. The following snippet is actually part of the Configuration class itself, but can be overridden by your code that uses and initializes this library. `Configuration` is a singleton, so changes to it will propagate to any subsequent calls to the gem.
@@ -377,7 +417,7 @@ The library offers a typical `Shhh::Configuration` class which can be used to tw
377
417
  ```ruby
378
418
  require 'zlib'
379
419
  Shhh::Configuration.configure do |config|
380
- config.password_cipher = 'AES-128-CBC' #
420
+ config.password_cipher = 'AES-128-CBC' #
381
421
  config.data_cipher = 'AES-256-CBC'
382
422
  config.private_key_cipher = config.data_cipher
383
423
  config.compression_enabled = true
@@ -402,16 +442,16 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
402
442
  Bug reports and pull requests are welcome on GitHub at https://github.com/kigster/shhh.
403
443
 
404
444
  ## Feature Ideas
405
-
445
+
406
446
  ### Natural Language Based API
407
447
 
408
448
  This is the proposed mini-idea/specification for an alternative CLI that is at a feature parity with the standard flag-based CLI.
409
449
 
410
- shhh generate key to the clipboard and keychain
411
- shhh encrypt file 'hello' using $key [to output.enc]
450
+ shhh generate key to the clipboard and keychain
451
+ shhh encrypt file 'hello' using $key [to output.enc]
412
452
  shhh edit 'passwords.enc' using $key
413
453
  shhh decrypt /etc/secrets encrypted with $key save to ./secrets
414
- shhh encrypt with keychain $item file $input
454
+ shhh encrypt with keychain $item file $input
415
455
 
416
456
  ## License
417
457
 
data/exe/shhh CHANGED
@@ -8,8 +8,8 @@ require 'shhh'
8
8
  #ARGV.any?{ |a| a =~ /^-/ } ?
9
9
  begin
10
10
  ARGV.first =~ /^-/ ?
11
- ::Shhh::App::CLI.new(ARGV.dup).run :
12
- ::Shhh::App::NLP::Translator.new(ARGV.dup).translate.and.run
11
+ ::Shhh::App::CLI.new(ARGV.dup).execute :
12
+ ::Shhh::App::NLP::Translator.new(ARGV.dup).translate.and.execute
13
13
  rescue Interrupt => e
14
14
  STDERR.flush
15
15
  STDERR.puts "Interrupt, #{e.message}, exiting."
data/lib/shhh/app/args.rb CHANGED
@@ -1,24 +1,41 @@
1
1
  module Shhh
2
2
  module App
3
- class Args < Struct.new(:opts, :argv)
4
- MODE = %i(encrypt decrypt generate edit keychain)
5
- KEY = %i(private_key interactive keyfile keychain)
6
- OUTPUT = %i(output quiet)
7
3
 
8
- def mode?; is(MODE); end
9
- def key?; is(KEY); end
4
+ class Args
5
+
6
+ OPTIONS_MODE_SELECTED = %i(encrypt decrypt generate edit keychain)
7
+ OPTIONS_REQUIRE_KEY = %i(encrypt decrypt edit)
8
+ OPTIONS_SPECIFY_KEY = %i(private_key interactive keyfile keychain)
9
+ OPTIONS_SPECIFY_OUTPUT = %i(output quiet)
10
+
11
+ attr_accessor :opts, :selected_options
12
+
13
+ def initialize(opts)
14
+ self.opts = opts
15
+ self.selected_options = opts.keys.reject { |k| !opts[k] }
16
+ end
17
+
18
+ # TODO: generate these methods dynamically
19
+ def do_options_specify_mode?
20
+ do?(OPTIONS_MODE_SELECTED)
21
+ end
22
+
23
+ def do_options_specify_key?
24
+ do?(OPTIONS_SPECIFY_KEY)
25
+ end
26
+
27
+ def do_options_require_key?
28
+ do?(OPTIONS_REQUIRE_KEY)
29
+ end
10
30
 
11
31
  def output_class
12
- output_type = OUTPUT.find{|o| opts[o] } # includes nil
32
+ output_type = OPTIONS_SPECIFY_OUTPUT.find { |o| opts[o] } # includes nil
13
33
  Shhh::App::Output.outputs[output_type]
14
34
  end
15
35
 
16
36
  private
17
- def is(list)
18
- !options_for(list).empty?
19
- end
20
- def options_for(of)
21
- of.map{ |o| opts[o] }.compact
37
+ def do?(list)
38
+ !(list & selected_options).empty?
22
39
  end
23
40
 
24
41
  end
data/lib/shhh/app/cli.rb CHANGED
@@ -1,11 +1,10 @@
1
-
2
- #!/usr/bin/env ruby
3
1
  require 'slop'
4
2
  require 'shhh'
5
3
  require 'colored2'
6
4
  require 'yaml'
5
+ require 'forwardable'
7
6
  require 'openssl'
8
- require 'shhh/app'
7
+ require 'shhh/application'
9
8
  require 'shhh/errors'
10
9
  require 'shhh/app/commands'
11
10
  require 'shhh/app/keychain'
@@ -53,91 +52,66 @@ module Shhh
53
52
  # in a cross-platform way inside the {Shhh::App::Keychain} module.
54
53
 
55
54
  class CLI
56
- attr_accessor :opts, :args, :outputs, :output_proc,
57
- :action, :password, :key, :input_handler, :key_handler
55
+
56
+ extend Forwardable
57
+
58
+ def_delegators :@application, :command
59
+
60
+ attr_accessor :opts, :application, :outputs, :output_proc
58
61
 
59
62
  def initialize(argv)
60
63
  begin
61
- self.opts = parse(argv.dup)
64
+ argv_copy = argv.dup
65
+ dict = false
66
+ if argv_copy.include?('--dictionary')
67
+ dict = true
68
+ argv_copy.delete('--dictionary')
69
+ end
70
+ self.opts = parse(argv_copy)
71
+ if dict
72
+ options = opts.parser.unused_options + opts.parser.used_options
73
+ puts options.map{|o| o.to_s.gsub(/.*(--[\w-]+).*/, '\1') }.sort.join(' ')
74
+ exit 0
75
+ end
62
76
  rescue StandardError => e
63
77
  error exception: e
64
78
  return
65
79
  end
66
80
 
81
+ configure_color(argv)
67
82
 
68
- self.args = ::Shhh::App::Args.new(opts, argv)
83
+ self.application = ::Shhh::Application.new(opts)
69
84
 
70
- configure_color(argv)
71
85
  select_output_stream
72
- initialize_input_handler
73
- initialize_key_handler
74
86
 
75
- self.action = { opts[:encrypt] => :encr, opts[:decrypt] => :decr }[true]
76
87
  end
77
88
 
78
- def run
89
+ def execute
79
90
  return Shhh::App.exit_code if Shhh::App.exit_code != 0
80
- unless opts[:generate]
81
- self.key = PrivateKey::Handler.new(opts,
82
- input_handler).key
83
- end
84
91
 
85
- if command
86
- STDERR.puts ' Running command: '.dark + "#{command.to_s}" if opts[:verbose]
87
- result = command.run
88
- output_proc.call(result)
92
+ result = application.execute
93
+ if result.is_a?(Hash)
94
+ self.output_proc = ::Shhh::App::Args.new({}).output_class
95
+ error(result)
89
96
  else
90
- # command was not found. Reset output to printing, and return an error.
91
- self.output_proc = Args.new(Hash.new, []).output_class
92
- command_not_found_error!
97
+ self.output_proc.call(result)
93
98
  end
94
-
95
- rescue ::OpenSSL::Cipher::CipherError => e
96
- error type: 'Cipher Error',
97
- details: e.message,
98
- reason: 'Perhaps either the secret is invalid, or encrypted data is corrupt.',
99
- exception: e
100
-
101
- rescue Shhh::Errors::InvalidEncodingPrivateKey => e
102
- error type: 'Private Key Error',
103
- details: 'Private key does not appear to be properly encoded. ',
104
- reason: (opts[:password] ? nil : 'Perhaps the key is password-protected?'),
105
- exception: e
106
-
107
- rescue Shhh::Errors::InvalidPasswordPrivateKey => e
108
- error type: 'Error',
109
- details: 'Invalid password, private key can not decrypted.'
110
-
111
- rescue Shhh::Errors::Error => e
112
- error type: 'Error',
113
- details: e.message,
114
- exception: e
115
-
116
- rescue StandardError => e
117
- error exception: e
118
99
  end
119
100
 
101
+ private
102
+
120
103
  def error(hash)
121
104
  Shhh::App.error(hash.merge(config: (opts ? opts.to_hash : {})))
122
105
  end
123
106
 
124
- def editor
125
- ENV['EDITOR'] || '/bin/vi'
126
- end
127
-
128
- def command
129
- @command_class ||= Shhh::App::Commands.find_command_class(opts)
130
- @command ||= @command_class.new(self) if @command_class
131
- end
132
-
133
- private
134
-
135
107
  def select_output_stream
136
- out_klass = self.args.output_class
137
- raise "Can not determine output class from arguments #{opts.to_hash}" unless
138
- out_klass && out_klass.is_a?(Class)
108
+ output_klass = application.args.output_class
139
109
 
140
- self.output_proc = out_klass.new(self).output_proc
110
+ unless output_klass && output_klass.is_a?(Class)
111
+ raise "Can not determine output class from arguments #{opts.to_hash}"
112
+ end
113
+
114
+ self.output_proc = output_klass.new(self).output_proc
141
115
  end
142
116
 
143
117
  def configure_color(argv)
@@ -147,77 +121,64 @@ module Shhh
147
121
  end
148
122
  end
149
123
 
150
- def initialize_input_handler(handler = Input::Handler.new)
151
- self.input_handler = handler
152
- end
153
-
154
- def initialize_key_handler
155
- self.key_handler = PrivateKey::Handler.new(self.opts, input_handler)
156
- end
157
-
158
-
159
- def command_not_found_error!
160
- if key
161
- h = opts.to_hash
162
- supplied_opts = h.keys.select { |k| h[k] }.join(', ')
163
- error type: 'Options Error',
164
- details: 'Unable to determined what command to run',
165
- reason: "You provided the following options: #{supplied_opts.bold.yellow}",
166
- comments: opts.to_s
167
- else
168
- raise Shhh::Errors::NoPrivateKeyFound.new('Private key is required')
169
- end
170
- end
171
-
172
124
  def parse(arguments)
173
125
  Slop.parse(arguments) do |o|
174
- o.banner = 'Usage:'.bold.yellow
175
- o.separator ' shhh [options]'.green
126
+ o.banner = "Shhh (#{Shhh::VERSION}) – encrypt/decrypt data with a private key\n".bold.white
127
+ o.separator 'Usage:'.yellow
128
+ o.separator ' # Generate a new key:'.dark
129
+ o.separator ' shhh -g '.green.bold +
130
+ '[ -c ] [ -p ] [ -x keychain ] [ -o keyfile | -q | ] '.green
131
+ o.separator ''
132
+ o.separator ' # Encrypt/Decrypt '.dark
133
+ o.separator ' shhh [ -d | -e ] '.green.bold +
134
+ '[ -f <file> | -s <string> ] '.green
135
+ o.separator ' [ -k key | -K keyfile | -x keychain | -i ] '.green
136
+ o.separator ' [ -o <output file> ] '.green
137
+ o.separator ' '
138
+ o.separator ' # Edit an encrypted file in $EDITOR '.dark
139
+ o.separator ' shhh -t -f <file> [ -b ]'.green.bold +
140
+ '[ -k key | -K keyfile | -x keychain | -i ] '.green
176
141
  o.separator ' '
177
142
  o.separator 'Modes:'.yellow
178
- o.bool '-h', '--help', ' show help'
143
+ o.bool '-e', '--encrypt', ' encrypt mode'
179
144
  o.bool '-d', '--decrypt', ' decrypt mode'
180
- o.bool '-t', '--edit', ' decrypt, open an encr. file in ' + editor
145
+ o.bool '-t', '--edit', ' decrypt, open an encr. file in an $EDITOR'
181
146
  o.separator ' '
182
147
  o.separator 'Create a private key:'.yellow
183
148
  o.bool '-g', '--generate', ' generate a new private key'
184
149
  o.bool '-p', '--password', ' encrypt the key with a password'
185
150
  o.bool '-c', '--copy', ' copy the new key to the clipboard'
151
+ if Shhh::App.is_osx?
152
+ o.string '-x', '--keychain', '[key-name] '.blue + 'add to (or read from) the OS-X Keychain'
153
+ end
186
154
  o.separator ' '
187
155
  o.separator 'Provide a private key:'.yellow
188
156
  o.bool '-i', '--interactive', ' Paste or type the key interactively'
189
157
  o.string '-k', '--private-key', '[key] '.blue + ' private key as a string'
190
158
  o.string '-K', '--keyfile', '[key-file]'.blue + ' private key from a file'
191
- if Shhh::App.is_osx?
192
- o.separator ' '
193
- o.separator 'Use your KeyChain password entry to store a private key:'.yellow
194
- o.string '-x', '--keychain', '[key-name] '.blue + 'add to, or read the key from Keychain'
195
- o.string '--keychain-del', '[key-name] '.blue + 'delete keychain entry with that name'
196
- end
197
159
  o.separator ' '
198
160
  o.separator 'Data:'.yellow
199
161
  o.string '-s', '--string', '[string]'.blue + ' specify a string to encrypt/decrypt'
200
162
  o.string '-f', '--file', '[file] '.blue + ' filename to read from'
201
163
  o.string '-o', '--output', '[file] '.blue + ' filename to write to'
202
- o.bool '-b', '--backup', ' create a backup file in the edit mode'
203
164
  o.separator ' '
204
- o.separator 'Flags:'.bold.yellow
205
- o.bool '-v', '--verbose', ' show additional information'
206
- o.bool '-q', '--quiet', ' silence all output'
207
- o.bool '-T', '--trace', ' print a backtrace of any errors'
208
- o.bool '-E', '--examples', ' show several examples'
209
- o.bool '-L', '--language', ' natural language examples'
210
- o.bool '-V', '--version', ' print library version'
211
- o.bool '-N', '--no-color', ' disable color output'
212
- o.bool '-e', '--encrypt', ' encrypt mode'
213
- o.separator ''
214
- o.on '--dictionary' do
215
- puts o.to_a.map{ |w| "#{w.flags.reject{|f| f.to_s !~ /--/ }.first.to_s}" }.join(' ')
216
- exit 0
165
+ o.separator 'Flags:'.yellow
166
+ if Shhh::App.is_osx?
167
+ o.string '--keychain-del', '[key-name] '.blue + 'delete keychain entry with that name'
217
168
  end
169
+ o.bool '-b', '--backup', ' create a backup file in the edit mode'
170
+ o.bool '-v', '--verbose', ' show additional information'
171
+ o.bool '-T', '--trace', ' print a backtrace of any errors'
172
+ o.bool '-q', '--quiet', ' silence all output'
173
+ o.bool '-V', '--version', ' print library version'
174
+ o.bool '-N', '--no-color', ' disable color output'
175
+ o.separator ' '
176
+ o.separator 'Help & Examples:'.yellow
177
+ o.bool '-E', '--examples', ' show several examples'
178
+ o.bool '-L', '--language', ' natural language examples'
179
+ o.bool '-h', '--help', ' show help'
180
+
218
181
  end
219
- rescue StandardError => e
220
- raise(e)
221
182
  end
222
183
  end
223
184
  end
@@ -42,26 +42,29 @@ module Shhh
42
42
  end
43
43
  end
44
44
 
45
- attr_accessor :cli
45
+ attr_accessor :application
46
46
 
47
- def initialize(cli)
48
- self.cli = cli
47
+ def initialize(application)
48
+ self.application = application
49
49
  end
50
50
 
51
51
  def opts
52
- cli.opts
52
+ application.opts
53
+ end
54
+ def opts_hash
55
+ application.opts_hash
53
56
  end
54
57
 
55
58
  def key
56
- @key ||= cli.key
59
+ @key ||= application.key
57
60
  end
58
61
 
59
- def run
62
+ def execute
60
63
  raise Shhh::Errors::AbstractMethodCalled.new(:run)
61
64
  end
62
65
 
63
66
  def to_s
64
- "#{self.class.short_name.to_s.bold.yellow}, with options: #{cli.args.argv.join(' ').gsub(/--/, '').bold.green}"
67
+ "#{self.class.short_name.to_s.bold.yellow}, with options: #{application.args.argv.join(' ').gsub(/--/, '').bold.green}"
65
68
  end
66
69
 
67
70
  end
@@ -8,7 +8,7 @@ module Shhh
8
8
  required_options :keychain_del
9
9
  try_after :generate_key, :open_editor, :encrypt_decrypt
10
10
 
11
- def run
11
+ def execute
12
12
  Shhh::App::KeyChain.new(opts[:keychain_del]).delete
13
13
  end
14
14
  end
@@ -11,8 +11,8 @@ module Shhh
11
11
 
12
12
  try_after :generate_key
13
13
 
14
- def run
15
- send(cli.action, content, cli.key)
14
+ def execute
15
+ send(application.action, content, application.key)
16
16
  end
17
17
 
18
18
  private
@@ -8,19 +8,19 @@ module Shhh
8
8
 
9
9
  required_options :generate
10
10
 
11
- def run
11
+ def execute
12
12
  retries ||= 0
13
13
  new_private_key = self.class.create_private_key
14
14
 
15
15
  if opts[:password]
16
16
  new_private_key = encr_password(new_private_key,
17
- cli.input_handler.new_password)
17
+ application.input_handler.new_password)
18
18
  end
19
19
 
20
20
  clipboard_copy(new_private_key) if opts[:copy]
21
21
 
22
22
  if opts[:keychain] && Shhh::App.is_osx?
23
- Shhh::App::KeyChain.new(opts[:keychain]).add(new_private_key)
23
+ Shhh::App::KeyChain.new(opts[:keychain], opts).add(new_private_key)
24
24
  end
25
25
 
26
26
  new_private_key
@@ -18,7 +18,7 @@ module Shhh
18
18
 
19
19
  attr_accessor :tempfile
20
20
 
21
- def run
21
+ def execute
22
22
  begin
23
23
  self.tempfile = ::Tempfile.new(::Base64.urlsafe_encode64(opts[:file]))
24
24
  decrypt_content(self.tempfile)
@@ -31,7 +31,7 @@ module Shhh
31
31
  end
32
32
 
33
33
  def launch_editor
34
- system("#{cli.editor} #{tempfile.path}")
34
+ system("#{application.editor} #{tempfile.path}")
35
35
  end
36
36
 
37
37
  private
@@ -72,7 +72,7 @@ module Shhh
72
72
  out << "\n\nDiff:\n#{diff}"
73
73
  out
74
74
  else
75
- raise Shhh::Errors::EditorExitedAbnormally.new("#{cli.editor} exited with #{$<}")
75
+ raise Shhh::Errors::EditorExitedAbnormally.new("#{application.editor} exited with #{$<}")
76
76
  end
77
77
  end
78
78
 
@@ -4,13 +4,10 @@ module Shhh
4
4
  module App
5
5
  module Commands
6
6
  class PrintKey < Command
7
- include Shhh
8
7
  required_options [ :keychain, :keyfile ]
9
8
 
10
- try_after :show_examples
11
-
12
- def run
13
- cli.key
9
+ def execute
10
+ self.key
14
11
  end
15
12
  end
16
13
  end
@@ -7,7 +7,7 @@ module Shhh
7
7
  required_options :examples
8
8
  try_after :show_help
9
9
 
10
- def run
10
+ def execute
11
11
  output = []
12
12
 
13
13
  output << example(comment: 'generate a new private key into an environment variable:',
@@ -4,10 +4,10 @@ module Shhh
4
4
  module Commands
5
5
  class ShowHelp < Command
6
6
 
7
- required_options :help, ->(opts) { opts.keys.all? { |k| !opts[k] } }
7
+ required_options :help, ->(opts) { opts.to_hash.keys.all? { |k| !opts[k] } }
8
8
  try_after :generate_key, :open_editor, :encrypt_decrypt
9
9
 
10
- def run
10
+ def execute
11
11
  opts.to_s(prefix: ' ' * 2)
12
12
  end
13
13
  end
@@ -10,7 +10,7 @@ module Shhh
10
10
 
11
11
 
12
12
 
13
- def run
13
+ def execute
14
14
  output = []
15
15
 
16
16
  output << Shhh::App::NLP::Base.usage
@@ -5,7 +5,7 @@ module Shhh
5
5
  class ShowVersion < Command
6
6
  required_options :version
7
7
  try_after :show_help
8
- def run
8
+ def execute
9
9
  "shhh (version #{Shhh::VERSION})"
10
10
  end
11
11
  end
@@ -44,7 +44,7 @@ module Shhh
44
44
 
45
45
  def find_command_class(opts)
46
46
  self.sorted_commands.each do |command_class|
47
- return command_class if command_class.options_satisfied_by?(opts.to_hash)
47
+ return command_class if command_class.options_satisfied_by?(opts)
48
48
  end
49
49
  nil
50
50
  end
@@ -22,15 +22,16 @@ module Shhh
22
22
  end
23
23
 
24
24
  def new_password
25
- password = prompt('New Password : ', :blue)
26
- password_confirm = prompt('Confirm Password : ', :blue)
27
-
28
- raise Shhh::Errors::PasswordsDontMatch.new(
29
- 'The passwords you entered do not match.') if password != password_confirm
25
+ password = prompt('New Password : ', :blue)
30
26
 
31
27
  raise Shhh::Errors::PasswordTooShort.new(
32
28
  'Minimum length is 7 characters.') if password.length < 7
33
29
 
30
+ password_confirm = prompt('Confirm Password : ', :blue)
31
+
32
+ raise Shhh::Errors::PasswordsDontMatch.new(
33
+ 'The passwords you entered do not match.') if password != password_confirm
34
+
34
35
  password
35
36
  end
36
37
  end
@@ -54,10 +54,10 @@ module Shhh
54
54
  puts "> #{command.yellow.green}" if opts[:verbose]
55
55
  output = `#{command}`
56
56
  result = $?
57
- raise Shhh::Errors::ExternalCommandError.new("Command error: #{result}, command: #{command}") unless result.success?
57
+ raise Shhh::Errors::KeyChainCommandError.new("Command error: #{result}, command: #{command}") unless result.success?
58
58
  output.chomp
59
59
  rescue Errno::ENOENT => e
60
- raise Shhh::Errors::ExternalCommandError.new("Command error: #{e.message}, command: #{command}")
60
+ raise Shhh::Errors::KeyChainCommandError.new("Command error: #{e.message}, command: #{command}")
61
61
  end
62
62
 
63
63
  def stderr_off
@@ -53,7 +53,7 @@ module Shhh
53
53
  ::Shhh::App::CLI.new(self.translated_argv)
54
54
  end
55
55
 
56
- alias_method :cli, :and
56
+ alias_method :application, :and
57
57
 
58
58
  end
59
59
  end
@@ -0,0 +1,46 @@
1
+ require 'drb/drb'
2
+ module Shhh
3
+ module App
4
+ module Password
5
+ module Cache
6
+ class Client
7
+ # The URI to connect to
8
+
9
+ attr_accessor :uri, :host, :port
10
+ attr_accessor :config
11
+
12
+ def initialize(host: nil,
13
+ port: nil,
14
+ config: {})
15
+ self.config =config
16
+ self.host = host
17
+ self.port = port
18
+ end
19
+
20
+ def uri
21
+ return uri if uri
22
+ template = 'druby://<%= host %>:<%= port %>>'
23
+ renderer = ERB.new template
24
+ self.uri = renderer.result(binding)
25
+ end
26
+
27
+ def start
28
+ raise NoMethodError, 'not implemented'
29
+ # Start a local DRbServer to handle callbacks.
30
+
31
+ # Not necessary for this small example, but will be required
32
+ # as soon as we pass a non-marshallable object as an argument
33
+ # to a dRuby call.
34
+
35
+ # Note: this must be called at least once per process to take any effect.
36
+ # This is particularly important if your application forks.
37
+ DRb.start_service
38
+ # timeserver = DRbObject.new_with_uri(SERVER_URI)
39
+ # puts timeserver.get_current_time
40
+ # sleep 10
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,33 @@
1
+ require 'drb/drb'
2
+ require 'singleton'
3
+ module Shhh
4
+ module App
5
+ module Password
6
+ module Cache
7
+ URI='druby://localhost:8787'
8
+
9
+ class Server
10
+ include Singleton
11
+
12
+ def lookup(key)
13
+ raise NoMethodError, 'not implemented'
14
+ return 'tasty bisquits'
15
+ end
16
+
17
+ FRONT_OBJECT=self.instance
18
+
19
+ def boot
20
+ raise NoMethodError, 'not implemented'
21
+ # The object that handles requests on the server
22
+
23
+ $SAFE = 1 # disable eval() and friends
24
+
25
+ DRb.start_service(URI, FRONT_OBJECT)
26
+ # Wait for the drb server thread to finish before exiting.
27
+ DRb.thread.join
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module Shhh
2
+ module App
3
+ module Password
4
+ module Cache
5
+ SERVER = {
6
+ host: '127.0.0.1',
7
+ port: 8787
8
+ }
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ Shhh.dir_r 'shhh/app/password'
@@ -26,7 +26,7 @@ module Shhh
26
26
  @key = begin
27
27
  Detector.new(opts, input_handler).key
28
28
  rescue Shhh::Errors::Error => e
29
- if Shhh::App::Args.new(opts).key? && key.nil?
29
+ if Shhh::App::Args.new(opts).do_options_specify_key? && key.nil?
30
30
  raise e
31
31
  end
32
32
  end
@@ -0,0 +1,85 @@
1
+ require 'shhh'
2
+ require 'colored2'
3
+ module Shhh
4
+ class Application
5
+
6
+ attr_accessor :opts,
7
+ :opts_hash,
8
+ :args,
9
+ :action,
10
+ :key,
11
+ :input_handler,
12
+ :key_handler,
13
+ :result
14
+
15
+ def initialize(opts)
16
+ self.opts = opts
17
+ self.opts_hash = opts.to_hash
18
+ self.args = ::Shhh::App::Args.new(opts_hash)
19
+ initialize_input_handler
20
+ initialize_key_handler
21
+ initialize_action
22
+ end
23
+
24
+ def initialize_action
25
+ self.action = if opts[:encrypt] then
26
+ :encr
27
+ elsif opts[:decrypt]
28
+ :decr
29
+ end
30
+ end
31
+
32
+ def execute
33
+ if args.do_options_require_key? || args.do_options_specify_key?
34
+ self.key = Shhh::App::PrivateKey::Handler.new(opts, input_handler).key
35
+ raise Shhh::Errors::NoPrivateKeyFound.new('Private key is required') unless self.key
36
+ end
37
+
38
+ unless command
39
+ raise Shhh::Errors::InsufficientOptionsError.new(
40
+ 'Can not determine what to do from the options ' + opts.keys.reject { |k| !opts[k] }.to_s)
41
+ end
42
+
43
+ self.result = command.execute
44
+ return result
45
+
46
+ rescue ::OpenSSL::Cipher::CipherError => e
47
+ error type: 'Cipher Error',
48
+ details: e.message,
49
+ reason: 'Perhaps either the secret is invalid, or encrypted data is corrupt.',
50
+ exception: e
51
+
52
+ rescue Shhh::Errors::Error => e
53
+ error type: e.class.name.split(/::/)[-1],
54
+ details: e.message
55
+
56
+ rescue StandardError => e
57
+ error exception: e
58
+ end
59
+
60
+ def command
61
+ @command_class ||= Shhh::App::Commands.find_command_class(opts)
62
+ @command ||= @command_class.new(self) if @command_class
63
+ end
64
+
65
+ private
66
+
67
+ def error(hash)
68
+ hash
69
+ end
70
+
71
+ def editor
72
+ ENV['EDITOR'] || '/bin/vi'
73
+ end
74
+
75
+
76
+ def initialize_input_handler(handler = ::Shhh::App::Input::Handler.new)
77
+ self.input_handler = handler
78
+ end
79
+
80
+ def initialize_key_handler
81
+ self.key_handler = ::Shhh::App::PrivateKey::Handler.new(self.opts, input_handler)
82
+ end
83
+
84
+ end
85
+ end
@@ -34,6 +34,6 @@ module Shhh
34
34
  end
35
35
 
36
36
  attr_accessor :data_cipher, :password_cipher, :private_key_cipher
37
- attr_accessor :compression_enabled, :compression_level
37
+ attr_accessor :compression_enabled, :compression_level, :password_cache
38
38
  end
39
39
  end
data/lib/shhh/errors.rb CHANGED
@@ -5,15 +5,24 @@ module Shhh
5
5
  class Shhh::Errors::Error < StandardError; end
6
6
 
7
7
  # No secret has been provided for encryption or decryption
8
- class NoPrivateKeyFound < Shhh::Errors::Error; end
9
- class PasswordsDontMatch < Shhh::Errors::Error; end
10
- class PasswordTooShort < Shhh::Errors::Error; end
11
- class DataEncodingVersionMismatch< Shhh::Errors::Error; end
8
+ class InsufficientOptionsError < Shhh::Errors::Error; end
9
+
10
+ class PasswordError < Shhh::Errors::Error; end
11
+ class PasswordsDontMatch < Shhh::Errors::PasswordError; end
12
+ class PasswordTooShort < Shhh::Errors::PasswordError; end
13
+
12
14
  class EditorExitedAbnormally < Shhh::Errors::Error; end
13
- class InvalidEncodingPrivateKey < Shhh::Errors::Error; end
14
- class InvalidPasswordPrivateKey < Shhh::Errors::Error; end
15
+
15
16
  class FileNotFound < Shhh::Errors::Error; end
16
- class ExternalCommandError < Shhh::Errors::Error; end
17
+
18
+ class DataEncodingVersionMismatch< Shhh::Errors::Error; end
19
+
20
+ class KeyError < Shhh::Errors::Error; end
21
+ class InvalidEncodingPrivateKey < Shhh::Errors::KeyError; end
22
+ class InvalidPasswordPrivateKey < Shhh::Errors::KeyError; end
23
+ class NoPrivateKeyFound < Shhh::Errors::KeyError; end
24
+
25
+ class KeyChainCommandError < Shhh::Errors::Error; end
17
26
 
18
27
  # Method was called on an abstract class. Override such methods in
19
28
  # subclasses, and use subclasses for instantiation of objects.
data/lib/shhh/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Shhh
2
- VERSION = '1.5.4'
2
+ VERSION = '1.6.1'
3
3
  end
data/lib/shhh.rb CHANGED
@@ -10,6 +10,7 @@ Shhh::Configuration.configure do |config|
10
10
  config.private_key_cipher = config.data_cipher
11
11
  config.compression_enabled = true
12
12
  config.compression_level = Zlib::BEST_COMPRESSION
13
+ config.password_cache = { provider: :drb, timeout: 30 }
13
14
  end
14
15
 
15
16
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shhh
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.4
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-16 00:00:00.000000000 Z
11
+ date: 2016-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: require_dir
@@ -218,11 +218,15 @@ files:
218
218
  - lib/shhh/app/output/file.rb
219
219
  - lib/shhh/app/output/noop.rb
220
220
  - lib/shhh/app/output/stdout.rb
221
+ - lib/shhh/app/password/cache.rb
222
+ - lib/shhh/app/password/cache/client.rb
223
+ - lib/shhh/app/password/cache/server.rb
221
224
  - lib/shhh/app/private_key/base64_decoder.rb
222
225
  - lib/shhh/app/private_key/decryptor.rb
223
226
  - lib/shhh/app/private_key/detector.rb
224
227
  - lib/shhh/app/private_key/handler.rb
225
228
  - lib/shhh/app/short_name.rb
229
+ - lib/shhh/application.rb
226
230
  - lib/shhh/cipher_handler.rb
227
231
  - lib/shhh/configuration.rb
228
232
  - lib/shhh/data.rb