shhh 1.4.1 → 1.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +152 -56
- data/bin/shhh.bash-completion +24 -0
- data/exe/shhh +12 -1
- data/lib/shhh/app/args.rb +13 -4
- data/lib/shhh/app/cli.rb +43 -22
- data/lib/shhh/app/commands/command.rb +6 -4
- data/lib/shhh/app/commands/show_help.rb +1 -1
- data/lib/shhh/app/commands/show_language_examples.rb +81 -0
- data/lib/shhh/app/nlp/constants.rb +32 -0
- data/lib/shhh/app/nlp/translator.rb +61 -0
- data/lib/shhh/app/nlp/usage.rb +72 -0
- data/lib/shhh/app/nlp.rb +18 -0
- data/lib/shhh/app/output/base.rb +61 -0
- data/lib/shhh/app/output/file.rb +3 -8
- data/lib/shhh/app/output/noop.rb +14 -0
- data/lib/shhh/app/output/stdout.rb +3 -1
- data/lib/shhh/app/output.rb +15 -0
- data/lib/shhh/app/short_name.rb +10 -0
- data/lib/shhh/app.rb +4 -2
- data/lib/shhh/version.rb +1 -1
- data/shhh.gemspec +12 -1
- metadata +48 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a18f2fa8ab3ca75426c0eccec0ddb42ca59c71ee
|
4
|
+
data.tar.gz: 2459a7f861d35612ab3e607a87999e9c98e071a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 031191a168e9e6aa553f3950c8a29c2dc26c15ae4f5b8baeb402b0da3a51036268e66aeb90d409c9ecad439ac259e1f04d54cd823f3d3cca380de196f2df392e
|
7
|
+
data.tar.gz: 76c711a907e9b97ef72c0ac83c30f8f47e24574c3398ec67d246a9fb8270db3c8761abeeed8d0737dbea89aff4d21fe1313da75603a9d92e215605057e8144dd
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,44 +1,57 @@
|
|
1
|
-
# Shhh
|
1
|
+
# Shhh — Your Encryption Best Friend
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/shhh.svg)](https://badge.fury.io/rb/shhh)
|
4
4
|
[![Downloads](http://ruby-gem-downloads-badge.herokuapp.com/shhh?type=total)](https://rubygems.org/gems/shhh)
|
5
5
|
|
6
|
-
|
7
|
-
[![Build Status](https://travis-ci.org/kigster/secrets-cipher-base64.svg?branch=master)](https://travis-ci.org/kigster/secrets-cipher-base64)
|
6
|
+
[![Build Status](https://travis-ci.org/kigster/shhh.svg?branch=master)](https://travis-ci.org/kigster/shhh)
|
8
7
|
[![Code Climate](https://codeclimate.com/github/kigster/secrets-cipher-base64/badges/gpa.svg)](https://codeclimate.com/github/kigster/secrets-cipher-base64)
|
9
8
|
[![Test Coverage](https://codeclimate.com/github/kigster/secrets-cipher-base64/badges/coverage.svg)](https://codeclimate.com/github/kigster/secrets-cipher-base64/coverage)
|
10
9
|
[![Issue Count](https://codeclimate.com/github/kigster/secrets-cipher-base64/badges/issue_count.svg)](https://codeclimate.com/github/kigster/secrets-cipher-base64)
|
11
10
|
|
12
|
-
##
|
11
|
+
## Description
|
13
12
|
|
14
|
-
|
13
|
+
### Summary
|
15
14
|
|
16
|
-
|
15
|
+
> __shhh__ is little program that makes it _trivial to encrypt and decrypt sensitive data_. But, unlike many other existing tools, __shhh__'s goal is to dramatically simplify the command line interface (CLI), and make symmetric encryption as routine as listing directories in Terminal.
|
17
16
|
|
18
|
-
|
19
|
-
>
|
20
|
-
> * Symmetric data encryption with:
|
21
|
-
> * the cipher `AES-256-CBC`
|
22
|
-
> * 256-bit private key
|
23
|
-
> * which can be optionally password-encrypted.
|
24
|
-
> * Rich command line interface with some innovative features, such as inline encrypted file editing using your current `$EDITOR`
|
25
|
-
> * Automatic compression of the data
|
26
|
-
> * Rich Ruby API and highly extensible approach to encryption/decryption
|
27
|
-
> * Automatic detection of password-protected keys,
|
28
|
-
> * and more...
|
17
|
+
With this tool I wanted to make it easy to memorize the most common options, so that there is little no longer a barrier to the full power of encryption offered by [`OpenSSL`](https://www.openssl.org/) library.
|
29
18
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
Using a single-line string that `urlsafe_encode64()` generates, makes this gem well suited for encrypting specific fields in the YAML file, or simply the entire file. This also means that the private key can be easily exported as an environment variable (as it's value is a single-line string).
|
35
|
-
|
36
|
-
> NOTE: The library leverages the code shown in the following discussion: http://stuff-things.net/2015/02/12/symmetric-encryption-with-ruby-and-rails/ I'd like to acknowledge the the author of the above thread for providing clear examples of a simple symmetric encryption with `OpenSSL`.
|
19
|
+
And no tool works in isolation: this is just a stepping stone that could be part of your deployment or infrastructure code: don't rely on external services: minimize the risk of a "man-in-the-middle" attack, by dealing with the encryption and decryption locally. Ideal application of this gem, is the ability to store sensitive application _secrets_ protected on a file system, or in a repo, and use `shhh` to automaticaly decrypt the data when any changes are to be made, or when the data needs to be read by an application service.
|
20
|
+
|
21
|
+
And finally, in addition to the rich CLI interface of the `shhh` executable, there is a rich and extensibe symmetric encryption API that can be easily used from any ruby project.
|
37
22
|
|
38
|
-
|
23
|
+
### How It Works
|
39
24
|
|
40
|
-
|
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.
|
27
|
+
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
|
+
3. You must save this key somewhere safe. We'll talk about this further.
|
29
|
+
4. You use __shhh__ (with `-e`) to encrypt _X_ with the key, and save into _Y_.
|
30
|
+
5. You now delete _X_ from your file system. You now only have _Y_ and the _key_.
|
31
|
+
7. To read the data back, you use __shhh__ with the `-d` (for "decrypt") to decrypt _Y_ back. You can print the contents or save it again.
|
32
|
+
8. But, instead of just decrypting it, you can use the `-t` mode (for "ediT"), which would decrypt _Y_ into _X_, save _X_ into a temporary location, and allow you to edit the unencrypted file using `$EDITOR`. Once you save and exit the editor, a new version is automatically encrypted and replaces the old version, showing you the diff and, optionally, creating a backup.
|
41
33
|
|
34
|
+
### Features
|
35
|
+
|
36
|
+
The `shhh` executable as well as the Ruby API provide:
|
37
|
+
|
38
|
+
* Symmetric data encryption with:
|
39
|
+
* the cipher `AES-256-CBC` used by the US Government
|
40
|
+
* 256-bit private key
|
41
|
+
* 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).
|
42
|
+
* which can be optionally password-encrypted using 128-bit key.
|
43
|
+
* which is automatically detected when the key is read
|
44
|
+
* Rich command line interface with some innovative features, such as inline editing of an encrypted file, using your favorite `$EDITOR`.
|
45
|
+
* Data handling:
|
46
|
+
* Automatic compression of the data upon encryption
|
47
|
+
* Automatic base64 encryption to make all encrypted strings fit onto a single line.
|
48
|
+
* This makes the format suitable for YAML or JSON configuration files, where only the values are encrypted.
|
49
|
+
* Rich Ruby API
|
50
|
+
* (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
|
+
### Symmetric Encryption
|
53
|
+
|
54
|
+
Symmetric encryption simply means that we are using the same private key to encrypt and decrypt.
|
42
55
|
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*).
|
43
56
|
|
44
57
|
## Installation
|
@@ -60,13 +73,21 @@ Or install it into the global namespace with `gem install` command:
|
|
60
73
|
|
61
74
|
### Private Keys
|
62
75
|
|
63
|
-
This library relies on the existance of the 32-byte private key (aka, *a secret*)
|
76
|
+
This library relies on the existance of the 32-byte private key (aka, *a secret*) to perform encryption and decryption.
|
64
77
|
|
65
|
-
|
78
|
+
The key can be easily:
|
79
|
+
|
80
|
+
* generated by this gem and displayed, copied to the clipboard, or saved to the KeyChain
|
81
|
+
* one way or another must be kept very well protected and secure from attackers
|
82
|
+
* can be fetched from the the Keychain in subsequent encryption/decryption steps
|
83
|
+
* password-protected, which you can enable during the generation with the `-p` flag.
|
84
|
+
* NOTE: right now there is no way to add a password to an existing key, only generate a new one.
|
66
85
|
|
67
|
-
|
86
|
+
Unencrypted private key will be in the form of a base64-encoded string, 45 characters long.
|
68
87
|
|
69
|
-
|
88
|
+
Encrypted private key will be considerably longer, perhaps 200-300 characters long.
|
89
|
+
|
90
|
+
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.
|
70
91
|
|
71
92
|
### Command Line (CLI)
|
72
93
|
|
@@ -116,7 +137,7 @@ Now, whenever you need to encrypt something, in addition to the `-k` and `-K` yo
|
|
116
137
|
|
117
138
|
Finally, you can delete a key from KeyChain access by running:
|
118
139
|
|
119
|
-
shhh -
|
140
|
+
shhh --keychain-del staging
|
120
141
|
|
121
142
|
#### KeyChain Key Management
|
122
143
|
|
@@ -136,33 +157,41 @@ This may be a good time to take a look at the full help message for the `shhh` t
|
|
136
157
|
|
137
158
|
Usage:
|
138
159
|
shhh [options]
|
160
|
+
|
139
161
|
Modes:
|
140
|
-
|
141
|
-
|
142
|
-
|
162
|
+
-e, --encrypt encrypt mode
|
163
|
+
-d, --decrypt decrypt mode
|
164
|
+
-t, --edit decrypt, open an encr. file in vim
|
165
|
+
|
143
166
|
Create a private key:
|
144
|
-
|
145
|
-
|
146
|
-
|
167
|
+
-g, --generate generate a new private key
|
168
|
+
-p, --password encrypt the key with a password
|
169
|
+
-c, --copy copy the new key to the clipboard
|
170
|
+
|
147
171
|
Provide a private key:
|
148
|
-
|
149
|
-
|
150
|
-
|
172
|
+
-i, --interactive Paste or type the key interactively
|
173
|
+
-k, --private-key [key] private key as a string
|
174
|
+
-K, --keyfile [key-file] private key from a file
|
175
|
+
|
151
176
|
Use your KeyChain password entry to store a private key:
|
152
|
-
|
153
|
-
|
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
|
+
|
154
180
|
Data:
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
181
|
+
-s, --string [string] specify a string to encrypt/decrypt
|
182
|
+
-f, --file [file] filename to read from
|
183
|
+
-o, --output [file] filename to write to
|
184
|
+
-b, --backup create a backup file in the edit mode
|
185
|
+
|
159
186
|
Flags:
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
187
|
+
-v, --verbose show additional information
|
188
|
+
-q, --quiet silence all output
|
189
|
+
-T, --trace print a backtrace of any errors
|
190
|
+
-E, --examples show several examples
|
191
|
+
-L, --language natural language examples
|
192
|
+
-V, --version print library version
|
193
|
+
-N, --no-color disable color output
|
194
|
+
-h, --help show help
|
166
195
|
```
|
167
196
|
|
168
197
|
### CLI Usage Examples
|
@@ -213,7 +242,7 @@ Here is a full command that opens a file specified by `-f | --file`, using the k
|
|
213
242
|
|
214
243
|
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.
|
215
244
|
|
216
|
-
To edit an encrypted file in $EDITOR, while asking
|
245
|
+
To edit an encrypted file in $EDITOR, while asking to paste the key (`-i | --interactive`), while creating a backup file (`-b | --backup`):
|
217
246
|
|
218
247
|
shhh -tibf data.enc
|
219
248
|
# => Private Key: ••••••••••••••••••••••••••••••••••••••••••••
|
@@ -224,6 +253,72 @@ To edit an encrypted file in $EDITOR, while asking for a key (`-i | --interactiv
|
|
224
253
|
# ---
|
225
254
|
# # (c) 2016 Konstantin Gredeskoul. All rights reserved.
|
226
255
|
|
256
|
+
|
257
|
+
### Natural Language Processing
|
258
|
+
|
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
|
266
|
+
|
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.
|
268
|
+
|
269
|
+
CURRENTLY IGNORED WORDS:
|
270
|
+
|
271
|
+
and, a, the, it, item, to, key, with, about, for, of, new, make
|
272
|
+
|
273
|
+
CURRENTLY DICTIONARY
|
274
|
+
|
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
|
290
|
+
|
291
|
+
EXAMPLES
|
292
|
+
|
293
|
+
```bash
|
294
|
+
# generate a new private key and copy to the clipboard
|
295
|
+
shhh make new key and copy it to the clipboard
|
296
|
+
|
297
|
+
# generate and save to a file a password-protected key, silently
|
298
|
+
shhh create a secure key and save it to "my.key"
|
299
|
+
|
300
|
+
# 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
|
302
|
+
|
303
|
+
# decrypt a previously encrypted string:
|
304
|
+
shhh decrypt string $ENC using a $KEY
|
305
|
+
|
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
|
308
|
+
|
309
|
+
# decrypt an encrypted file and print it to STDOUT:
|
310
|
+
shhh decrypt file data.enc using $KEY
|
311
|
+
|
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
|
314
|
+
|
315
|
+
# generate a new password-encrypted key, save it to your Keychain:
|
316
|
+
shhh generate key with a password to keychain "kyname"
|
317
|
+
|
318
|
+
# use the new key to encrypt a file:
|
319
|
+
shhh encrypt with keychain item "keyname" file password.txt save to passwords.enc
|
320
|
+
```
|
321
|
+
|
227
322
|
### Ruby API
|
228
323
|
|
229
324
|
To use this library you must include the main `Shhh` module into your library.
|
@@ -312,9 +407,10 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/kigste
|
|
312
407
|
|
313
408
|
This is the proposed mini-idea/specification for an alternative CLI that is at a feature parity with the standard flag-based CLI.
|
314
409
|
|
315
|
-
shhh
|
316
|
-
shhh
|
317
|
-
shhh
|
410
|
+
shhh generate key to the clipboard and keychain
|
411
|
+
shhh encrypt file 'hello' using $key [to output.enc]
|
412
|
+
shhh edit 'passwords.enc' using $key
|
413
|
+
shhh decrypt /etc/secrets encrypted with $key save to ./secrets
|
318
414
|
shhh encrypt with keychain $item file $input
|
319
415
|
|
320
416
|
## License
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
#
|
3
|
+
# Shhh command line completion
|
4
|
+
#
|
5
|
+
# © 2015-2016, Konstantin Gredeskoul, https://github.com/kigster/shhh
|
6
|
+
# MIT LICENSE
|
7
|
+
#
|
8
|
+
|
9
|
+
_shhh() {
|
10
|
+
local SHHH_OPTS SHHH_POINTS cur prev
|
11
|
+
|
12
|
+
cur="${COMP_WORDS[COMP_CWORD]}"
|
13
|
+
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
14
|
+
|
15
|
+
COMPREPLY=()
|
16
|
+
|
17
|
+
SHHH_COMP_OPTIONS=$(shhh --dictionary)
|
18
|
+
[[ $COMP_CWORD == 1 ]] && SHHH_COMP_OPTIONS="${SHHH_COMP_OPTIONS} ${SHHH_COMMANDS}"
|
19
|
+
COMPREPLY=( $(compgen -W "${SHHH_COMP_OPTIONS}" -- ${cur}) )
|
20
|
+
return 0
|
21
|
+
}
|
22
|
+
|
23
|
+
complete -F _shhh shhh
|
24
|
+
|
data/exe/shhh
CHANGED
@@ -5,4 +5,15 @@ $LOAD_PATH << lib_path if File.exist?(lib_path) && !$LOAD_PATH.include?(lib_path
|
|
5
5
|
|
6
6
|
require 'shhh'
|
7
7
|
|
8
|
-
|
8
|
+
#ARGV.any?{ |a| a =~ /^-/ } ?
|
9
|
+
begin
|
10
|
+
ARGV.first =~ /^-/ ?
|
11
|
+
::Shhh::App::CLI.new(ARGV.dup).run :
|
12
|
+
::Shhh::App::NLP::Translator.new(ARGV.dup).translate.and.run
|
13
|
+
rescue Interrupt => e
|
14
|
+
STDERR.flush
|
15
|
+
STDERR.puts "Interrupt, #{e.message}, exiting."
|
16
|
+
STDERR.flush
|
17
|
+
end
|
18
|
+
|
19
|
+
|
data/lib/shhh/app/args.rb
CHANGED
@@ -1,15 +1,24 @@
|
|
1
1
|
module Shhh
|
2
2
|
module App
|
3
|
-
class Args < Struct.new(:opts)
|
3
|
+
class Args < Struct.new(:opts, :argv)
|
4
4
|
MODE = %i(encrypt decrypt generate edit keychain)
|
5
5
|
KEY = %i(private_key interactive keyfile keychain)
|
6
|
+
OUTPUT = %i(output quiet)
|
6
7
|
|
7
|
-
def mode?; is
|
8
|
-
def key?; is
|
8
|
+
def mode?; is(MODE); end
|
9
|
+
def key?; is(KEY); end
|
10
|
+
|
11
|
+
def output_class
|
12
|
+
output_type = OUTPUT.find{|o| opts[o] } # includes nil
|
13
|
+
Shhh::App::Output.outputs[output_type]
|
14
|
+
end
|
9
15
|
|
10
16
|
private
|
11
17
|
def is(list)
|
12
|
-
list.
|
18
|
+
!options_for(list).empty?
|
19
|
+
end
|
20
|
+
def options_for(of)
|
21
|
+
of.map{ |o| opts[o] }.compact
|
13
22
|
end
|
14
23
|
|
15
24
|
end
|
data/lib/shhh/app/cli.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
#!/usr/bin/env ruby
|
2
3
|
require 'slop'
|
3
4
|
require 'shhh'
|
@@ -9,8 +10,10 @@ require 'shhh/errors'
|
|
9
10
|
require 'shhh/app/commands'
|
10
11
|
require 'shhh/app/keychain'
|
11
12
|
require 'shhh/app/private_key/handler'
|
13
|
+
require 'shhh/app/nlp/constants'
|
12
14
|
require 'highline'
|
13
15
|
|
16
|
+
require_relative 'output/file'
|
14
17
|
require_relative 'output/file'
|
15
18
|
require_relative 'output/stdout'
|
16
19
|
|
@@ -50,7 +53,7 @@ module Shhh
|
|
50
53
|
# in a cross-platform way inside the {Shhh::App::Keychain} module.
|
51
54
|
|
52
55
|
class CLI
|
53
|
-
attr_accessor :opts, :
|
56
|
+
attr_accessor :opts, :args, :outputs, :output_proc,
|
54
57
|
:action, :password, :key, :input_handler, :key_handler
|
55
58
|
|
56
59
|
def initialize(argv)
|
@@ -60,11 +63,15 @@ module Shhh
|
|
60
63
|
error exception: e
|
61
64
|
return
|
62
65
|
end
|
66
|
+
|
67
|
+
|
68
|
+
self.args = ::Shhh::App::Args.new(opts, argv)
|
69
|
+
|
63
70
|
configure_color(argv)
|
64
71
|
select_output_stream
|
65
|
-
|
66
72
|
initialize_input_handler
|
67
73
|
initialize_key_handler
|
74
|
+
|
68
75
|
self.action = { opts[:encrypt] => :encr, opts[:decrypt] => :decr }[true]
|
69
76
|
end
|
70
77
|
|
@@ -76,11 +83,12 @@ module Shhh
|
|
76
83
|
end
|
77
84
|
|
78
85
|
if command
|
86
|
+
STDERR.puts ' Running command: '.dark + "#{command.to_s}" if opts[:verbose]
|
79
87
|
result = command.run
|
80
88
|
output_proc.call(result)
|
81
89
|
else
|
82
90
|
# command was not found. Reset output to printing, and return an error.
|
83
|
-
self.output_proc =
|
91
|
+
self.output_proc = Args.new(Hash.new, []).output_class
|
84
92
|
command_not_found_error!
|
85
93
|
end
|
86
94
|
|
@@ -125,9 +133,11 @@ module Shhh
|
|
125
133
|
private
|
126
134
|
|
127
135
|
def select_output_stream
|
128
|
-
|
129
|
-
|
130
|
-
|
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)
|
139
|
+
|
140
|
+
self.output_proc = out_klass.new(self).output_proc
|
131
141
|
end
|
132
142
|
|
133
143
|
def configure_color(argv)
|
@@ -137,7 +147,6 @@ module Shhh
|
|
137
147
|
end
|
138
148
|
end
|
139
149
|
|
140
|
-
|
141
150
|
def initialize_input_handler(handler = Input::Handler.new)
|
142
151
|
self.input_handler = handler
|
143
152
|
end
|
@@ -153,8 +162,8 @@ module Shhh
|
|
153
162
|
supplied_opts = h.keys.select { |k| h[k] }.join(', ')
|
154
163
|
error type: 'Options Error',
|
155
164
|
details: 'Unable to determined what command to run',
|
156
|
-
reason: "You provided the following options: #{supplied_opts.bold.yellow}"
|
157
|
-
|
165
|
+
reason: "You provided the following options: #{supplied_opts.bold.yellow}",
|
166
|
+
comments: opts.to_s
|
158
167
|
else
|
159
168
|
raise Shhh::Errors::NoPrivateKeyFound.new('Private key is required')
|
160
169
|
end
|
@@ -163,37 +172,49 @@ module Shhh
|
|
163
172
|
def parse(arguments)
|
164
173
|
Slop.parse(arguments) do |o|
|
165
174
|
o.banner = 'Usage:'.bold.yellow
|
166
|
-
o.separator ' shhh [options]'.
|
167
|
-
o.separator '
|
175
|
+
o.separator ' shhh [options]'.green
|
176
|
+
o.separator ' '
|
177
|
+
o.separator 'Modes:'.yellow
|
168
178
|
o.bool '-h', '--help', ' show help'
|
169
179
|
o.bool '-d', '--decrypt', ' decrypt mode'
|
170
180
|
o.bool '-t', '--edit', ' decrypt, open an encr. file in ' + editor
|
171
|
-
o.separator '
|
181
|
+
o.separator ' '
|
182
|
+
o.separator 'Create a private key:'.yellow
|
172
183
|
o.bool '-g', '--generate', ' generate a new private key'
|
173
184
|
o.bool '-p', '--password', ' encrypt the key with a password'
|
174
185
|
o.bool '-c', '--copy', ' copy the new key to the clipboard'
|
175
|
-
o.separator '
|
186
|
+
o.separator ' '
|
187
|
+
o.separator 'Provide a private key:'.yellow
|
176
188
|
o.bool '-i', '--interactive', ' Paste or type the key interactively'
|
177
|
-
o.string '-k', '--private-key', '[key] '.
|
178
|
-
o.string '-K', '--keyfile', '[key-file]'.
|
189
|
+
o.string '-k', '--private-key', '[key] '.blue + ' private key as a string'
|
190
|
+
o.string '-K', '--keyfile', '[key-file]'.blue + ' private key from a file'
|
179
191
|
if Shhh::App.is_osx?
|
180
|
-
o.separator '
|
181
|
-
o.
|
182
|
-
o.string '--keychain
|
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'
|
183
196
|
end
|
184
|
-
o.separator '
|
185
|
-
o.
|
186
|
-
o.string '-
|
187
|
-
o.string '-
|
197
|
+
o.separator ' '
|
198
|
+
o.separator 'Data:'.yellow
|
199
|
+
o.string '-s', '--string', '[string]'.blue + ' specify a string to encrypt/decrypt'
|
200
|
+
o.string '-f', '--file', '[file] '.blue + ' filename to read from'
|
201
|
+
o.string '-o', '--output', '[file] '.blue + ' filename to write to'
|
188
202
|
o.bool '-b', '--backup', ' create a backup file in the edit mode'
|
203
|
+
o.separator ' '
|
189
204
|
o.separator 'Flags:'.bold.yellow
|
190
205
|
o.bool '-v', '--verbose', ' show additional information'
|
206
|
+
o.bool '-q', '--quiet', ' silence all output'
|
191
207
|
o.bool '-T', '--trace', ' print a backtrace of any errors'
|
192
208
|
o.bool '-E', '--examples', ' show several examples'
|
209
|
+
o.bool '-L', '--language', ' natural language examples'
|
193
210
|
o.bool '-V', '--version', ' print library version'
|
194
211
|
o.bool '-N', '--no-color', ' disable color output'
|
195
212
|
o.bool '-e', '--encrypt', ' encrypt mode'
|
196
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
|
217
|
+
end
|
197
218
|
end
|
198
219
|
rescue StandardError => e
|
199
220
|
raise(e)
|
@@ -9,6 +9,8 @@ module Shhh
|
|
9
9
|
class << self
|
10
10
|
attr_accessor :required, :incompatible
|
11
11
|
|
12
|
+
include Shhh::App::ShortName
|
13
|
+
|
12
14
|
def try_after(*dependencies)
|
13
15
|
Shhh::App::Commands.order(self, dependencies)
|
14
16
|
end
|
@@ -25,10 +27,6 @@ module Shhh
|
|
25
27
|
incompatible
|
26
28
|
end
|
27
29
|
|
28
|
-
def short_name
|
29
|
-
name.split(/::/)[-1].underscore.to_sym
|
30
|
-
end
|
31
|
-
|
32
30
|
def options_satisfied_by?(opts_hash)
|
33
31
|
proc = required_options.find { |option| option.is_a?(Proc) }
|
34
32
|
return true if proc && proc.call(opts_hash)
|
@@ -62,6 +60,10 @@ module Shhh
|
|
62
60
|
raise Shhh::Errors::AbstractMethodCalled.new(:run)
|
63
61
|
end
|
64
62
|
|
63
|
+
def to_s
|
64
|
+
"#{self.class.short_name.to_s.bold.yellow}, with options: #{cli.args.argv.join(' ').gsub(/--/, '').bold.green}"
|
65
|
+
end
|
66
|
+
|
65
67
|
end
|
66
68
|
end
|
67
69
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'colored2'
|
2
|
+
require_relative 'command'
|
3
|
+
require_relative '../nlp'
|
4
|
+
module Shhh
|
5
|
+
module App
|
6
|
+
module Commands
|
7
|
+
class ShowLanguageExamples < Command
|
8
|
+
required_options :language
|
9
|
+
try_after :show_help
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
def run
|
14
|
+
output = []
|
15
|
+
|
16
|
+
output << Shhh::App::NLP::Base.usage
|
17
|
+
|
18
|
+
output << example(comment: 'generate a new private key and copy to the clipboard but do not print to terminal',
|
19
|
+
command: 'shhh create new key to clipboard quietly'
|
20
|
+
)
|
21
|
+
|
22
|
+
output << example(comment: 'generate and save to a file a password-protected key, silently',
|
23
|
+
command: 'shhh create a secure key and save it to "my.key"',
|
24
|
+
)
|
25
|
+
|
26
|
+
output << example(comment: 'encrypt a plain text string with a key, and save the output to a file',
|
27
|
+
command: 'shhh encrypt string "secret string" using $(cat my.key) save to file.enc')
|
28
|
+
|
29
|
+
output << example(comment: 'decrypt a previously encrypted string:',
|
30
|
+
command: 'shhh decrypt string $ENC using $(cat my.key)')
|
31
|
+
|
32
|
+
output << example(comment: 'encrypt "file.txt" with key from my.key and save it to file.enc',
|
33
|
+
command: 'shhh encrypt file file.txt with key from my.key and save it to file.enc')
|
34
|
+
|
35
|
+
output << example(comment: 'decrypt an encrypted file and print it to STDOUT:',
|
36
|
+
command: 'shhh decrypt file file.enc with key from "my.key"')
|
37
|
+
|
38
|
+
output << example(comment: 'edit an encrypted file in $EDITOR, ask for key, and create a backup upon save',
|
39
|
+
command: 'shhh edit file file.enc ask for a key and make a backup',
|
40
|
+
)
|
41
|
+
|
42
|
+
if Shhh::App.is_osx?
|
43
|
+
output << example(comment: 'generate a new password-encrypted key, save it to your Keychain:',
|
44
|
+
command: 'shhh create a new protected key store in keychain "my-keychain-key"')
|
45
|
+
|
46
|
+
output << example(comment: 'print the key stored in the keychain item "my-keychain-key"',
|
47
|
+
command: 'shhh print keychain "my-keychain-key"')
|
48
|
+
|
49
|
+
output << example(comment: 'use the new key to encrypt a file:',
|
50
|
+
command: 'shhh encrypt with keychain "my-keychain-key" file "password.txt" and write to "passwords.enc"')
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
output.flatten.compact.join("\n")
|
55
|
+
end
|
56
|
+
|
57
|
+
def example(comment: nil, command: nil, echo: nil, result: nil)
|
58
|
+
@dict ||= ::Shhh::App::NLP::Constants::DICTIONARY.to_a.flatten!
|
59
|
+
_command = command.split(' ').map do |w|
|
60
|
+
_w = w.to_sym
|
61
|
+
if w == 'shhh'
|
62
|
+
w.italic.yellow
|
63
|
+
elsif ::Shhh::App::NLP::Constants::STRIPPED.include?(_w)
|
64
|
+
w.italic.red
|
65
|
+
elsif @dict.include?(_w)
|
66
|
+
w.blue
|
67
|
+
else
|
68
|
+
w
|
69
|
+
end
|
70
|
+
end.join(' ') if command
|
71
|
+
out = []
|
72
|
+
out << "# #{comment}".white.dark.italic if comment
|
73
|
+
out << "#{_command}" if command
|
74
|
+
out << "#{echo}" if echo
|
75
|
+
out << "#{result}" if result
|
76
|
+
out << (' '*80).dark
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Shhh
|
2
|
+
module App
|
3
|
+
module NLP
|
4
|
+
module Constants
|
5
|
+
STRIPPED = %i(and a the it item to key with about for of new make store in print)
|
6
|
+
|
7
|
+
DICTIONARY = {
|
8
|
+
# option (Slop)
|
9
|
+
# list of english words that map to it
|
10
|
+
:copy => [:clipboard],
|
11
|
+
:decrypt => [:unlock],
|
12
|
+
:edit => [:open],
|
13
|
+
:encrypt => [:lock],
|
14
|
+
:backup => [],
|
15
|
+
:keychain => [],
|
16
|
+
:file => [:read],
|
17
|
+
:generate => [:create],
|
18
|
+
:interactive => [:ask, :enter, :type],
|
19
|
+
:keyfile => [:from],
|
20
|
+
:output => [:save, :write],
|
21
|
+
:private_key => [:using, :private],
|
22
|
+
:string => [:value],
|
23
|
+
:quiet => [:silently, :quietly, :silent, :shhh],
|
24
|
+
:password => [:secure, :secured, :protected]
|
25
|
+
}
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative 'constants'
|
2
|
+
module Shhh
|
3
|
+
module App
|
4
|
+
module NLP
|
5
|
+
class Translator
|
6
|
+
|
7
|
+
attr_accessor :argv, :translated_argv, :opts
|
8
|
+
|
9
|
+
def initialize(argv)
|
10
|
+
self.argv = argv
|
11
|
+
self.opts = CLI.new(%w(-E)).opts.to_hash
|
12
|
+
self.translated_argv = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def dict
|
16
|
+
::Shhh::App::NLP::Constants::DICTIONARY
|
17
|
+
end
|
18
|
+
|
19
|
+
def stripped
|
20
|
+
::Shhh::App::NLP::Constants::STRIPPED
|
21
|
+
end
|
22
|
+
|
23
|
+
def translate
|
24
|
+
self.translated_argv = argv.map do |value|
|
25
|
+
nlp_argument = value.to_sym
|
26
|
+
arg = nil
|
27
|
+
arg ||= dict.keys.find do |key|
|
28
|
+
dict[key].include?(nlp_argument) || key == nlp_argument
|
29
|
+
end
|
30
|
+
arg ||= nlp_argument
|
31
|
+
|
32
|
+
if stripped.include?(arg)
|
33
|
+
# nada
|
34
|
+
elsif opts.to_hash.key?(arg)
|
35
|
+
'--' + "#{arg.to_s.gsub(/_/, '-')}"
|
36
|
+
else
|
37
|
+
arg.to_s
|
38
|
+
end
|
39
|
+
end.compact
|
40
|
+
|
41
|
+
counts = {}
|
42
|
+
translated_argv.each{ |arg| counts.key?(arg) ? counts[arg] += 1 : counts[arg] = 1 }
|
43
|
+
translated_argv.delete_if{ |arg| counts[arg] > 1 }
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def and
|
48
|
+
translate if translated_argv.empty?
|
49
|
+
if self.translated_argv.include?('--verbose')
|
50
|
+
STDERR.puts 'Original arguments: '.dark + "#{argv.join(' ').green}"
|
51
|
+
STDERR.puts ' Translated argv: '.dark + "#{translated_argv.join(' ').blue}"
|
52
|
+
end
|
53
|
+
::Shhh::App::CLI.new(self.translated_argv)
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_method :cli, :and
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'pp'
|
2
|
+
module Shhh
|
3
|
+
module App
|
4
|
+
# shhh generate key to the clipboard and keychain
|
5
|
+
# shhh encrypt file 'hello' using $key [to output.enc]
|
6
|
+
# shhh edit 'passwords.enc' using $key
|
7
|
+
# shhh decrypt /etc/secrets encrypted with $key save to ./secrets
|
8
|
+
# shhh encrypt file $input with keychain $item
|
9
|
+
module NLP
|
10
|
+
module Usage
|
11
|
+
|
12
|
+
def usage
|
13
|
+
out = ''
|
14
|
+
out << %Q`
|
15
|
+
#{header('Natural Language Processing')}
|
16
|
+
|
17
|
+
#{'When '.dark.normal}#{'shhh'.bold.blue} #{'is invoked, and the first argument does not begin with a dash,
|
18
|
+
then the the NLP (natural language processing) Translator is invoked.
|
19
|
+
The Translator is based on a very simple algorithm:
|
20
|
+
|
21
|
+
* ignore any of the words tagged STRIPPED. These are the ambiguous words,
|
22
|
+
or words with duplicate meaning.
|
23
|
+
|
24
|
+
* map the remaining arguments to regular double-dashed options using the DICTIONARY
|
25
|
+
|
26
|
+
* words that are a direct match for a --option are automatically double-dashed
|
27
|
+
|
28
|
+
* remaining words are left as is (these would be file names, key names, etc).
|
29
|
+
|
30
|
+
* finally, the resulting "new" command line is parsed with regular options.
|
31
|
+
|
32
|
+
* When arguments include "verbose", NLP system will print "before" and "after"
|
33
|
+
of the arguments, so that any issues can be debugged and corrected.
|
34
|
+
|
35
|
+
'.dark.normal}
|
36
|
+
|
37
|
+
#{header('Currently ignored words:')}
|
38
|
+
#{Constants::STRIPPED.join(', ').red.italic}
|
39
|
+
|
40
|
+
#{header('Regular Word Mapping')}
|
41
|
+
#{Constants::DICTIONARY.pretty_inspect.split(/\n/).map do |line|
|
42
|
+
line.gsub(
|
43
|
+
/[\:\}\,\[\]]/, ''
|
44
|
+
).gsub(
|
45
|
+
/[ {](\w+)=>([^\n]*)/, '\2|\1'
|
46
|
+
)
|
47
|
+
end.map { |line| convert_dictionary(*line.split('|')) }.join}
|
48
|
+
|
49
|
+
#{header('Examples')}
|
50
|
+
`
|
51
|
+
out
|
52
|
+
end
|
53
|
+
|
54
|
+
def convert_dictionary(left = '', right = '')
|
55
|
+
[
|
56
|
+
sprintf('%35.35s', left.gsub(/ /, ' ')).italic.yellow,
|
57
|
+
' ───────➤ '.dark,
|
58
|
+
sprintf('--%-20.20s', right).blue,
|
59
|
+
|
60
|
+
"\n"
|
61
|
+
].join
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def header(title)
|
66
|
+
title.upcase.bold.underlined
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/shhh/app/nlp.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'cli'
|
2
|
+
require_relative 'nlp/constants'
|
3
|
+
require_relative 'nlp/usage'
|
4
|
+
require_relative 'nlp/translator'
|
5
|
+
module Shhh
|
6
|
+
module App
|
7
|
+
# shhh generate key to the clipboard and keychain
|
8
|
+
# shhh encrypt file 'hello' using $key [to output.enc]
|
9
|
+
# shhh edit 'passwords.enc' using $key
|
10
|
+
# shhh decrypt /etc/secrets encrypted with $key save to ./secrets
|
11
|
+
# shhh encrypt file $input with keychain $item
|
12
|
+
module NLP
|
13
|
+
class Base
|
14
|
+
extend Usage
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'shhh/app/short_name'
|
2
|
+
module Shhh
|
3
|
+
module App
|
4
|
+
module Output
|
5
|
+
class Base
|
6
|
+
|
7
|
+
attr_accessor :cli
|
8
|
+
|
9
|
+
def initialize(cli)
|
10
|
+
self.cli = cli
|
11
|
+
end
|
12
|
+
|
13
|
+
def opts
|
14
|
+
cli.opts
|
15
|
+
end
|
16
|
+
|
17
|
+
@outputs = []
|
18
|
+
class << self
|
19
|
+
attr_accessor :outputs
|
20
|
+
|
21
|
+
def append(output_klass)
|
22
|
+
outputs << output_klass if outputs.is_a?(Array)
|
23
|
+
raise "Cannot append #{output_class} after #outputs has been converted to a Hash" \
|
24
|
+
unless outputs.is_a?(Array)
|
25
|
+
end
|
26
|
+
|
27
|
+
def map_outputs!
|
28
|
+
klasses = self.outputs
|
29
|
+
self.outputs = Hash.new
|
30
|
+
klasses.each { |k| self.outputs[k.required_option] = k }
|
31
|
+
outputs
|
32
|
+
end
|
33
|
+
|
34
|
+
def options_to_outputs
|
35
|
+
map_outputs! if outputs.is_a?(Array)
|
36
|
+
outputs
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.inherited(klass)
|
41
|
+
klass.instance_eval do
|
42
|
+
class << self
|
43
|
+
attr_writer :required_option
|
44
|
+
end
|
45
|
+
|
46
|
+
klass.required_option = nil
|
47
|
+
|
48
|
+
class << self
|
49
|
+
def required_option(_option = nil)
|
50
|
+
self.required_option = _option if _option
|
51
|
+
@required_option
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
klass.extend(Shhh::App::ShortName)
|
56
|
+
Shhh::App::Output::Base.append klass
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/shhh/app/output/file.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
|
+
require 'shhh/app/output/base'
|
1
2
|
module Shhh
|
2
3
|
module App
|
3
4
|
module Output
|
4
|
-
class File
|
5
|
-
attr_accessor :cli
|
5
|
+
class File < ::Shhh::App::Output::Base
|
6
6
|
|
7
|
-
|
8
|
-
self.cli = cli
|
9
|
-
end
|
7
|
+
required_option :output
|
10
8
|
|
11
|
-
def opts
|
12
|
-
cli.opts
|
13
|
-
end
|
14
9
|
|
15
10
|
def output_proc
|
16
11
|
->(data) {
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'shhh/app/output/base'
|
2
|
+
require 'shhh/app/output/file'
|
3
|
+
require 'shhh/app/output/stdout'
|
4
|
+
require 'shhh/app/output/noop'
|
5
|
+
|
6
|
+
module Shhh
|
7
|
+
module App
|
8
|
+
module Output
|
9
|
+
def self.outputs
|
10
|
+
Shhh::App::Output::Base.options_to_outputs
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
data/lib/shhh/app.rb
CHANGED
@@ -27,12 +27,14 @@ module Shhh
|
|
27
27
|
exception: nil,
|
28
28
|
type: nil,
|
29
29
|
details: nil,
|
30
|
-
reason: nil
|
30
|
+
reason: nil,
|
31
|
+
comments: nil)
|
31
32
|
|
32
33
|
self.out.puts([\
|
33
34
|
"#{(type || exception.class.name).titleize}:".red.bold.underlined +
|
34
35
|
(sprintf ' %s', details || exception.message).red.italic,
|
35
|
-
reason ? "\n#{reason.blue.bold.italic}" : nil
|
36
|
+
(reason ? "\n#{reason.blue.bold.italic}" : nil),
|
37
|
+
(comments ? "\n\n#{comments}" : nil)].compact.join("\n"))
|
36
38
|
self.out.puts "\n" + exception.backtrace.join("\n").bold.red if exception && config && config[:trace]
|
37
39
|
self.exit_code = 1
|
38
40
|
end
|
data/lib/shhh/version.rb
CHANGED
data/shhh.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
4
|
require 'shhh/version'
|
5
|
-
|
5
|
+
BASH_COMPLETION = File.read("#{lib}/../bin/shhh.bash-completion")
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'shhh'
|
8
8
|
spec.version = Shhh::VERSION
|
@@ -17,6 +17,17 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.bindir = 'exe'
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ['lib']
|
20
|
+
spec.required_ruby_version = '>= 2.2'
|
21
|
+
spec.post_install_message = "
|
22
|
+
|
23
|
+
Please copy and paste the following BASH function into your ~/.bashrc or
|
24
|
+
equivalent, in order to enable command completion:
|
25
|
+
|
26
|
+
#{BASH_COMPLETION}
|
27
|
+
|
28
|
+
Thank you for installing Shhh!
|
29
|
+
-- KG (github.com/kigster)
|
30
|
+
"
|
20
31
|
|
21
32
|
spec.add_dependency 'require_dir', '~> 0.1'
|
22
33
|
spec.add_dependency 'colored2', '~> 2.0'
|
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.4
|
4
|
+
version: 1.5.4
|
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-
|
11
|
+
date: 2016-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: require_dir
|
@@ -189,6 +189,7 @@ files:
|
|
189
189
|
- Rakefile
|
190
190
|
- bin/console
|
191
191
|
- bin/setup
|
192
|
+
- bin/shhh.bash-completion
|
192
193
|
- exe/keychain
|
193
194
|
- exe/shhh
|
194
195
|
- lib/shhh.rb
|
@@ -204,15 +205,24 @@ files:
|
|
204
205
|
- lib/shhh/app/commands/print_key.rb
|
205
206
|
- lib/shhh/app/commands/show_examples.rb
|
206
207
|
- lib/shhh/app/commands/show_help.rb
|
208
|
+
- lib/shhh/app/commands/show_language_examples.rb
|
207
209
|
- lib/shhh/app/commands/show_version.rb
|
208
210
|
- lib/shhh/app/input/handler.rb
|
209
211
|
- lib/shhh/app/keychain.rb
|
212
|
+
- lib/shhh/app/nlp.rb
|
213
|
+
- lib/shhh/app/nlp/constants.rb
|
214
|
+
- lib/shhh/app/nlp/translator.rb
|
215
|
+
- lib/shhh/app/nlp/usage.rb
|
216
|
+
- lib/shhh/app/output.rb
|
217
|
+
- lib/shhh/app/output/base.rb
|
210
218
|
- lib/shhh/app/output/file.rb
|
219
|
+
- lib/shhh/app/output/noop.rb
|
211
220
|
- lib/shhh/app/output/stdout.rb
|
212
221
|
- lib/shhh/app/private_key/base64_decoder.rb
|
213
222
|
- lib/shhh/app/private_key/decryptor.rb
|
214
223
|
- lib/shhh/app/private_key/detector.rb
|
215
224
|
- lib/shhh/app/private_key/handler.rb
|
225
|
+
- lib/shhh/app/short_name.rb
|
216
226
|
- lib/shhh/cipher_handler.rb
|
217
227
|
- lib/shhh/configuration.rb
|
218
228
|
- lib/shhh/data.rb
|
@@ -227,7 +237,40 @@ files:
|
|
227
237
|
homepage: https://github.com/kigster/shhh
|
228
238
|
licenses: []
|
229
239
|
metadata: {}
|
230
|
-
post_install_message:
|
240
|
+
post_install_message: |2
|
241
|
+
|
242
|
+
|
243
|
+
Please copy and paste the following BASH function into your ~/.bashrc or
|
244
|
+
equivalent, in order to enable command completion:
|
245
|
+
|
246
|
+
#!/usr/bin/env bash
|
247
|
+
#
|
248
|
+
# Shhh command line completion
|
249
|
+
#
|
250
|
+
# © 2015-2016, Konstantin Gredeskoul, https://github.com/kigster/shhh
|
251
|
+
# MIT LICENSE
|
252
|
+
#
|
253
|
+
|
254
|
+
_shhh() {
|
255
|
+
local SHHH_OPTS SHHH_POINTS cur prev
|
256
|
+
|
257
|
+
cur="${COMP_WORDS[COMP_CWORD]}"
|
258
|
+
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
259
|
+
|
260
|
+
COMPREPLY=()
|
261
|
+
|
262
|
+
SHHH_COMP_OPTIONS=$(shhh --dictionary)
|
263
|
+
[[ $COMP_CWORD == 1 ]] && SHHH_COMP_OPTIONS="${SHHH_COMP_OPTIONS} ${SHHH_COMMANDS}"
|
264
|
+
COMPREPLY=( $(compgen -W "${SHHH_COMP_OPTIONS}" -- ${cur}) )
|
265
|
+
return 0
|
266
|
+
}
|
267
|
+
|
268
|
+
complete -F _shhh shhh
|
269
|
+
|
270
|
+
|
271
|
+
|
272
|
+
Thank you for installing Shhh!
|
273
|
+
-- KG (github.com/kigster)
|
231
274
|
rdoc_options: []
|
232
275
|
require_paths:
|
233
276
|
- lib
|
@@ -235,7 +278,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
235
278
|
requirements:
|
236
279
|
- - ">="
|
237
280
|
- !ruby/object:Gem::Version
|
238
|
-
version: '
|
281
|
+
version: '2.2'
|
239
282
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
240
283
|
requirements:
|
241
284
|
- - ">="
|
@@ -243,7 +286,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
286
|
version: '0'
|
244
287
|
requirements: []
|
245
288
|
rubyforge_project:
|
246
|
-
rubygems_version: 2.
|
289
|
+
rubygems_version: 2.5.1
|
247
290
|
signing_key:
|
248
291
|
specification_version: 4
|
249
292
|
summary: Simple tool to encrypt/decrypt data using symmetric aes-256-cbc encryption
|