shh 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -5,3 +5,92 @@ Secret Squirrel
5
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.
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
+
9
+ Now with more tab completion!
10
+
11
+ = Usage
12
+
13
+ Here you sit expectantly in front of a computer at the command line.
14
+
15
+ == Install
16
+
17
+ gem install shh
18
+
19
+ (you may need to install gemcutter first)
20
+
21
+ == Launch
22
+
23
+ Open all 'secrets' stored in ~/.secret
24
+
25
+ > shh
26
+
27
+ Opens all 'secrets' stored in foo/.secret
28
+
29
+ > shh foo
30
+
31
+ == Authenticate
32
+
33
+ Enter your passphrase
34
+
35
+ This passphrase will be used to encrypt and decrypt all of your secrets so don't make it too obvious.
36
+
37
+ == Listing mode
38
+
39
+ This mode allows you to view and edit 'entries' (which are encrypted hashes stored in files)
40
+
41
+ > list
42
+
43
+ bitbucket (260f34de-6779-4367-af2a-44184dec1cc1)
44
+ amazon (291a3e6c-2c7b-4960-a146-1f6635d9a74e)
45
+ yahoo (2fe408e7-7f2b-4dc0-854a-c92c21f131ae)
46
+ evernote (41ad0a21-eafc-4f70-9b0d-0251be207b9e)
47
+ gmail (8b35c1f2-851d-40fc-bd12-c2aad12c370a)
48
+ rememberthemilk (a499f612-d034-4e49-82a8-6967d29653a1)
49
+
50
+ * list - show entries
51
+ * edit <name> - edit or create entry
52
+ * view <name> - view entry
53
+ * quit
54
+
55
+ == Viewing mode
56
+
57
+ This mode allows you to view (but not edit) an existing entry
58
+
59
+ > view bitbucket
60
+ (bitbucket) > list
61
+ id,name,password,username
62
+ (bitbucket) > show username
63
+ markryall
64
+
65
+ list keys, show key, copy key or quit? c password
66
+
67
+ * list - show entry keys
68
+ * show <key> - show entry value on screen
69
+ * copy <key> - copy entry value to clipboard
70
+ * quit
71
+
72
+ == Editing mode
73
+
74
+ This mode is viewing mode plus some editing commands
75
+
76
+ > edit bitbucket
77
+ (bitbucket) > edit foo
78
+ Enter new value for foo
79
+ bar
80
+ (bitbucket) > delete foo
81
+
82
+ * edit <key> - edit or create key
83
+ * delete <key> - remove a key
84
+
85
+ == Quitting mode
86
+
87
+ You don't want to be a quitter
88
+
89
+ = Future plans for world domination
90
+
91
+ * Add some color
92
+ * Add help
93
+ * Launch applications for urls
94
+ * Add multi line values (edit with default text editor)
95
+ * Include uuid as part of encryption key (and upgrade encryption on existing entries)
96
+ * add some source control (hg/git) commands
data/bin/shh CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  $:.unshift File.dirname(__FILE__)+'/../lib'
4
4
  require 'shh'
5
- Shh::Cli.new.execute(*ARGV)
5
+ Shh::Cli.execute(*ARGV)
data/lib/shh/cli.rb CHANGED
@@ -1,93 +1,16 @@
1
1
  require 'rubygems'
2
- require 'pathname2'
3
- require 'highline/import'
4
- require 'uuidtools'
5
- require 'yaml'
6
- require 'shh/crypt'
7
- require 'shh/clipboard'
2
+ require 'shh/repository'
3
+ require 'shh/prompt'
4
+ require 'shh/entries_menu'
8
5
 
9
6
  module Shh
10
7
  class Cli
11
- def execute *args
12
- passphrase = ask('Enter your passphrase') { |q| q.echo = false }
8
+ def self.execute *args
9
+ prompt = Prompt.new
10
+ passphrase = prompt.get('Enter your passphrase', :silent => true)
11
+ path = args.shift || ('~')
13
12
 
14
- path = args.shift
15
- @folder = path ? Pathname.new(path) : Pathname.new(File.expand_path('~'))+'.secret'
16
- @folder.mkdir_p
17
- @crypt = Crypt.new(passphrase)
18
- @clipboard = Shh.clipboard
19
-
20
- loop do
21
- choose do |menu|
22
- menu.layout = :menu_only
23
- menu.shell = true
24
- menu.choice('list entries') { list }
25
- menu.choice('edit entry') { |command, details| edit details }
26
- menu.choice('view entry') { |command, details| view details }
27
- menu.choice('quit') { exit }
28
- end
29
- end
30
- end
31
-
32
- def list
33
- each_entry {|entry| say "#{entry['name']} (#{entry['id']})" }
34
- end
35
-
36
- def edit name=''
37
- entry = find_entry(check_name(name))
38
- entry ||= {'name' => check_name(name), 'id' => UUIDTools::UUID.random_create.to_s}
39
- persist_entry prompt_loop(entry)
40
- end
41
-
42
- def view name=''
43
- prompt_loop find_entry(check_name(name)), true
44
- end
45
-
46
- private
47
-
48
- def each_entry
49
- @folder.children.each do |child|
50
- yield load_entry(child)
51
- end
52
- end
53
-
54
- def check_name name
55
- name = ask('Enter the entry name') unless name.size > 0
56
- name
57
- end
58
-
59
- def find_entry name
60
- each_entry {|e| return e if e['name'] == name}
61
- nil
62
- end
63
-
64
- def load_entry path
65
- entry = path.open('rb') {|io| @crypt.decrypt(io) }
66
- YAML::load(entry)
67
- end
68
-
69
- def persist_entry entry
70
- (@folder + entry['id']).open('wb') {|io| @crypt.encrypt(entry.to_yaml, io) }
71
- end
72
-
73
- def prompt_loop hash, read_only=false
74
- loop do
75
- choose do |menu|
76
- menu.layout = :menu_only
77
- menu.shell = true
78
- menu.choice('edit key') { |command, name| hash[name] = new_value(name) } unless read_only
79
- menu.choice('list keys') { say(hash.keys.sort.join(',')) }
80
- menu.choice('show key') { |command, name| say(hash[name]) if hash[name] }
81
- menu.choice('delete key') { |command, name| hash[name] = nil } unless read_only
82
- menu.choice('copy key') { |command, name| @clipboard.content = hash[name] } if @clipboard
83
- menu.choice('quit') { return hash }
84
- end
85
- end
86
- end
87
-
88
- def new_value name
89
- echo = (name =~ /pass/) ? false : true
90
- ask("Enter new value for #{name}") {|q| q.echo = echo }
13
+ EntriesMenu.new(prompt, Repository.new(passphrase, path)).main_loop
91
14
  end
92
15
  end
93
16
  end
@@ -0,0 +1,63 @@
1
+ require 'uuidtools'
2
+ require 'readline'
3
+ require 'shh/entry_menu'
4
+
5
+ module Shh
6
+ class EntriesMenu
7
+ def initialize prompt, repository
8
+ @prompt, @repository = prompt, repository
9
+ refresh
10
+ end
11
+
12
+ def main_loop
13
+ prompt_text = ' > '
14
+
15
+ begin
16
+ while line = Readline.readline(prompt_text, true).strip
17
+ case line
18
+ when 'quit'
19
+ return
20
+ when 'refresh'
21
+ refresh
22
+ when 'list'
23
+ list
24
+ when /^view (.*)/
25
+ view $1
26
+ when /^edit (.*)/
27
+ edit $1
28
+ end
29
+ end
30
+ rescue Interrupt => e
31
+ return
32
+ end
33
+ end
34
+
35
+ def refresh
36
+ commands = ['list', 'refresh', 'quit']
37
+ @repository.each_entry do |entry|
38
+ commands << "edit #{entry['name']}"
39
+ commands << "view #{entry['name']}"
40
+ end
41
+ Readline.completion_proc = lambda do |text|
42
+ commands.grep( /^#{Regexp.escape(text)}/ ).sort
43
+ end
44
+ Readline.completer_word_break_characters = ''
45
+ end
46
+
47
+ def list
48
+ @repository.each_entry {|entry| say "#{entry['name']} (#{entry['id']})" }
49
+ end
50
+
51
+ def edit name
52
+ entry = @repository.find_entry(name)
53
+ entry ||= {'name' => name, 'id' => UUIDTools::UUID.random_create.to_s}
54
+ @repository.persist_entry EntryMenu.new(@prompt, entry).main_loop
55
+ refresh
56
+ end
57
+
58
+ def view name
59
+ EntryMenu.new(@prompt, @repository.find_entry(name), true).main_loop
60
+ refresh
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,60 @@
1
+ require 'shh/clipboard'
2
+
3
+ module Shh
4
+ class EntryMenu
5
+ def initialize prompt, hash, read_only=false
6
+ @prompt, @hash, @read_only = prompt, hash, read_only
7
+ @clipboard = Shh.clipboard
8
+ refresh
9
+ end
10
+
11
+ def main_loop
12
+ prompt_text = "(#{@hash['name']}) > "
13
+
14
+ begin
15
+ while line = Readline.readline(prompt_text, true).strip
16
+ case line
17
+ when 'quit'
18
+ return @hash
19
+ when 'list'
20
+ say(@hash.keys.sort.join(','))
21
+ when /^edit (.*)/
22
+ name = $1
23
+ @hash[name] = new_value(name) unless @read_only
24
+ when /^copy (.*)/
25
+ name = $1
26
+ @clipboard.content = @hash[name] if @clipboard and @hash[name]
27
+ when /^delete (.*)/
28
+ name = $1
29
+ @hash.delete(name) unless @read_only
30
+ when /^show (.*)/
31
+ name = $1
32
+ say(@hash[name]) if @hash[name]
33
+ end
34
+ end
35
+ rescue Interrupt => e
36
+ return @hash
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def refresh
43
+ commands = ['list', 'quit']
44
+ @hash.keys.each do |key|
45
+ commands << "edit #{key}" unless @read_only
46
+ commands << "delete #{key}" unless @read_only
47
+ commands << "show #{key}"
48
+ commands << "copy #{key}"
49
+ end
50
+ Readline.completion_proc = lambda do |text|
51
+ commands.grep( /^#{Regexp.escape(text)}/ ).sort
52
+ end
53
+ Readline.completer_word_break_characters = ''
54
+ end
55
+
56
+ def new_value name
57
+ @prompt.get "Enter new value for #{name}", :silent => (name =~ /pass/)
58
+ end
59
+ end
60
+ end
data/lib/shh/prompt.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'highline/import'
2
+
3
+ module Shh
4
+ class Prompt
5
+ def get text, params={}
6
+ return params[:value] if params[:value] and params[:value].size > 0
7
+ echo = params[:silent] ? false : true
8
+ ask(text) { |q| q.echo = false }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ require 'pathname2'
2
+ require 'yaml'
3
+ require 'shh/crypt'
4
+
5
+ module Shh
6
+ class Repository
7
+ attr_reader :folder
8
+
9
+ def initialize passphrase, path
10
+ @folder = Pathname.new(File.expand_path(path)) + '.secret'
11
+ @folder.mkdir_p
12
+ @crypt = Crypt.new(passphrase)
13
+ end
14
+
15
+ def each_entry
16
+ @folder.children.each do |child|
17
+ entry = load_entry(child)
18
+ yield entry if entry
19
+ end
20
+ end
21
+
22
+ def find_entry name
23
+ each_entry {|e| return e if e['name'] == name}
24
+ nil
25
+ end
26
+
27
+ def load_entry path
28
+ return nil if path.directory?
29
+ yaml = path.open('rb') {|io| @crypt.decrypt(io) }
30
+ entry = YAML::load(yaml)
31
+ return nil unless entry
32
+ path.basename.to_s == entry['id'] ? entry : nil
33
+ end
34
+
35
+ def persist_entry entry
36
+ (@folder + entry['id']).open('wb') {|io| @crypt.encrypt(entry.to_yaml, io) }
37
+ end
38
+ end
39
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Ryall
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-18 00:00:00 +11:00
12
+ date: 2009-12-26 00:00:00 +11:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -67,6 +67,10 @@ files:
67
67
  - lib/shh/clipboard.rb
68
68
  - lib/shh/crypt.rb
69
69
  - lib/shh/darwin10_clipboard.rb
70
+ - lib/shh/entries_menu.rb
71
+ - lib/shh/entry_menu.rb
72
+ - lib/shh/prompt.rb
73
+ - lib/shh/repository.rb
70
74
  - lib/shh/win32_clipboard.rb
71
75
  - lib/shh.rb
72
76
  - bin/shh