shhh 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|