shh 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +28 -44
- data/bin/shh +2 -2
- data/lib/shh/blowfish_serialiser.rb +28 -0
- data/lib/shh/cli.rb +8 -4
- data/lib/shh/command/commit_changes.rb +13 -0
- data/lib/shh/command/diff_entry.rb +26 -0
- data/lib/shh/command/entries_command.rb +13 -0
- data/lib/shh/command/exhume_entry.rb +18 -0
- data/lib/shh/command/historic_entry_command.rb +26 -0
- data/lib/shh/command/list_entries.rb +9 -2
- data/lib/shh/command/open_entry.rb +5 -3
- data/lib/shh/command/show_history.rb +26 -0
- data/lib/shh/entries_menu.rb +6 -0
- data/lib/shh/entry_menu.rb +6 -2
- metadata +82 -24
- data/lib/shh/crypt.rb +0 -25
- data/lib/shh/repository.rb +0 -44
data/README.rdoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Secret Squirrel
|
4
4
|
|
5
|
-
This is a command line utility for managing secure information such as accounts, passwords as individual files so that they can be easily managed in a version control repository.
|
5
|
+
This is a command line utility for managing secure information such as accounts, passwords as individual files so that they can be easily managed in either a hg or git version control repository.
|
6
6
|
|
7
7
|
You won't be hiding anything from the NSA with this level of encryption so it isn't recommended that you make your repository publicly accessible.
|
8
8
|
|
@@ -12,6 +12,8 @@ Now with more tab completion and multi line editing!
|
|
12
12
|
|
13
13
|
Here you sit expectantly in front of a computer at the command line.
|
14
14
|
|
15
|
+
Either read the explanation below or checkout the following gist:
|
16
|
+
|
15
17
|
== Install
|
16
18
|
|
17
19
|
gem install shh
|
@@ -26,6 +28,8 @@ Opens all 'secrets' stored in foo/.secret
|
|
26
28
|
|
27
29
|
> shh foo
|
28
30
|
|
31
|
+
Note that shh will crash if the parent directory of .secret does not contain either a .hg or .git.
|
32
|
+
|
29
33
|
== Authenticate
|
30
34
|
|
31
35
|
Enter your passphrase
|
@@ -36,52 +40,37 @@ This passphrase will be used to encrypt and decrypt all of your secrets so don't
|
|
36
40
|
|
37
41
|
This mode allows you to view and edit 'entries' (which are encrypted hashes stored in files)
|
38
42
|
|
39
|
-
>
|
40
|
-
|
41
|
-
bitbucket (260f34de-6779-4367-af2a-44184dec1cc1)
|
42
|
-
amazon (291a3e6c-2c7b-4960-a146-1f6635d9a74e)
|
43
|
-
yahoo (2fe408e7-7f2b-4dc0-854a-c92c21f131ae)
|
44
|
-
evernote (41ad0a21-eafc-4f70-9b0d-0251be207b9e)
|
45
|
-
gmail (8b35c1f2-851d-40fc-bd12-c2aad12c370a)
|
46
|
-
rememberthemilk (a499f612-d034-4e49-82a8-6967d29653a1)
|
47
|
-
|
48
|
-
* list - list entries
|
49
|
-
* edit <name> - edit or create entry
|
50
|
-
* view <name> - view entry
|
51
|
-
* quit
|
52
|
-
|
53
|
-
== Viewing mode
|
54
|
-
|
55
|
-
This mode allows you to view (but not edit) an existing entry
|
56
|
-
|
57
|
-
> view bitbucket
|
58
|
-
(bitbucket) > list
|
59
|
-
id,name,password,username
|
60
|
-
(bitbucket) > view username
|
61
|
-
markryall
|
43
|
+
> ls
|
62
44
|
|
63
|
-
|
45
|
+
amazon
|
46
|
+
bitbucket
|
47
|
+
evernote
|
48
|
+
gmail
|
49
|
+
rememberthemilk
|
50
|
+
yahoo
|
64
51
|
|
65
|
-
*
|
66
|
-
*
|
67
|
-
*
|
68
|
-
*
|
69
|
-
* run <key> - execute ruby script (available if it starts with #!/usr/bin/env ruby)
|
52
|
+
* ls - list entries
|
53
|
+
* cd <name> - edit or create entry
|
54
|
+
* history <name> - view changes related to an entry
|
55
|
+
* exhume <cs> <name> - view entry as at the specified changeset
|
70
56
|
* quit
|
71
57
|
|
72
58
|
== Editing mode
|
73
59
|
|
74
|
-
|
75
|
-
|
76
|
-
> edit bitbucket
|
77
|
-
(bitbucket) > set foo
|
60
|
+
> cd bitbucket
|
61
|
+
shh:bitbucket > set foo
|
78
62
|
Enter new value for foo
|
79
63
|
bar
|
80
64
|
(bitbucket) > delete foo
|
81
65
|
|
66
|
+
* ls - list keys
|
82
67
|
* edit <key> - edit or create key using text editor (notepad or EDITOR)
|
83
68
|
* set <key> - edit or create key from prompt
|
84
|
-
*
|
69
|
+
* cat/less/more - show the value associated with a key
|
70
|
+
* cp - copies the value of a key to the system clipboard
|
71
|
+
* launch - launches the value associated with the key (really only useful for launching a url)
|
72
|
+
* exec - executes the value associated with the key as a script (see scripting below)
|
73
|
+
* rm <key> - remove a key
|
85
74
|
|
86
75
|
== Quitting mode
|
87
76
|
|
@@ -89,13 +78,9 @@ You don't want to be a quitter
|
|
89
78
|
|
90
79
|
== Scripting
|
91
80
|
|
92
|
-
In a script the
|
93
|
-
|
94
|
-
* splat.clipboard = <text> - allows content to be copied to the clipboard
|
95
|
-
* splat.browser - a watir compatible browser
|
96
|
-
* hash - the current selected entry
|
81
|
+
In a script the current entry is available as a variable called 'entry'
|
97
82
|
|
98
|
-
Example:
|
83
|
+
Very Contrived Example:
|
99
84
|
|
100
85
|
browser = 'http://www.github.com/login'.to_browser
|
101
86
|
browser.text_field(:id, 'login_field').set hash['username']
|
@@ -105,6 +90,5 @@ Example:
|
|
105
90
|
= Future plans for world domination
|
106
91
|
|
107
92
|
* Add some color
|
108
|
-
* Add
|
109
|
-
*
|
110
|
-
* add commands for displaying history of entries
|
93
|
+
* Add more history commands using source control (hg/git) commands
|
94
|
+
* Support other source control systems
|
data/bin/shh
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'crypt/blowfish'
|
2
|
+
|
3
|
+
module Shh
|
4
|
+
class BlowfishSerialiser
|
5
|
+
def initialize serialiser, passphrase
|
6
|
+
@blowfish = ::Crypt::Blowfish.new(passphrase)
|
7
|
+
@serialiser = serialiser
|
8
|
+
end
|
9
|
+
|
10
|
+
def read io
|
11
|
+
decrypted_io = StringIO.new
|
12
|
+
while l = io.read(8) do
|
13
|
+
decrypted_io.print @blowfish.decrypt_block(l)
|
14
|
+
end
|
15
|
+
@serialiser.read StringIO.new(decrypted_io.string.gsub("\0",''))
|
16
|
+
end
|
17
|
+
|
18
|
+
def write io, hash
|
19
|
+
serialised_io = StringIO.new
|
20
|
+
@serialiser.write serialised_io, hash
|
21
|
+
serialised_io.rewind
|
22
|
+
while l = serialised_io.read(8) do
|
23
|
+
while l.size < 8 do l += "\0" end
|
24
|
+
io.print @blowfish.encrypt_block(l)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/shh/cli.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'shh/repository'
|
3
2
|
require 'shh/prompt'
|
4
3
|
require 'shh/entries_menu'
|
4
|
+
require 'shh/blowfish_serialiser'
|
5
|
+
require 'flat_hash/serialiser'
|
6
|
+
require 'flat_hash/repository'
|
5
7
|
|
6
8
|
module Shh
|
7
9
|
class Cli
|
8
10
|
def self.execute *args
|
9
11
|
prompt = Prompt.new
|
10
12
|
passphrase = prompt.ask('Enter your passphrase', :silent => true)
|
11
|
-
path = args.shift ||
|
12
|
-
|
13
|
-
|
13
|
+
path = args.shift || '~'
|
14
|
+
Dir.chdir(File.expand_path(path)) do
|
15
|
+
serialiser = BlowfishSerialiser.new(FlatHash::Serialiser.new, passphrase)
|
16
|
+
EntriesMenu.new(prompt, FlatHash::Repository.new(serialiser, '.secret')).push
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Shh::Command::CommitChanges
|
2
|
+
attr_reader :help
|
3
|
+
|
4
|
+
def initialize repository, io
|
5
|
+
@io, @repository = io, repository
|
6
|
+
@help = "Commits all pending changes to vcs (note that this will add _all_ pending changes not only cards)"
|
7
|
+
@usage = "<commit message>"
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute text=nil
|
11
|
+
@repository.addremovecommit text
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
require 'shh/command/historic_entry_command'
|
3
|
+
|
4
|
+
class Shh::Command::DiffEntry
|
5
|
+
include Shh::Command::HistoricEntryCommand
|
6
|
+
|
7
|
+
def help
|
8
|
+
"Displays changes made since the specified revision of the entry\nRevision is a number representing the number of changesets to go back in history (ie. 0 is the most recently committed version)"
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute text=nil
|
12
|
+
with_current_and_historic_entry(text) do |current, changeset, historic|
|
13
|
+
diff = current.diff(historic)
|
14
|
+
if diff.empty?
|
15
|
+
puts "no changes"
|
16
|
+
else
|
17
|
+
added = current.keys - historic.keys
|
18
|
+
removed = historic.keys-current.keys
|
19
|
+
modified = diff.keys - (added + removed)
|
20
|
+
puts "added #{added.join(',')}" unless added.empty?
|
21
|
+
puts "removed #{removed.join(',')}" unless removed.empty?
|
22
|
+
puts "modified #{modified.join(',')}" unless modified.empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'uuidtools'
|
2
|
+
require 'shh/command/historic_entry_command'
|
3
|
+
require 'shh/entry_menu'
|
4
|
+
|
5
|
+
class Shh::Command::ExhumeEntry
|
6
|
+
include Shh::Command::HistoricEntryCommand
|
7
|
+
|
8
|
+
def help
|
9
|
+
"Enters a subshell for viewing the specifed entry as it was at the specified revision\nRevision is a number representing the number of changesets to go back in history (ie. 0 is the most recently committed version)"
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute text=nil
|
13
|
+
with_current_and_historic_entry(text) do |current, changeset, historic|
|
14
|
+
puts "warning: you are viewing #{historic['name']} as at #{changeset.id}, any changes you make will be discarded"
|
15
|
+
Shh::EntryMenu.new(@io, historic).push
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Shh::Command::HistoricEntryCommand
|
2
|
+
def initialize repository, io
|
3
|
+
@repository, @io = repository, io
|
4
|
+
end
|
5
|
+
|
6
|
+
def usage
|
7
|
+
"<entry name> <revision>"
|
8
|
+
end
|
9
|
+
|
10
|
+
def completion text
|
11
|
+
@repository.map{|entry| entry['name']}.grep(/^#{text}/).sort || []
|
12
|
+
end
|
13
|
+
private
|
14
|
+
def with_current_and_historic_entry text
|
15
|
+
if text =~ /^(.*) (\d+)$/
|
16
|
+
name, rev = $1, $2.to_i
|
17
|
+
return unless name
|
18
|
+
return if name.empty?
|
19
|
+
current = @repository.find { |entry| entry['name'] == name }
|
20
|
+
return unless current
|
21
|
+
cs = @repository.history(current.id)[rev]
|
22
|
+
return unless cs
|
23
|
+
yield current, cs, @repository.element_at(cs.id, current.id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -9,8 +9,15 @@ class Shh::Command::ListEntries
|
|
9
9
|
|
10
10
|
def execute text=nil
|
11
11
|
@repository.each do |entry|
|
12
|
-
|
13
|
-
|
12
|
+
unless entry.id == entry['id']
|
13
|
+
puts "Encryption failure! Did you enter the correct password?"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@repository.sort{|l,r| (l['name']) <=> (r['name'])}.each do |entry|
|
18
|
+
description = "#{entry['name']} (#{entry.id})"
|
19
|
+
next if text and !(description =~ /#{text}/)
|
20
|
+
@io.say description
|
14
21
|
end
|
15
22
|
end
|
16
23
|
end
|
@@ -15,9 +15,11 @@ class Shh::Command::OpenEntry
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def execute name=nil
|
18
|
-
|
19
|
-
|
18
|
+
return unless name
|
19
|
+
return if name.empty?
|
20
|
+
entry = @repository.find { |entry| entry['name'] == name }
|
21
|
+
entry ||= {'name' => name, 'id' => UUIDTools::UUID.random_create.to_s }
|
20
22
|
Shh::EntryMenu.new(@io, entry).push
|
21
|
-
@repository
|
23
|
+
@repository[entry['id']] = entry
|
22
24
|
end
|
23
25
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Shh::Command::ShowHistory
|
2
|
+
attr_reader :usage, :help
|
3
|
+
|
4
|
+
def initialize repository, io
|
5
|
+
@repository, @io = repository, io
|
6
|
+
@usage = "(<substring>)"
|
7
|
+
@help = "Shows history for a given entry"
|
8
|
+
end
|
9
|
+
|
10
|
+
def completion text
|
11
|
+
@repository.map{|entry| entry['name']}.grep(/^#{text}/).sort || []
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute name=nil
|
15
|
+
entry = @repository.find { |entry| entry['name'] == name }
|
16
|
+
id = entry ? entry.id : nil
|
17
|
+
first = true
|
18
|
+
@repository.history(id).each do |cs|
|
19
|
+
puts '-------' unless first
|
20
|
+
puts "#{cs.id} #{cs.time}"
|
21
|
+
puts "#{cs.author}"
|
22
|
+
puts "#{cs.description}"
|
23
|
+
first = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/shh/entries_menu.rb
CHANGED
@@ -12,5 +12,11 @@ class Shh::EntriesMenu
|
|
12
12
|
'ls' => load_command(:list_entries, @repository, @io),
|
13
13
|
'cd' => load_command(:open_entry, @repository, @io)
|
14
14
|
}
|
15
|
+
if @repository.vcs_supported?
|
16
|
+
@commands['history'] = load_command(:show_history, @repository, @io)
|
17
|
+
@commands['exhume'] = load_command(:exhume_entry, @repository, @io)
|
18
|
+
@commands['diff'] = load_command(:diff_entry, @repository, @io)
|
19
|
+
@commands['ci'] = load_command(:commit_changes, @repository, @io)
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
data/lib/shh/entry_menu.rb
CHANGED
@@ -7,11 +7,15 @@ class Shh::EntryMenu
|
|
7
7
|
|
8
8
|
def initialize io, entry
|
9
9
|
@io, @entry = io, entry
|
10
|
+
show_command = load_command(:show_key, entry, io)
|
11
|
+
edit_command = load_command(:edit_key, entry, io)
|
10
12
|
@commands = {
|
11
13
|
'ls' => load_command(:list_keys, entry, io),
|
12
14
|
'set' => load_command(:set_key, entry, io),
|
13
|
-
'edit' =>
|
14
|
-
'cat' =>
|
15
|
+
'edit' => edit_command,
|
16
|
+
'cat' => show_command,
|
17
|
+
'less' => show_command,
|
18
|
+
'more' => show_command,
|
15
19
|
'cp' => load_command(:copy_key, entry, io),
|
16
20
|
'launch' => load_command(:launch_key, entry, io),
|
17
21
|
'rm' => load_command(:remove_key, entry, io),
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
9
|
+
- 8
|
10
|
+
version: 0.1.8
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Mark Ryall
|
@@ -14,121 +15,169 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-08-21 00:00:00 +10:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
22
|
+
name: flat_hash
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ~>
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 27
|
27
30
|
segments:
|
28
|
-
-
|
29
|
-
-
|
31
|
+
- 0
|
32
|
+
- 0
|
30
33
|
- 2
|
31
|
-
version:
|
34
|
+
version: 0.0.2
|
32
35
|
type: :runtime
|
33
36
|
version_requirements: *id001
|
34
37
|
- !ruby/object:Gem::Dependency
|
35
|
-
name:
|
38
|
+
name: highline
|
36
39
|
prerelease: false
|
37
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 13
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 6
|
49
|
+
- 1
|
50
|
+
version: 1.6.1
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: uuidtools
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
38
58
|
requirements:
|
39
59
|
- - ~>
|
40
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 9
|
41
62
|
segments:
|
42
63
|
- 2
|
43
64
|
- 1
|
44
65
|
- 1
|
45
66
|
version: 2.1.1
|
46
67
|
type: :runtime
|
47
|
-
version_requirements: *
|
68
|
+
version_requirements: *id003
|
48
69
|
- !ruby/object:Gem::Dependency
|
49
70
|
name: crypt
|
50
71
|
prerelease: false
|
51
|
-
requirement: &
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
52
74
|
requirements:
|
53
75
|
- - ~>
|
54
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 27
|
55
78
|
segments:
|
56
79
|
- 1
|
57
80
|
- 1
|
58
81
|
- 4
|
59
82
|
version: 1.1.4
|
60
83
|
type: :runtime
|
61
|
-
version_requirements: *
|
84
|
+
version_requirements: *id004
|
62
85
|
- !ruby/object:Gem::Dependency
|
63
86
|
name: splat
|
64
87
|
prerelease: false
|
65
|
-
requirement: &
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
66
90
|
requirements:
|
67
91
|
- - ~>
|
68
92
|
- !ruby/object:Gem::Version
|
93
|
+
hash: 27
|
69
94
|
segments:
|
70
95
|
- 0
|
71
96
|
- 1
|
72
97
|
- 0
|
73
98
|
version: 0.1.0
|
74
99
|
type: :runtime
|
75
|
-
version_requirements: *
|
100
|
+
version_requirements: *id005
|
76
101
|
- !ruby/object:Gem::Dependency
|
77
102
|
name: shell_shock
|
78
103
|
prerelease: false
|
79
|
-
requirement: &
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
80
106
|
requirements:
|
81
107
|
- - ~>
|
82
108
|
- !ruby/object:Gem::Version
|
109
|
+
hash: 25
|
83
110
|
segments:
|
84
111
|
- 0
|
85
112
|
- 0
|
86
113
|
- 3
|
87
114
|
version: 0.0.3
|
88
115
|
type: :runtime
|
89
|
-
version_requirements: *
|
116
|
+
version_requirements: *id006
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: activesupport
|
119
|
+
prerelease: false
|
120
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
hash: 19
|
126
|
+
segments:
|
127
|
+
- 2
|
128
|
+
- 3
|
129
|
+
- 8
|
130
|
+
version: 2.3.8
|
131
|
+
type: :runtime
|
132
|
+
version_requirements: *id007
|
90
133
|
- !ruby/object:Gem::Dependency
|
91
134
|
name: rake
|
92
135
|
prerelease: false
|
93
|
-
requirement: &
|
136
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
94
138
|
requirements:
|
95
139
|
- - ~>
|
96
140
|
- !ruby/object:Gem::Version
|
141
|
+
hash: 49
|
97
142
|
segments:
|
98
143
|
- 0
|
99
144
|
- 8
|
100
145
|
- 7
|
101
146
|
version: 0.8.7
|
102
147
|
type: :development
|
103
|
-
version_requirements: *
|
148
|
+
version_requirements: *id008
|
104
149
|
- !ruby/object:Gem::Dependency
|
105
150
|
name: gemesis
|
106
151
|
prerelease: false
|
107
|
-
requirement: &
|
152
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
108
154
|
requirements:
|
109
155
|
- - ~>
|
110
156
|
- !ruby/object:Gem::Version
|
157
|
+
hash: 25
|
111
158
|
segments:
|
112
159
|
- 0
|
113
160
|
- 0
|
114
161
|
- 3
|
115
162
|
version: 0.0.3
|
116
163
|
type: :development
|
117
|
-
version_requirements: *
|
164
|
+
version_requirements: *id009
|
118
165
|
- !ruby/object:Gem::Dependency
|
119
166
|
name: orangutan
|
120
167
|
prerelease: false
|
121
|
-
requirement: &
|
168
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
122
170
|
requirements:
|
123
171
|
- - ~>
|
124
172
|
- !ruby/object:Gem::Version
|
173
|
+
hash: 17
|
125
174
|
segments:
|
126
175
|
- 0
|
127
176
|
- 0
|
128
177
|
- 7
|
129
178
|
version: 0.0.7
|
130
179
|
type: :development
|
131
|
-
version_requirements: *
|
180
|
+
version_requirements: *id010
|
132
181
|
description: |
|
133
182
|
A command line utility that manages accounts and passwords as individual encypted files
|
134
183
|
|
@@ -140,10 +189,16 @@ extensions: []
|
|
140
189
|
extra_rdoc_files: []
|
141
190
|
|
142
191
|
files:
|
192
|
+
- lib/shh/blowfish_serialiser.rb
|
143
193
|
- lib/shh/cli.rb
|
194
|
+
- lib/shh/command/commit_changes.rb
|
144
195
|
- lib/shh/command/copy_key.rb
|
196
|
+
- lib/shh/command/diff_entry.rb
|
145
197
|
- lib/shh/command/edit_key.rb
|
198
|
+
- lib/shh/command/entries_command.rb
|
146
199
|
- lib/shh/command/execute_key.rb
|
200
|
+
- lib/shh/command/exhume_entry.rb
|
201
|
+
- lib/shh/command/historic_entry_command.rb
|
147
202
|
- lib/shh/command/key_command.rb
|
148
203
|
- lib/shh/command/launch_key.rb
|
149
204
|
- lib/shh/command/list_entries.rb
|
@@ -151,13 +206,12 @@ files:
|
|
151
206
|
- lib/shh/command/open_entry.rb
|
152
207
|
- lib/shh/command/remove_key.rb
|
153
208
|
- lib/shh/command/set_key.rb
|
209
|
+
- lib/shh/command/show_history.rb
|
154
210
|
- lib/shh/command/show_key.rb
|
155
211
|
- lib/shh/commands.rb
|
156
|
-
- lib/shh/crypt.rb
|
157
212
|
- lib/shh/entries_menu.rb
|
158
213
|
- lib/shh/entry_menu.rb
|
159
214
|
- lib/shh/prompt.rb
|
160
|
-
- lib/shh/repository.rb
|
161
215
|
- bin/shh
|
162
216
|
- README.rdoc
|
163
217
|
- MIT-LICENSE
|
@@ -171,23 +225,27 @@ rdoc_options: []
|
|
171
225
|
require_paths:
|
172
226
|
- lib
|
173
227
|
required_ruby_version: !ruby/object:Gem::Requirement
|
228
|
+
none: false
|
174
229
|
requirements:
|
175
230
|
- - ">="
|
176
231
|
- !ruby/object:Gem::Version
|
232
|
+
hash: 3
|
177
233
|
segments:
|
178
234
|
- 0
|
179
235
|
version: "0"
|
180
236
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
237
|
+
none: false
|
181
238
|
requirements:
|
182
239
|
- - ">="
|
183
240
|
- !ruby/object:Gem::Version
|
241
|
+
hash: 3
|
184
242
|
segments:
|
185
243
|
- 0
|
186
244
|
version: "0"
|
187
245
|
requirements: []
|
188
246
|
|
189
247
|
rubyforge_project:
|
190
|
-
rubygems_version: 1.3.
|
248
|
+
rubygems_version: 1.3.7
|
191
249
|
signing_key:
|
192
250
|
specification_version: 3
|
193
251
|
summary: command line utility for managing secure information
|
data/lib/shh/crypt.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'crypt/blowfish'
|
2
|
-
|
3
|
-
module Shh
|
4
|
-
class Crypt
|
5
|
-
def initialize passphrase
|
6
|
-
@blowfish = ::Crypt::Blowfish.new(passphrase)
|
7
|
-
end
|
8
|
-
|
9
|
-
def encrypt text, out_io
|
10
|
-
in_io = StringIO.new(text)
|
11
|
-
while l = in_io.read(8) do
|
12
|
-
while l.size < 8 do l += "\0" end
|
13
|
-
out_io.print @blowfish.encrypt_block(l)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def decrypt in_io
|
18
|
-
out_io = StringIO.new
|
19
|
-
while l = in_io.read(8) do
|
20
|
-
out_io.print @blowfish.decrypt_block(l)
|
21
|
-
end
|
22
|
-
out_io.string.gsub("\0",'')
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/shh/repository.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'shh/crypt'
|
3
|
-
require 'fileutils'
|
4
|
-
|
5
|
-
module Shh
|
6
|
-
class Repository
|
7
|
-
include Enumerable
|
8
|
-
|
9
|
-
attr_reader :folder
|
10
|
-
|
11
|
-
def initialize passphrase, path
|
12
|
-
@folder = Pathname.new(File.expand_path(path)) + '.secret'
|
13
|
-
@folder.mkpath
|
14
|
-
@crypt = Crypt.new(passphrase)
|
15
|
-
end
|
16
|
-
|
17
|
-
def each
|
18
|
-
@folder.children.each do |child|
|
19
|
-
entry = load(child)
|
20
|
-
yield entry if entry
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def find_by_name name
|
25
|
-
each {|e| return e if e['name'] == name}
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
|
29
|
-
def load path
|
30
|
-
return nil if path.directory?
|
31
|
-
yaml = path.open('rb') {|io| @crypt.decrypt(io) }
|
32
|
-
entry = YAML::load(yaml)
|
33
|
-
unless entry and path.basename.to_s == entry['id']
|
34
|
-
$stderr.puts "failed to deserialise #{path}"
|
35
|
-
return nil
|
36
|
-
end
|
37
|
-
entry
|
38
|
-
end
|
39
|
-
|
40
|
-
def persist entry
|
41
|
-
(@folder + entry['id']).open('wb') {|io| @crypt.encrypt(entry.to_yaml, io) }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|