shhh 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.codeclimate.yml +25 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +13 -0
- data/Gemfile +6 -0
- data/LICENSE +22 -0
- data/MANAGING-KEYS.md +67 -0
- data/README.md +328 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/keychain +38 -0
- data/exe/shhh +8 -0
- data/lib/shhh/app/args.rb +17 -0
- data/lib/shhh/app/cli.rb +150 -0
- data/lib/shhh/app/commands/command.rb +68 -0
- data/lib/shhh/app/commands/delete_keychain_item.rb +17 -0
- data/lib/shhh/app/commands/encrypt_decrypt.rb +26 -0
- data/lib/shhh/app/commands/generate_key.rb +41 -0
- data/lib/shhh/app/commands/open_editor.rb +96 -0
- data/lib/shhh/app/commands/print_key.rb +18 -0
- data/lib/shhh/app/commands/show_examples.rb +64 -0
- data/lib/shhh/app/commands/show_help.rb +16 -0
- data/lib/shhh/app/commands/show_version.rb +14 -0
- data/lib/shhh/app/commands.rb +55 -0
- data/lib/shhh/app/input/handler.rb +35 -0
- data/lib/shhh/app/keychain.rb +135 -0
- data/lib/shhh/app/output/file.rb +23 -0
- data/lib/shhh/app/output/stdout.rb +11 -0
- data/lib/shhh/app/private_key/base64_decoder.rb +17 -0
- data/lib/shhh/app/private_key/decryptor.rb +50 -0
- data/lib/shhh/app/private_key/detector.rb +34 -0
- data/lib/shhh/app/private_key/handler.rb +34 -0
- data/lib/shhh/app.rb +45 -0
- data/lib/shhh/cipher_handler.rb +45 -0
- data/lib/shhh/configuration.rb +23 -0
- data/lib/shhh/data/decoder.rb +28 -0
- data/lib/shhh/data/encoder.rb +24 -0
- data/lib/shhh/data/wrapper_struct.rb +43 -0
- data/lib/shhh/data.rb +23 -0
- data/lib/shhh/errors.rb +27 -0
- data/lib/shhh/extensions/class_methods.rb +12 -0
- data/lib/shhh/extensions/instance_methods.rb +114 -0
- data/lib/shhh/version.rb +3 -0
- data/lib/shhh.rb +73 -0
- data/shhh.gemspec +33 -0
- metadata +249 -0
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'shhh'
|
2
|
+
require 'shhh/app'
|
3
|
+
require 'shhh/errors'
|
4
|
+
|
5
|
+
|
6
|
+
module Shhh
|
7
|
+
module App
|
8
|
+
#
|
9
|
+
# This class forms and shells several commands that wrap Mac OS-X +security+ command.
|
10
|
+
# They provide access to storing generic passwords in the KeyChain Access.
|
11
|
+
#
|
12
|
+
class KeyChain
|
13
|
+
class << self
|
14
|
+
attr_accessor :user, :kind, :sub_section
|
15
|
+
|
16
|
+
def configure
|
17
|
+
yield self
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate!
|
21
|
+
raise ArgumentError.new(
|
22
|
+
'User is not defined. Either set $USER in environment, or directly on the class.') unless self.user
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
configure do
|
27
|
+
self.kind = 'shhh'
|
28
|
+
self.user = ENV['USER']
|
29
|
+
self.sub_section = 'generic-password'
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_accessor :key_name, :opts, :stderr_disabled
|
33
|
+
|
34
|
+
def initialize(key_name, opts = {})
|
35
|
+
self.key_name = key_name
|
36
|
+
self.opts = opts
|
37
|
+
self.class.validate!
|
38
|
+
end
|
39
|
+
|
40
|
+
def add(password)
|
41
|
+
execute command(:add, "-U -w '#{password}' ")
|
42
|
+
end
|
43
|
+
|
44
|
+
def find
|
45
|
+
execute command(:find, ' -g -w ')
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete
|
49
|
+
execute command(:delete)
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute(command)
|
53
|
+
command += ' 2>/dev/null' if stderr_disabled
|
54
|
+
puts "> #{command.yellow.green}" if opts[:verbose]
|
55
|
+
output = `#{command}`
|
56
|
+
result = $?
|
57
|
+
raise Shhh::Errors::ExternalCommandError.new("Command error: #{result}, command: #{command}") unless result.success?
|
58
|
+
output.chomp
|
59
|
+
rescue Errno::ENOENT => e
|
60
|
+
raise Shhh::Errors::ExternalCommandError.new("Command error: #{e.message}, command: #{command}")
|
61
|
+
end
|
62
|
+
|
63
|
+
def stderr_off
|
64
|
+
self.stderr_disabled = true
|
65
|
+
end
|
66
|
+
|
67
|
+
def stderr_on
|
68
|
+
self.stderr_disabled = false
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def command(action, extras = nil)
|
74
|
+
out = base_command(action)
|
75
|
+
out << extras if extras
|
76
|
+
out = out.join
|
77
|
+
# Do not actually ever run these commands on non MacOSX
|
78
|
+
out = "echo Run this –\"#{out}\", on #{Shhh::App.this_os}?\nAre you sure?" unless Shhh::App.is_osx?
|
79
|
+
out
|
80
|
+
end
|
81
|
+
|
82
|
+
def base_command(action)
|
83
|
+
[
|
84
|
+
"security #{action}-#{self.class.sub_section} ",
|
85
|
+
"-a '#{self.class.user}' ",
|
86
|
+
"-D '#{self.class.kind}' ",
|
87
|
+
"-s '#{self.key_name}' "
|
88
|
+
]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
#
|
96
|
+
# Usage: add-generic-password [-a account] [-s service] [-w password] [options...] [-A|-T appPath] [keychain]
|
97
|
+
# -a Specify account name (required)
|
98
|
+
# -c Specify item creator (optional four-character code)
|
99
|
+
# -C Specify item type (optional four-character code)
|
100
|
+
# -D Specify kind (default is "application password")
|
101
|
+
# -G Specify generic attribute (optional)
|
102
|
+
# -j Specify comment string (optional)
|
103
|
+
# -l Specify label (if omitted, service name is used as default label)
|
104
|
+
# -s Specify service name (required)
|
105
|
+
# -p Specify password to be added (legacy option, equivalent to -w)
|
106
|
+
# -w Specify password to be added
|
107
|
+
# -A Allow any application to access this item without warning (insecure, not recommended!)
|
108
|
+
# -T Specify an application which may access this item (multiple -T options are allowed)
|
109
|
+
# -U Update item if it already exists (if omitted, the item cannot already exist)
|
110
|
+
#
|
111
|
+
# Usage: find-generic-password [-a account] [-s service] [options...] [-g] [keychain...]
|
112
|
+
# -a Match "account" string
|
113
|
+
# -c Match "creator" (four-character code)
|
114
|
+
# -C Match "type" (four-character code)
|
115
|
+
# -D Match "kind" string
|
116
|
+
# -G Match "value" string (generic attribute)
|
117
|
+
# -j Match "comment" string
|
118
|
+
# -l Match "label" string
|
119
|
+
# -s Match "service" string
|
120
|
+
# -g Display the password for the item found
|
121
|
+
# -w Display only the password on stdout
|
122
|
+
# If no keychains are specified to search, the default search list is used.
|
123
|
+
# Find a generic password item.
|
124
|
+
#
|
125
|
+
# Usage: delete-generic-password [-a account] [-s service] [options...] [keychain...]
|
126
|
+
# -a Match "account" string
|
127
|
+
# -c Match "creator" (four-character code)
|
128
|
+
# -C Match "type" (four-character code)
|
129
|
+
# -D Match "kind" string
|
130
|
+
# -G Match "value" string (generic attribute)
|
131
|
+
# -j Match "comment" string
|
132
|
+
# -l Match "label" string
|
133
|
+
# -s Match "service" string
|
134
|
+
# If no keychains are specified to search, the default search list is used.
|
135
|
+
# Delete a generic password item.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Shhh
|
2
|
+
module App
|
3
|
+
module Output
|
4
|
+
class File
|
5
|
+
attr_accessor :cli
|
6
|
+
|
7
|
+
def initialize(cli)
|
8
|
+
self.cli = cli
|
9
|
+
end
|
10
|
+
|
11
|
+
def opts
|
12
|
+
cli.opts
|
13
|
+
end
|
14
|
+
|
15
|
+
def output_proc
|
16
|
+
->(data) {
|
17
|
+
::File.open(opts[:output], 'w') { |f| f.write(data) }
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Shhh
|
2
|
+
module App
|
3
|
+
module PrivateKey
|
4
|
+
class Base64Decoder < Struct.new(:encoded_key)
|
5
|
+
|
6
|
+
def key
|
7
|
+
return nil if encoded_key.nil?
|
8
|
+
begin
|
9
|
+
Base64.urlsafe_decode64(encoded_key)
|
10
|
+
rescue ArgumentError
|
11
|
+
encoded_key
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative 'decryptor'
|
2
|
+
module Shhh
|
3
|
+
module App
|
4
|
+
module PrivateKey
|
5
|
+
class Decryptor
|
6
|
+
include Shhh
|
7
|
+
|
8
|
+
attr_accessor :encrypted_key, :input_handler
|
9
|
+
|
10
|
+
def initialize(encrypted_key, input_handler = Shhh::App::Input::Handler)
|
11
|
+
self.encrypted_key = encrypted_key
|
12
|
+
self.input_handler = input_handler
|
13
|
+
end
|
14
|
+
|
15
|
+
def key
|
16
|
+
return nil if encrypted_key.nil?
|
17
|
+
decrypted_key = nil
|
18
|
+
if should_decrypt?
|
19
|
+
begin
|
20
|
+
retries ||= 0
|
21
|
+
decrypted_key = decrypt(password)
|
22
|
+
rescue ::OpenSSL::Cipher::CipherError => e
|
23
|
+
STDERR.puts 'Invalid password. Please try again.'
|
24
|
+
((retries += 1) < 3) ? retry : raise(Shhh::Errors::InvalidPasswordPrivateKey.new(e))
|
25
|
+
end
|
26
|
+
else
|
27
|
+
decrypted_key = encrypted_key
|
28
|
+
end
|
29
|
+
decrypted_key
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def should_decrypt?
|
35
|
+
encrypted_key && (encrypted_key.length > 32)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def decrypt(password)
|
40
|
+
decr_password(encrypted_key, password)
|
41
|
+
end
|
42
|
+
|
43
|
+
def password
|
44
|
+
input_handler.ask
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Shhh
|
2
|
+
module App
|
3
|
+
module PrivateKey
|
4
|
+
class Detector < Struct.new(:opts) # :nodoc:
|
5
|
+
@mapping = Hash.new
|
6
|
+
class << self
|
7
|
+
attr_reader :mapping
|
8
|
+
|
9
|
+
def register(argument, proc)
|
10
|
+
self.mapping[argument] = proc
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def key
|
15
|
+
self.class.mapping.each_pair do |options_key, key_proc|
|
16
|
+
return key_proc.call(self.opts[options_key]) if self.opts[options_key]
|
17
|
+
end
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Detector.register :private_key, ->(key) { key }
|
23
|
+
Detector.register :interactive, -> { Input::Handler.prompt('Private Key: ', :magenta) }
|
24
|
+
Detector.register :keychain, ->(key_name) { KeyChain.new(key_name).find }
|
25
|
+
Detector.register :keyfile, ->(file) {
|
26
|
+
begin
|
27
|
+
::File.read(file)
|
28
|
+
rescue Errno::ENOENT
|
29
|
+
raise Shhh::Errors::FileNotFound.new("Encryption key file #{file} was not found.")
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'detector'
|
2
|
+
require_relative 'base64_decoder'
|
3
|
+
require_relative 'decryptor'
|
4
|
+
module Shhh
|
5
|
+
module App
|
6
|
+
module PrivateKey
|
7
|
+
# This class figures out what is the private key that is
|
8
|
+
# provided to be used.
|
9
|
+
class Handler
|
10
|
+
include Shhh
|
11
|
+
|
12
|
+
attr_accessor :opts, :key
|
13
|
+
|
14
|
+
def initialize(opts)
|
15
|
+
self.opts = opts
|
16
|
+
|
17
|
+
|
18
|
+
self.key =
|
19
|
+
begin
|
20
|
+
Detector.new(opts).key
|
21
|
+
rescue Shhh::Errors::Error => e
|
22
|
+
if Shhh::App::Args.new(opts).key? && key.nil?
|
23
|
+
raise e
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if key && key.length > 45
|
28
|
+
self.key = Decryptor.new(Base64Decoder.new(key).key).key
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/shhh/app.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'shhh/data'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
module Shhh
|
4
|
+
# The +App+ Module is responsible for handing user input and executing commands.
|
5
|
+
# Central class in this module is the +CLI+ class.
|
6
|
+
|
7
|
+
# This module is responsible for printing pretty errors and maintaining the
|
8
|
+
# future exit code class-global variable.
|
9
|
+
|
10
|
+
module App
|
11
|
+
class << self
|
12
|
+
attr_accessor :exit_code
|
13
|
+
end
|
14
|
+
|
15
|
+
self.exit_code = 0
|
16
|
+
|
17
|
+
def self.out
|
18
|
+
STDERR
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.error(
|
22
|
+
config: {},
|
23
|
+
exception: nil,
|
24
|
+
type: nil,
|
25
|
+
details: nil,
|
26
|
+
reason: nil)
|
27
|
+
|
28
|
+
self.out.puts([\
|
29
|
+
"#{(type || exception.class.name).titleize}:".red.bold.underlined +
|
30
|
+
(sprintf ' %s', details || exception.message).red.italic,
|
31
|
+
reason ? "\n#{reason.blue.bold.italic}" : nil].compact.join("\n"))
|
32
|
+
self.out.puts "\n" + exception.backtrace.join("\n").bold.red if exception && config && config[:trace]
|
33
|
+
self.exit_code = 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.is_osx?
|
37
|
+
Gem::Platform.local.os.eql?('darwin')
|
38
|
+
end
|
39
|
+
def self.this_os
|
40
|
+
Gem::Platform.local.os
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Shhh.dir_r 'shhh/app'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require_relative 'configuration'
|
3
|
+
|
4
|
+
module Shhh
|
5
|
+
#
|
6
|
+
# +CipherHandler+ contains cipher-related utilities necessary to create
|
7
|
+
# ciphers, and seed them with the salt or iV vector,
|
8
|
+
#
|
9
|
+
module CipherHandler
|
10
|
+
|
11
|
+
CREATE_CIPHER = ->(name) { ::OpenSSL::Cipher.new(name) }
|
12
|
+
|
13
|
+
CipherStruct = Struct.new(:cipher, :iv, :salt)
|
14
|
+
|
15
|
+
def create_cipher(direction:,
|
16
|
+
cipher_name:,
|
17
|
+
iv: nil,
|
18
|
+
salt: nil)
|
19
|
+
|
20
|
+
cipher = new_cipher(cipher_name)
|
21
|
+
cipher.send(direction)
|
22
|
+
iv ||= cipher.random_iv
|
23
|
+
cipher.iv = iv
|
24
|
+
CipherStruct.new(cipher, iv, salt)
|
25
|
+
end
|
26
|
+
|
27
|
+
def new_cipher(cipher_name)
|
28
|
+
CREATE_CIPHER.call(cipher_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def update_cipher(cipher, value)
|
32
|
+
data = cipher.update(value)
|
33
|
+
data << cipher.final
|
34
|
+
data
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def create_private_key
|
39
|
+
key = CREATE_CIPHER.call(Shhh::Configuration.property(:private_key_cipher)).random_key
|
40
|
+
::Base64.urlsafe_encode64(key)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Shhh
|
2
|
+
# Application configuration Singleton class.
|
3
|
+
# It's values are requested by the library upon encryption or
|
4
|
+
# decryption, or any other operation.
|
5
|
+
|
6
|
+
class Configuration
|
7
|
+
class << self
|
8
|
+
attr_accessor :config
|
9
|
+
|
10
|
+
def configure
|
11
|
+
self.config ||= Configuration.new
|
12
|
+
yield config if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def property(name)
|
16
|
+
self.config.send(name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :data_cipher, :password_cipher, :private_key_cipher
|
21
|
+
attr_accessor :compression_enabled, :compression_level
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative '../errors'
|
2
|
+
require 'base64'
|
3
|
+
require 'zlib'
|
4
|
+
module Shhh
|
5
|
+
module Data
|
6
|
+
class Decoder
|
7
|
+
attr_accessor :data, :data_encoded, :data
|
8
|
+
|
9
|
+
def initialize(data_encoded, compress)
|
10
|
+
self.data_encoded = data_encoded
|
11
|
+
self.data = begin
|
12
|
+
Base64.urlsafe_decode64(data_encoded)
|
13
|
+
rescue
|
14
|
+
data_encoded
|
15
|
+
end
|
16
|
+
|
17
|
+
if compress.nil? || compress # auto-guess
|
18
|
+
self.data = begin
|
19
|
+
Zlib::Inflate.inflate(data)
|
20
|
+
rescue Zlib::Error => e
|
21
|
+
data
|
22
|
+
end
|
23
|
+
end
|
24
|
+
self.data = Marshal.load(data)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'zlib'
|
3
|
+
|
4
|
+
require 'shhh/errors'
|
5
|
+
require 'shhh/configuration'
|
6
|
+
|
7
|
+
module Shhh
|
8
|
+
module Data
|
9
|
+
class Encoder
|
10
|
+
attr_accessor :data, :data_encoded
|
11
|
+
|
12
|
+
def initialize(data, compress)
|
13
|
+
self.data = data
|
14
|
+
self.data_encoded = Marshal.dump(data)
|
15
|
+
self.data_encoded = Zlib::Deflate.deflate(data_encoded, compression_level) if compress
|
16
|
+
self.data_encoded = Base64.urlsafe_encode64(data_encoded)
|
17
|
+
end
|
18
|
+
|
19
|
+
def compression_level
|
20
|
+
Shhh::Configuration.config.compression_level
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../errors'
|
2
|
+
module Shhh
|
3
|
+
module Data
|
4
|
+
class WrapperStruct < Struct.new(
|
5
|
+
:encrypted_data, # [Blob] Binary encrypted data (possibly compressed)
|
6
|
+
:iv, # [String] IV used to encrypt the data
|
7
|
+
:cipher_name, # [String] Name of the cipher used
|
8
|
+
:salt, # [Integer] For password-encrypted data this is the salt
|
9
|
+
:version, # [Integer] Version of the cipher used
|
10
|
+
:compress # [Boolean] indicates if compression should be applied
|
11
|
+
)
|
12
|
+
|
13
|
+
VERSION = 1
|
14
|
+
|
15
|
+
attr_accessor :compressed
|
16
|
+
|
17
|
+
def initialize(
|
18
|
+
encrypted_data:, # [Blob] Binary encrypted data (possibly compressed)
|
19
|
+
iv:, # [String] IV used to encrypt the data
|
20
|
+
cipher_name:, # [String] Name of the cipher used
|
21
|
+
salt: nil, # [Integer] For password-encrypted data this is the salt
|
22
|
+
version: VERSION, # [Integer] Version of the cipher used
|
23
|
+
compress: Shhh::Configuration.config.compression_enabled
|
24
|
+
)
|
25
|
+
super(encrypted_data, iv, cipher_name, salt, version, compress)
|
26
|
+
end
|
27
|
+
|
28
|
+
def config
|
29
|
+
Shhh::Configuration.config
|
30
|
+
end
|
31
|
+
|
32
|
+
def serialize
|
33
|
+
Marshal.dump(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.deserialize(data)
|
37
|
+
Marshal.load(data)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
data/lib/shhh/data.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'errors'
|
2
|
+
require 'base64'
|
3
|
+
require 'zlib'
|
4
|
+
|
5
|
+
require_relative 'data/wrapper_struct'
|
6
|
+
require_relative 'data/encoder'
|
7
|
+
require_relative 'data/decoder'
|
8
|
+
|
9
|
+
module Shhh
|
10
|
+
# This module is responsible for taking arbitrary data of any format, and safely compressing
|
11
|
+
# the result of `Marshal.dump(data)` using Zlib, and then doing `#urlsafe_encode64` encoding
|
12
|
+
# to convert it to a string,
|
13
|
+
module Data
|
14
|
+
def encode(data, compress = true)
|
15
|
+
Encoder.new(data, compress).data_encoded
|
16
|
+
end
|
17
|
+
|
18
|
+
def decode(data_encoded, compress = nil)
|
19
|
+
Decoder.new(data_encoded, compress).data
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
data/lib/shhh/errors.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Shhh
|
2
|
+
module Errors
|
3
|
+
# Exceptions superclass for this library.
|
4
|
+
class Shhh::Errors::Error < StandardError; end
|
5
|
+
|
6
|
+
# No secret has been provided for encryption or decryption
|
7
|
+
class NoPrivateKeyFound < Shhh::Errors::Error; end
|
8
|
+
class PasswordsDontMatch < Shhh::Errors::Error; end
|
9
|
+
class PasswordTooShort < Shhh::Errors::Error; end
|
10
|
+
class DataEncodingVersionMismatch< Shhh::Errors::Error; end
|
11
|
+
class EditorExitedAbnormally < Shhh::Errors::Error; end
|
12
|
+
class InvalidEncodingPrivateKey < Shhh::Errors::Error; end
|
13
|
+
class InvalidPasswordPrivateKey < Shhh::Errors::Error; end
|
14
|
+
class FileNotFound < Shhh::Errors::Error; end
|
15
|
+
class ExternalCommandError < Shhh::Errors::Error; end
|
16
|
+
|
17
|
+
# Method was called on an abstract class. Override such methods in
|
18
|
+
# subclasses, and use subclasses for instantiation of objects.
|
19
|
+
class AbstractMethodCalled < ArgumentError
|
20
|
+
def initialize(method, message = nil)
|
21
|
+
super("Abstract method call, on #{method}" + (message || ''))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|