passw3rd 0.0.11 → 0.1.0

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.
@@ -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: