keychain 0.2.1

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.
Files changed (3) hide show
  1. data/README +34 -0
  2. data/bin/keychain +237 -0
  3. metadata +64 -0
data/README ADDED
@@ -0,0 +1,34 @@
1
+ keychain is a very simple command line tool for managing passwords
2
+
3
+ Features include:
4
+
5
+ - passwords are stored in the blowfish encrypted file $HOME/.keychain
6
+ - search for entries using regular expressions
7
+ - automatically generates more or less pronouncable random passwords
8
+
9
+ Usage is very simple, you either start keychain without any arguments
10
+ to enter an interactive mode or directly supply the command on the
11
+ command line. Commands are:
12
+
13
+ help - print this help
14
+ print [pattern] - print entries matching pattern (patterin is full
15
+ regular expression. In particular '.*' matches
16
+ everything, not '*'
17
+ store id user key - add an entry. If key == ?, generates random password
18
+ delete id - delete entry
19
+ rename id_new id_old - rename an entry
20
+ password - change master password
21
+
22
+ Now, although I'm using this script for managing my own passwords you
23
+ should carefully read the following disclaimer:
24
+
25
+ THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY GUARANTEES TO ITS
26
+ SUITEDNESS FOR ANY PARTICULAR USE. IN PARTICULAR, I CANNOT GUARANTEE
27
+ THAT THIS SCRIPT WILL NOT ACCIDENTALLY FORGETS YOUR PASSWORDS, OR THAT
28
+ THE DATA IS ENCRYPTED IN A FASHION WHICH CANNOT BE CRACKED. THEREFORE,
29
+ KEEP YOUR $HOME/.keychain PRIVATE, AND REGULARY MAKE SURE TO STORE
30
+ YOUR PASSWORDS SOMEWHERE ELSE. ALSO MAKE SURE THAT YOU DO NOT FORGET
31
+ YOUR MASTER PASSWORD!
32
+
33
+ On the other hand, if you have ideas how to improve the security and
34
+ the cryptologic strength of the encoding, I'd be happy to know!
data/bin/keychain ADDED
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+
4
+ # A simple keychain manager written in ruby
5
+ #
6
+ # Requires the crypt and highline gem
7
+ #
8
+ # Written by Mikio L. Braun, 2008
9
+
10
+ require 'yaml'
11
+ require 'rubygems'
12
+ require 'crypt/blowfish'
13
+ require 'highline/import'
14
+
15
+ class KeyChain
16
+ FILENAME = File.join(ENV['HOME'], '.keychain')
17
+
18
+ def initialize
19
+ @keychain = {}
20
+ end
21
+
22
+ def load
23
+ if test ?f, FILENAME
24
+ @crypt = get_crypt
25
+ s = File.open(FILENAME) do |f|
26
+ @crypt.decrypt_string(f.read)
27
+ end
28
+ begin
29
+ @keychain = YAML::load(s)
30
+ raise 'ups' unless Hash === @keychain
31
+ rescue
32
+ puts "Wrong password."
33
+ exit
34
+ end
35
+ else
36
+ puts "Couldn't find keychain. Enter initial password!"
37
+ @crypt = get_new_crypt
38
+ save
39
+ File.chmod 0600, FILENAME
40
+ end
41
+ end
42
+
43
+ def save
44
+ s = YAML::dump(@keychain)
45
+ File.open(FILENAME, 'w') do |f|
46
+ f.write(@crypt.encrypt_string(s))
47
+ end
48
+ end
49
+
50
+ def store(id, user, passwd)
51
+ if @keychain.member? id
52
+ if ask("overwriting \"#{id}\"? ") != 'y'
53
+ puts "Did not overwrite"
54
+ return
55
+ end
56
+ end
57
+ @keychain[id] = [user, passwd]
58
+ end
59
+
60
+ def print(pat=nil)
61
+ puts "id | login | password"
62
+ puts "---------------------+---------------------------+----------------------"
63
+ pat ||= /.*/
64
+ @keychain.keys.grep(pat).sort.each do |id|
65
+ printf "%-20s | %-25s | %-15s\n", id, @keychain[id][0], @keychain[id][1]
66
+ end
67
+ end
68
+
69
+ def rename(id_old, id_new)
70
+ unless @keychain.member? id_old
71
+ puts "Cannot find key \"#{id_old}\""
72
+ return
73
+ end
74
+
75
+ if @keychain.member? id_new
76
+ puts "New id \"#{id_new}\" already exists!"
77
+ return
78
+ end
79
+
80
+ @keychain[id_new] = @keychain[id_old]
81
+ @keychain.delete id_old
82
+ end
83
+
84
+ def delete(id)
85
+ unless @keychain.member? id_old
86
+ puts "Cannot find key \"#{id_old}\""
87
+ return
88
+ end
89
+
90
+ @keychain.delete id
91
+ end
92
+
93
+ def password
94
+ @crypt = get_new_crypt
95
+ save
96
+ end
97
+
98
+ # generate a random password using a markov chain on
99
+ # vowels and consonants to produce pronouncable passwords.
100
+ def generate_password(l)
101
+ vow = %w(a e i o u)
102
+ con = %w(b c d f g h j k l m n p q r s t v x y z)
103
+
104
+ pw = ''
105
+ state = if rand < 0.8 then :c else :v end
106
+ for i in 0..l
107
+ case state
108
+ when :v
109
+ pw << vow[rand(vow.size)]
110
+ state = :c if rand > 0.4
111
+ when :c
112
+ pw << con[rand(con.size)]
113
+ state = :v if rand > 0.1
114
+ end
115
+ end
116
+ return pw
117
+ end
118
+ private
119
+ def get_new_crypt
120
+ password = ask('new password> ') {|q| q.echo = false}
121
+ retyped = ask('retype password> ') {|q| q.echo = false}
122
+ if password != retyped
123
+ puts "Passwords did not match."
124
+ exit
125
+ end
126
+ Crypt::Blowfish.new password
127
+ end
128
+
129
+ def get_crypt
130
+ password = ask('password> ') {|q| q.echo = false}
131
+ Crypt::Blowfish.new password
132
+ end
133
+ end
134
+
135
+ Help = <<EOS
136
+ Usage: keychain command [args]
137
+
138
+ Commands:
139
+
140
+ help - print this help
141
+ print [pattern] - print entries matching pattern (patterin is full
142
+ regular expression. In particular '.*' matches
143
+ everything, not '*'
144
+ store id user key - add an entry. If key == ?, generates random password
145
+ delete id - delete entry
146
+ rename id_new id_old - rename an entry
147
+ password - change master password
148
+
149
+ Version 0.2.1 - August 8, 2008
150
+ EOS
151
+
152
+ if ARGV.size == 0
153
+ ARGV << 'interactive'
154
+ end
155
+
156
+ def cmd(kc, args)
157
+ case args[0]
158
+ when 'print'
159
+ if args.size == 2
160
+ kc.print(Regexp.new(args[1]))
161
+ else
162
+ kc.print
163
+ end
164
+ when 'store'
165
+ if args.size < 4
166
+ puts "Format is \"add id user key\""
167
+ return
168
+ end
169
+ if args[3] == '?'
170
+ l = ask('password length? ').to_i
171
+ if l > 0
172
+ ok = false
173
+ pw = nil
174
+ until ok
175
+ pw = kc.generate_password(l)
176
+ puts "Generated password: #{pw}"
177
+ case ask('okay (ynq)? ')
178
+ when 'y'
179
+ ok = true
180
+ when 'q'
181
+ pw = nil
182
+ break
183
+ end
184
+ end
185
+ return unless pw
186
+ kc.store(args[1], args[2], pw)
187
+ end
188
+ else
189
+ kc.store(args[1], args[2], args[3])
190
+ end
191
+ kc.save
192
+ when 'delete'
193
+ if args.size < 1
194
+ puts "Which id do you want to delete?"
195
+ end
196
+ kc.delete(args[1])
197
+ kc.save
198
+ when 'rename'
199
+ if args.size < 2
200
+ puts "Format is \"rename id_old id_new\""
201
+ end
202
+ kc.rename(args[1], args[2])
203
+ kc.save
204
+ when 'help'
205
+ puts Help
206
+ when 'password'
207
+ kc.password
208
+ when 'gen'
209
+ puts kc.generate_password(args[1].to_i)
210
+ else
211
+ puts "Didn't understand command"
212
+ return
213
+ end
214
+ end
215
+
216
+ kc = KeyChain.new
217
+ if ARGV[0] == 'interactive'
218
+ puts "Entering interactive mode. Enter password. Then type 'exit' or an empty line to quite."
219
+ kc.load
220
+ while true
221
+ begin
222
+ s = ask('keychain> ')
223
+ if s == 'exit' or s == ''
224
+ exit
225
+ end
226
+ cmd(kc, s.split(' '))
227
+ rescue EOFError
228
+ puts "quitting..."
229
+ exit
230
+ rescue
231
+ raise
232
+ end
233
+ end
234
+ else
235
+ kc.load unless ARGV[0] == 'help' or ARGV[0] == 'gen'
236
+ cmd(kc, ARGV)
237
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: keychain
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.2.1
7
+ date: 2008-08-08 00:00:00 +02:00
8
+ summary: A simple shell tool for managing passwords
9
+ require_paths:
10
+ - lib
11
+ email: mikiobraun@gmail.com
12
+ homepage: http://ml.cs.tu-berlin.de/~mikio
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Mikio L. Braun
31
+ files:
32
+ - bin/keychain
33
+ - README
34
+ test_files: []
35
+
36
+ rdoc_options: []
37
+
38
+ extra_rdoc_files:
39
+ - README
40
+ executables:
41
+ - keychain
42
+ extensions: []
43
+
44
+ requirements: []
45
+
46
+ dependencies:
47
+ - !ruby/object:Gem::Dependency
48
+ name: crypt
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Version::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.1.4
55
+ version:
56
+ - !ruby/object:Gem::Dependency
57
+ name: highline
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Version::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.4.0
64
+ version: