passw3rd 0.0.11 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/lib/passw3rd/key_loader.rb +3 -2
- data/lib/passw3rd/password_service.rb +52 -28
- data/lib/passw3rd/version.rb +1 -1
- data/spec/config_spec.rb +3 -0
- data/spec/password_service_spec.rb +14 -0
- data/spec/spec_helper.rb +1 -0
- data/test/password_service_test.rb +19 -1
- metadata +5 -2
data/History.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
=== 0.1.0 / 2011-10-31
|
2
|
+
|
3
|
+
Finally some real life support
|
4
|
+
* Defaults to aes-256 for regulatory compliance (Thanks Edward Bonver)
|
5
|
+
* loads URIs, so password files can live anywhere (Thanks Ben Duong)
|
6
|
+
* Internals: code cleanup (Thanks @xternal), guard + test::unit + rspec love, better configuration options (thanks again @xternal)
|
7
|
+
|
1
8
|
=== 0.0.11 / 2011-10-12
|
2
9
|
|
3
10
|
Keys/ivs were being written as arrays, broke openssl command line compatibility:
|
data/lib/passw3rd/key_loader.rb
CHANGED
@@ -7,7 +7,7 @@ module Passw3rd
|
|
7
7
|
|
8
8
|
def self.load(path=nil)
|
9
9
|
if path.nil?
|
10
|
-
path =
|
10
|
+
path = ::Passw3rd::PasswordService.key_file_dir
|
11
11
|
end
|
12
12
|
|
13
13
|
begin
|
@@ -29,7 +29,8 @@ module Passw3rd
|
|
29
29
|
path = ENV['HOME']
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
# d'oh!
|
33
|
+
cipher = OpenSSL::Cipher::Cipher.new(::Passw3rd::PasswordService.cipher_name)
|
33
34
|
iv = cipher.random_iv
|
34
35
|
key = cipher.random_key
|
35
36
|
|
@@ -1,37 +1,46 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
1
3
|
module Passw3rd
|
2
4
|
class PasswordService
|
3
|
-
|
4
|
-
|
5
|
+
class << self
|
6
|
+
attr_writer :password_file_dir
|
7
|
+
def password_file_dir
|
8
|
+
@password_file_dir || ENV.fetch("HOME")
|
9
|
+
end
|
5
10
|
|
6
|
-
|
7
|
-
|
11
|
+
attr_writer :key_file_dir
|
12
|
+
def key_file_dir
|
13
|
+
@key_file_dir || ENV.fetch("HOME")
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_writer :cipher_name
|
17
|
+
def cipher_name
|
18
|
+
@cipher_name || 'aes-256-cbc'
|
19
|
+
end
|
8
20
|
end
|
9
21
|
|
10
|
-
def self.
|
11
|
-
|
12
|
-
end
|
22
|
+
def self.configure(&block)
|
23
|
+
instance_eval &block
|
24
|
+
end
|
13
25
|
|
14
|
-
def self.get_password (password_file, key_path=
|
15
|
-
|
16
|
-
|
26
|
+
def self.get_password (password_file, key_path = key_file_dir)
|
27
|
+
uri = _parse_uri(password_file)
|
28
|
+
encoded_password = Base64.decode64(open(uri.to_s) { |f| f.read })
|
29
|
+
decrypt(encoded_password, key_path)
|
17
30
|
end
|
18
31
|
|
19
|
-
def self.write_password_file(password, output_path, key_path =
|
20
|
-
enc_password =
|
32
|
+
def self.write_password_file(password, output_path, key_path = key_file_dir)
|
33
|
+
enc_password = encrypt(password, key_path)
|
21
34
|
base64pw = Base64.encode64(enc_password)
|
22
|
-
path = File.join(
|
23
|
-
|
35
|
+
path = File.join(password_file_dir, output_path)
|
36
|
+
open(path, 'w') { |f| f.write base64pw }
|
24
37
|
path
|
25
38
|
end
|
26
39
|
|
27
|
-
def self.encrypt(password, key_path =
|
28
|
-
raise "password cannot be blank" if password.empty?
|
40
|
+
def self.encrypt(password, key_path = key_file_dir)
|
41
|
+
raise ArgumentError, "password cannot be blank" if password.to_s.empty?
|
29
42
|
|
30
|
-
|
31
|
-
cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
|
32
|
-
cipher.encrypt
|
33
|
-
cipher.key = pair.key
|
34
|
-
cipher.iv = pair.iv
|
43
|
+
cipher = cipher_setup(:encrypt, key_path)
|
35
44
|
begin
|
36
45
|
e = cipher.update(password)
|
37
46
|
e << cipher.final
|
@@ -41,19 +50,34 @@ module Passw3rd
|
|
41
50
|
end
|
42
51
|
end
|
43
52
|
|
44
|
-
def self.decrypt(cipher_text, key_path =
|
45
|
-
|
46
|
-
cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
|
47
|
-
cipher.decrypt
|
48
|
-
cipher.key = pair.key
|
49
|
-
cipher.iv = pair.iv
|
53
|
+
def self.decrypt(cipher_text, key_path = key_file_dir)
|
54
|
+
cipher = cipher_setup(:decrypt, key_path)
|
50
55
|
begin
|
51
56
|
d = cipher.update(cipher_text)
|
52
57
|
d << cipher.final
|
53
58
|
rescue OpenSSL::Cipher::CipherError => err
|
54
|
-
puts "
|
59
|
+
puts "Couldn't decrypt password. Are you using the right keys?"
|
55
60
|
raise err
|
56
61
|
end
|
57
62
|
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def self.cipher_setup(method, key_path)
|
67
|
+
pair = KeyLoader.load(key_path)
|
68
|
+
cipher = OpenSSL::Cipher::Cipher.new(cipher_name)
|
69
|
+
cipher.send(method)
|
70
|
+
cipher.key = pair.key
|
71
|
+
cipher.iv = pair.iv
|
72
|
+
cipher
|
73
|
+
end
|
74
|
+
|
75
|
+
def self._parse_uri password_file
|
76
|
+
unless (password_file =~ URI::regexp(['ftp', 'http', 'https', 'file'])).nil?
|
77
|
+
URI.parse(password_file)
|
78
|
+
else
|
79
|
+
File.join(password_file_dir, password_file)
|
80
|
+
end
|
81
|
+
end
|
58
82
|
end
|
59
83
|
end
|
data/lib/passw3rd/version.rb
CHANGED
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ::Passw3rd::PasswordService do
|
4
|
+
describe "#_parse_uri" do
|
5
|
+
it "detects uris" do
|
6
|
+
::Passw3rd::PasswordService._parse_uri("http://example.com").should be_is_a URI::HTTP
|
7
|
+
end
|
8
|
+
|
9
|
+
it "falls back to a file path" do
|
10
|
+
URI.should_not_receive(:parse)
|
11
|
+
::Passw3rd::PasswordService._parse_uri("/some/file/some/where/over/the/rainbow").should be_is_a String
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'passw3rd'
|
@@ -11,6 +11,7 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
11
11
|
|
12
12
|
::Passw3rd::KeyLoader.create_key_iv_file(Dir.tmpdir)
|
13
13
|
::Passw3rd::PasswordService.key_file_dir = Dir.tmpdir
|
14
|
+
::Passw3rd::PasswordService.cipher_name = 'aes-256-cbc'
|
14
15
|
end
|
15
16
|
|
16
17
|
def test_enc_dec
|
@@ -20,6 +21,14 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
20
21
|
assert_equal(@random_string, dec)
|
21
22
|
end
|
22
23
|
|
24
|
+
def test_enc_raise_on_blank_password
|
25
|
+
assert_raise(ArgumentError) { ::Passw3rd::PasswordService.encrypt("") }
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_enc_raise_on_nil_password
|
29
|
+
assert_raise(ArgumentError) { ::Passw3rd::PasswordService.encrypt(nil) }
|
30
|
+
end
|
31
|
+
|
23
32
|
def test_set_and_get_password
|
24
33
|
password_file = ::Passw3rd::PasswordService.write_password_file(@random_string, "test")
|
25
34
|
decrypted = Passw3rd::PasswordService.get_password("test")
|
@@ -33,6 +42,15 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
33
42
|
decrypted = Passw3rd::PasswordService.get_password("test2")
|
34
43
|
assert_equal(@random_string, decrypted)
|
35
44
|
end
|
45
|
+
|
46
|
+
def test_configure_with_block
|
47
|
+
Passw3rd::PasswordService.configure do |c|
|
48
|
+
c.password_file_dir = "/tmp/"
|
49
|
+
c.cipher_name = "aes-256-cbc"
|
50
|
+
end
|
51
|
+
assert_equal(Passw3rd::PasswordService.password_file_dir, "/tmp/")
|
52
|
+
assert_equal(Passw3rd::PasswordService.cipher_name, "aes-256-cbc")
|
53
|
+
end
|
36
54
|
|
37
55
|
def test_gen_key
|
38
56
|
enc = ::Passw3rd::PasswordService.encrypt(@random_string)
|
@@ -44,4 +62,4 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
44
62
|
def sudorandumb
|
45
63
|
Digest::SHA1.hexdigest(Time.now.to_s.split(//).sort_by{rand}.join)
|
46
64
|
end
|
47
|
-
end
|
65
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passw3rd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-31 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: Generate a key/iv file, generate passwords, and store encrypted files
|
15
15
|
in source control, keep the key/iv safe!
|
@@ -31,6 +31,9 @@ files:
|
|
31
31
|
- lib/passw3rd.rb
|
32
32
|
- bin/passw3rd
|
33
33
|
- test/password_service_test.rb
|
34
|
+
- spec/config_spec.rb
|
35
|
+
- spec/password_service_spec.rb
|
36
|
+
- spec/spec_helper.rb
|
34
37
|
homepage: https://github.com/oreoshake/passw3rd
|
35
38
|
licenses: []
|
36
39
|
post_install_message:
|