passw3rd 0.0.11 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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:
@@ -7,7 +7,7 @@ module Passw3rd
7
7
 
8
8
  def self.load(path=nil)
9
9
  if path.nil?
10
- path = ENV['HOME']
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
- cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
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
- @@password_file_dir = ENV["HOME"]
4
- @@key_file_dir = ENV["HOME"]
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
- def self.password_file_dir= dir
7
- @@password_file_dir = dir
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.key_file_dir= dir
11
- @@key_file_dir = dir
12
- end
22
+ def self.configure(&block)
23
+ instance_eval &block
24
+ end
13
25
 
14
- def self.get_password (password_file, key_path=nil)
15
- encoded_password = Base64.decode64(IO.readlines(File.join(@@password_file_dir, password_file)).join)
16
- PasswordService.decrypt(encoded_password, key_path || @@key_file_dir)
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 = nil)
20
- enc_password = PasswordService.encrypt(password, key_path || @@key_file_dir)
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(@@password_file_dir, output_path)
23
- File.open(path, 'w') { |f| f.write base64pw }
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 = nil)
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
- pair = KeyLoader.load(key_path || @@key_file_dir)
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 = nil)
45
- pair = KeyLoader.load(key_path || @@key_file_dir)
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 "Coudln't decrypt password. Are you using the right keys?"
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
@@ -1,3 +1,3 @@
1
1
  module Passw3rd
2
- Version = VERSION = '0.0.11'
2
+ Version = VERSION = '0.1.0'
3
3
  end
@@ -0,0 +1,3 @@
1
+ describe "Config" do
2
+ it "does stuff"
3
+ end
@@ -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
@@ -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.11
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-13 00:00:00.000000000Z
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: