shh 0.1.7 → 0.1.8
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.
- 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
|