clandestine 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -9
- data/.rspec +2 -0
- data/README.md +30 -18
- data/Rakefile +0 -24
- data/bin/clandestine +1 -1
- data/clandestine.gemspec +3 -1
- data/lib/clandestine.rb +1 -9
- data/lib/clandestine/clandestine_error.rb +4 -0
- data/lib/clandestine/command_line_options.rb +52 -0
- data/lib/clandestine/command_line_runner.rb +86 -0
- data/lib/clandestine/commands.rb +52 -0
- data/lib/clandestine/commands/add.rb +29 -0
- data/lib/clandestine/commands/delete.rb +25 -0
- data/lib/clandestine/commands/get.rb +37 -0
- data/lib/clandestine/commands/remove_safe.rb +18 -0
- data/lib/clandestine/commands/update.rb +32 -0
- data/lib/clandestine/crypt.rb +44 -21
- data/lib/clandestine/io.rb +32 -0
- data/lib/clandestine/password_generator.rb +18 -0
- data/lib/clandestine/safe.rb +71 -44
- data/lib/clandestine/safe_authentication.rb +18 -0
- data/lib/clandestine/safe_location.rb +3 -0
- data/lib/clandestine/version.rb +1 -1
- data/spec/commands_spec.rb +98 -0
- data/spec/crypt_spec.rb +20 -5
- data/spec/safe_authentication_spec.rb +30 -0
- data/spec/spec_helper.rb +0 -8
- metadata +50 -12
- data/lib/clandestine/config.rb +0 -25
- data/lib/clandestine/guard.rb +0 -217
- data/spec/config_spec.rb +0 -47
- data/spec/guard_spec.rb +0 -127
- data/spec/safe_spec.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28199bdaabcdce860096d540533772d884633985
|
4
|
+
data.tar.gz: d50ae77ce56c28705d610713563a04a6a0a64418
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e735a21d659094d197fc01ef14dab5be103bea886b9c6ee5cd94eb56514f75fe995c1c1f279aa1e986c43e98425ea92daea992beacc9dae54fa41668bc951672
|
7
|
+
data.tar.gz: 24d36dede0d1e12f9c872743f746ce95d1a4b0e29299fffae3e29297ade654c7fbc45cf97a10b1fa0c5bc6f4ea56b3f34e7a60862773fad6da1096cd657c8b81
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/README.md
CHANGED
@@ -1,32 +1,44 @@
|
|
1
|
-
|
1
|
+
Clandestine
|
2
|
+
-----------
|
2
3
|
|
3
4
|
Clandestine allows you to store passwords in a local file using AES-CBC-256 encryption.
|
4
5
|
|
5
|
-
|
6
|
+
Requirements
|
7
|
+
------------
|
6
8
|
|
7
|
-
Ruby
|
9
|
+
Ruby v2.0+
|
8
10
|
|
9
11
|
Currently only supported on OSX
|
10
12
|
|
11
|
-
|
13
|
+
Installation
|
14
|
+
------------
|
12
15
|
|
13
16
|
Clandestine can be installed using RubyGems:
|
14
17
|
|
15
18
|
$ gem install clandestine
|
16
19
|
|
17
|
-
|
20
|
+
Usage
|
21
|
+
-----
|
18
22
|
|
19
23
|
user$ clandestine
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
-
|
24
|
-
-g
|
25
|
-
-d <key>
|
26
|
-
-
|
27
|
-
-l
|
28
|
-
-
|
29
|
-
-
|
30
|
-
-
|
31
|
-
|
32
|
-
|
24
|
+
Clandestine v0.1.0
|
25
|
+
Usage: clandestine [option] [key]
|
26
|
+
|
27
|
+
-a, --add <key> Add password for <key> (Passwords are randomly generated)
|
28
|
+
-g, --get [key] Get password for [key] (Returns all keys if key isn't given)
|
29
|
+
-d, --delete <key> Delete <key> and related password
|
30
|
+
-u, --update [key] Update password for [key] (Updates password for safe if key isn't given)
|
31
|
+
-l, --location Print location of safe (Default is ~/.cls if env variable CLANDESTINE_SAFE isn't set)
|
32
|
+
-r, --remove Remove safe completely
|
33
|
+
-v, --version Print version number
|
34
|
+
-h, --help Print these options
|
35
|
+
|
36
|
+
|
37
|
+
Contributing
|
38
|
+
------------
|
39
|
+
1. Fork it
|
40
|
+
2. Create your feature branch (git checkout -b my-new-feature)
|
41
|
+
3. Write specs (bundle exec rspec spec)
|
42
|
+
4. Commit your changes (git commit -am 'Add some feature')
|
43
|
+
5. Push to the branch (git push origin my-new-feature)
|
44
|
+
6. Create new Pull Request
|
data/Rakefile
CHANGED
@@ -1,25 +1 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
require "bundler/gem_tasks"
|
3
|
-
require 'rspec/core/rake_task'
|
4
|
-
|
5
|
-
namespace :spec do
|
6
|
-
desc 'Run specs for Crypt'
|
7
|
-
RSpec::Core::RakeTask.new :crypt do |t|
|
8
|
-
t.pattern = 'spec/crypt_spec.rb'
|
9
|
-
end
|
10
|
-
desc 'Run specs for Safe'
|
11
|
-
RSpec::Core::RakeTask.new :safe do |t|
|
12
|
-
t.pattern = 'spec/safe_spec.rb'
|
13
|
-
end
|
14
|
-
desc 'Run specs for Guard'
|
15
|
-
RSpec::Core::RakeTask.new :guard do |t|
|
16
|
-
t.pattern = 'spec/guard_spec.rb'
|
17
|
-
end
|
18
|
-
desc 'Rub specs for Config'
|
19
|
-
RSpec::Core::RakeTask.new :config do |t|
|
20
|
-
t.pattern = 'spec/config_spec.rb'
|
21
|
-
end
|
22
|
-
task :all => [:safe, :guard, :crypt, :config]
|
23
|
-
end
|
24
|
-
|
25
|
-
task :default => 'spec:all'
|
data/bin/clandestine
CHANGED
data/clandestine.gemspec
CHANGED
@@ -15,5 +15,7 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
16
|
gem.require_paths = ["lib"]
|
17
17
|
gem.add_dependency 'highline'
|
18
|
-
gem.
|
18
|
+
gem.add_dependency 'json'
|
19
|
+
gem.add_dependency 'bcrypt-ruby'
|
20
|
+
gem.add_development_dependency 'rspec', '~> 2'
|
19
21
|
end
|
data/lib/clandestine.rb
CHANGED
@@ -1,9 +1 @@
|
|
1
|
-
|
2
|
-
require 'base64'
|
3
|
-
require 'digest/sha2'
|
4
|
-
require 'fileutils'
|
5
|
-
require 'clandestine/version'
|
6
|
-
require 'clandestine/crypt'
|
7
|
-
require 'clandestine/config'
|
8
|
-
require 'clandestine/safe'
|
9
|
-
require 'clandestine/guard'
|
1
|
+
require_relative 'clandestine/command_line_runner'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Clandestine
|
2
|
+
class CommandLineOptions
|
3
|
+
|
4
|
+
attr_reader :parser
|
5
|
+
attr_accessor :options
|
6
|
+
private :options
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@options = {}
|
10
|
+
@parser = OptionParser.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse
|
14
|
+
parser.banner = "Clandestine v#{Clandestine::VERSION}\nUsage: clandestine [option] [key]\n\n"
|
15
|
+
|
16
|
+
parser.on('-a', '--add <key>', 'Add password for <key>') do |key|
|
17
|
+
options[:add] = key
|
18
|
+
end
|
19
|
+
|
20
|
+
parser.on('-g', '--get [key]', 'Get password for [key] (Returns all keys if key isn\'t given)') do |key|
|
21
|
+
options[:get] = key
|
22
|
+
end
|
23
|
+
|
24
|
+
parser.on('-d', '--delete <key>', 'Delete <key> and related password') do |key|
|
25
|
+
options[:delete] = key
|
26
|
+
end
|
27
|
+
|
28
|
+
parser.on('-u', '--update [key]', 'Update password for [key] (Updates password for safe if key isn\'t given)') do |key|
|
29
|
+
options[:update] = key
|
30
|
+
end
|
31
|
+
|
32
|
+
parser.on '-l', '--location', 'Print location of safe (Default is ~/.cls if env variable CLANDESTINE_SAFE isn\'t set)' do
|
33
|
+
options[:location] = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
parser.on '-r', '--remove', 'Remove safe completely' do
|
37
|
+
options[:remove] = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
parser.on '-v', '--version', 'Print version number' do |h|
|
41
|
+
options[:version] = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
parser.on_tail '-h', '--help', 'Print these options' do |h|
|
45
|
+
options[:help] = parser
|
46
|
+
end
|
47
|
+
|
48
|
+
parser.parse!
|
49
|
+
options
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require_relative 'command_line_options'
|
3
|
+
require_relative 'commands'
|
4
|
+
require_relative 'version'
|
5
|
+
require_relative 'clandestine_error'
|
6
|
+
require_relative 'io'
|
7
|
+
|
8
|
+
module Clandestine
|
9
|
+
|
10
|
+
class CommandLineRunner
|
11
|
+
|
12
|
+
def self.run
|
13
|
+
clo = CommandLineOptions.new
|
14
|
+
options = clo.parse
|
15
|
+
|
16
|
+
command = options.keys.first
|
17
|
+
value = options[command]
|
18
|
+
|
19
|
+
case command
|
20
|
+
when :add
|
21
|
+
output = run_command(command, value)
|
22
|
+
if output
|
23
|
+
puts "Successfully added password for #{value}"
|
24
|
+
else
|
25
|
+
puts "Password already exists for #{value}"
|
26
|
+
end
|
27
|
+
when :get
|
28
|
+
output = run_command(command, value)
|
29
|
+
if value && !output.is_a?(Array)
|
30
|
+
IO.copy_to_clipboard(output)
|
31
|
+
else
|
32
|
+
IO.print_keys(output)
|
33
|
+
end
|
34
|
+
when :update
|
35
|
+
output = run_command(command, value)
|
36
|
+
if output
|
37
|
+
if value
|
38
|
+
puts "Password for #{value} has been updated"
|
39
|
+
else
|
40
|
+
puts "Password for safe has been updated"
|
41
|
+
end
|
42
|
+
else
|
43
|
+
if value
|
44
|
+
puts "#{value} does not exist"
|
45
|
+
else
|
46
|
+
puts "Failed to update safe password"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
when :delete
|
50
|
+
if run_command(command, value)
|
51
|
+
puts "#{value} has been deleted"
|
52
|
+
else
|
53
|
+
puts "#{value} does not exist"
|
54
|
+
end
|
55
|
+
when :remove
|
56
|
+
if run_command(command, value)
|
57
|
+
puts "Safe has been successfully removed"
|
58
|
+
else
|
59
|
+
puts "Failed to remve safe"
|
60
|
+
end
|
61
|
+
when :version
|
62
|
+
puts Commands.version
|
63
|
+
when :location
|
64
|
+
puts Commands.location
|
65
|
+
when :help
|
66
|
+
puts clo.parser.on_tail
|
67
|
+
else
|
68
|
+
puts clo.parser.on_tail
|
69
|
+
end
|
70
|
+
puts
|
71
|
+
rescue OptionParser::MissingArgument, OptionParser::InvalidOption
|
72
|
+
puts clo.parser.on_tail
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.run_command(command, value)
|
76
|
+
if command
|
77
|
+
if value
|
78
|
+
Commands.send(command, value)
|
79
|
+
else
|
80
|
+
Commands.send(command, nil)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
require_relative 'clandestine_error'
|
3
|
+
require_relative 'io'
|
4
|
+
require_relative 'safe_location'
|
5
|
+
require_relative 'commands/add'
|
6
|
+
require_relative 'commands/update'
|
7
|
+
require_relative 'commands/get'
|
8
|
+
require_relative 'commands/delete'
|
9
|
+
require_relative 'commands/remove_safe'
|
10
|
+
|
11
|
+
module Clandestine
|
12
|
+
module Commands
|
13
|
+
def self.add(key, password = nil)
|
14
|
+
password = IO.get_password unless password
|
15
|
+
Add.new(password, key).add
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.get(key = nil, password = nil)
|
19
|
+
if key && password.nil?
|
20
|
+
password = IO.get_password
|
21
|
+
end
|
22
|
+
Get.new(password, key).get
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.delete(key, password = nil)
|
26
|
+
password = IO.get_password unless password
|
27
|
+
Delete.new(password, key).delete
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.update(key = nil, password = nil)
|
31
|
+
password = IO.get_password unless password
|
32
|
+
Update.new(password, key).update
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.location
|
36
|
+
ENV['CLANDESTINE_SAFE'] || SAFE_LOCATION
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.remove(password = nil)
|
40
|
+
password = IO.get_password unless password
|
41
|
+
RemoveSafe.new(password).remove
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.version
|
45
|
+
Clandestine::VERSION
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.help(options)
|
49
|
+
options
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../safe'
|
2
|
+
require_relative '../io'
|
3
|
+
require_relative '../password_generator'
|
4
|
+
require_relative '../clandestine_error'
|
5
|
+
|
6
|
+
module Clandestine
|
7
|
+
module Commands
|
8
|
+
class Add
|
9
|
+
attr_reader :safe_password, :key
|
10
|
+
private :safe_password, :key
|
11
|
+
|
12
|
+
def initialize(safe_password, key)
|
13
|
+
raise ClandestineError.new 'Missing required key argument' unless key
|
14
|
+
@safe_password = safe_password
|
15
|
+
@key = key.to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
def add
|
19
|
+
Safe.new(safe_password).open do |safe|
|
20
|
+
if !safe.exists?(key)
|
21
|
+
safe.add(key, PasswordGenerator.random_password)
|
22
|
+
else
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative '../safe'
|
2
|
+
|
3
|
+
module Clandestine
|
4
|
+
module Commands
|
5
|
+
class Delete
|
6
|
+
attr_reader :safe_password, :key
|
7
|
+
private :safe_password, :key
|
8
|
+
|
9
|
+
def initialize(safe_password, key)
|
10
|
+
@safe_password = safe_password
|
11
|
+
@key = key.to_sym
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete
|
15
|
+
Safe.new(safe_password).open do |safe|
|
16
|
+
if safe.exists?(key)
|
17
|
+
safe.delete(key)
|
18
|
+
else
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../safe'
|
2
|
+
require_relative '../io'
|
3
|
+
|
4
|
+
module Clandestine
|
5
|
+
module Commands
|
6
|
+
class Get
|
7
|
+
|
8
|
+
attr_reader :safe_password, :key
|
9
|
+
private :safe_password, :key
|
10
|
+
|
11
|
+
def initialize(safe_password, key)
|
12
|
+
@safe_password = safe_password
|
13
|
+
@key = key.to_sym if key
|
14
|
+
end
|
15
|
+
|
16
|
+
def get
|
17
|
+
Safe.new(safe_password).open do |safe|
|
18
|
+
if no_key_or_value?(safe)
|
19
|
+
safe.contents
|
20
|
+
else
|
21
|
+
safe[key]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def no_key_or_value?(safe)
|
29
|
+
!key || key_missing?(safe)
|
30
|
+
end
|
31
|
+
|
32
|
+
def key_missing?(safe)
|
33
|
+
!safe[key]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|