passman 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bda4662265b49027fdbcd554dec1e3d3647a2ace
4
- data.tar.gz: 34836b929208a72a53171d148eb72ce1713793b2
3
+ metadata.gz: 3fd80581c44a6b45f671dee954c907546c1d0070
4
+ data.tar.gz: a6b7bb2c53cc7f49dbd46d780c2e8eeb98c1a569
5
5
  SHA512:
6
- metadata.gz: 039799e9ba6eadd3039554d51796129b66240011b74c25ca9f59ce892e42c73d51140dad085070198615e66a556f8842d986b6c1cb9e594ab64e3ff470543506
7
- data.tar.gz: 8dda4311d9e2afb3b405672caebc6332727963658c777883605739b3684e158790b4ff4e3fa6274e2ad8a91dbd7e1b79c81d04b261593e3973e1a57187687893
6
+ metadata.gz: f8843144a6727eb8d50eeddedcd98d5527da66f79ec892970acce16374b16036b655948d6a63f8ff60539c5b131b0194c72791d22b18c7f9993f65568c99b12c
7
+ data.tar.gz: ad5c45e1a5e9d802d73ee20a55689cb359bcadfec480b39c7624924ac792b2ab3aaa6daa48e51a1e64f83093bffe3d5cc5ffac54bd71bb0378e6a668b494d9a7
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # PassMan - Password Manager
2
- [![Gem Version](https://badge.fury.io/rb/passman.svg)]()
2
+ [![Gem Version](https://badge.fury.io/rb/passman.svg)](https://badge.fury.io/rb/passman)
3
3
  [![Dependency Status](https://gemnasium.com/badges/github.com/alebian/passman.svg)](https://gemnasium.com/github.com/alebian/passman)
4
4
  [![Build Status](https://travis-ci.org/alebian/passman.svg)](https://travis-ci.org/alebian/passman)
5
5
  [![Code Climate](https://codeclimate.com/github/alebian/passman/badges/gpa.svg)](https://codeclimate.com/github/alebian/passman)
6
6
  [![Test Coverage](https://codeclimate.com/github/alebian/passman/badges/coverage.svg)](https://codeclimate.com/github/alebian/passman/coverage)
7
7
  [![Inline docs](http://inch-ci.org/github/alebian/passman.svg)](http://inch-ci.org/github/alebian/passman)
8
8
 
9
- PassMan is a command line application that stores your passwords encripted with a symmetric-key algorithm. It also let's you save more information about your accounts such as recovery information and more.
9
+ PassMan is a command line application that stores your passwords encrypted with AES 256 symmetric-key algorithm. It also let's you save more information about your accounts such as recovery information and more.
10
10
 
11
11
  ## Installation
12
12
 
@@ -16,16 +16,46 @@ Run this in your terminal:
16
16
 
17
17
  ## Usage
18
18
 
19
- After installing the gem, you can use it in your command line:
19
+ PassMan will save your passwords in a file called 'passman.json' by default, you can tell PassMan to store the passwords in different files.
20
+
21
+ First of all you will need a 32 bit (or more) symmetric key. This will be used in the future to encrypt and decrypt your passwords but PassMan will not store that value. Everytime PassMan needs to encrypt or decrypt your passwords it will ask you for one key. You can tell PassMan to create a new secure random key if you want to:
22
+
23
+ ```
24
+ passman -g 32
25
+ # => c50647a4dde91848fb5edda217149258
26
+ ```
27
+
28
+ Once you have your key, write it down on paper or try to remember it. Now you can start saving your passwords.
29
+
30
+ ```
31
+ passman -a Twitter -u alebian -p MySuperPassword
32
+ ```
33
+
34
+ You will be prompted to insert you key and then PassMan will store your password.
35
+
36
+ Now you can retreive your passwords:
20
37
 
21
38
  ```
22
- passman
39
+ passman -r Twitter
23
40
  ```
24
41
 
25
- ```ruby
42
+ You can tell Passman to store your password in a different file:
26
43
 
27
44
  ```
45
+ passman -a Twitter -u alebian -p MySuperPassword -f ~/my_database
46
+ ```
47
+
48
+ You can list the stored accounts:
28
49
 
50
+ ```
51
+ passman -l
52
+ ```
53
+
54
+ You can delete your accounts:
55
+
56
+ ```
57
+ passman -d Twitter
58
+ ```
29
59
 
30
60
  ## Contributing
31
61
 
@@ -5,7 +5,7 @@ require 'optparse'
5
5
  require 'colorize'
6
6
  require 'io/console'
7
7
 
8
- options = {}
8
+ options = { length: 32 }
9
9
 
10
10
  begin
11
11
 
@@ -39,7 +39,7 @@ begin
39
39
  end
40
40
 
41
41
  opts.on('-g', '--generate [N]', Integer, 'Generates a new random password of N characters, or default if N is not provided') do |length|
42
- options[:length] = length
42
+ options[:length] = length unless length.nil? || length.empty?
43
43
  options[:generate] = true
44
44
  end
45
45
 
@@ -48,7 +48,7 @@ begin
48
48
  end
49
49
 
50
50
  opts.on('-v', '--version', 'Displays version') do
51
- puts "PassMan Version: #{Passman::VERSION}"
51
+ puts "PassMan Version: #{Passman::VERSION}".colorize(:yellow)
52
52
  exit
53
53
  end
54
54
 
@@ -60,52 +60,73 @@ begin
60
60
 
61
61
  parser.parse!
62
62
 
63
+ manager = Passman::Manager.new(options[:file])
64
+ key = ''
65
+ password = ''
66
+
63
67
  if options[:account]
64
68
 
65
- raise ArgumentError, 'No username provided.' unless options[:username]
66
- password = ''
67
69
  if options[:password]
68
70
  password = options[:password]
69
71
  else
70
- password = Passman.generate_password(options[:length])
72
+ password = manager.generate_password(options[:length])
73
+ puts "Password generated: #{password}".colorize(:yellow)
71
74
  end
72
75
 
73
- if Passman.get(options[:account], options[:file])
76
+ if manager.exist?(options[:account])
74
77
  print 'There is a username already stored. Do you want to overwrite it? [Y/n] '
75
78
  overwrite = gets
76
79
  exit unless overwrite == 'Y'
77
80
  puts ''
78
81
  end
79
82
 
80
- print 'Insert your symmetric-key: '
83
+ print 'Insert your symmetric-key:'
81
84
  key = STDIN.noecho(&:gets)
85
+ raise ArgumentError, 'Key cannot be empty' if key.empty?
82
86
  puts ''
83
- Passman.add(options[:account], options[:username], Passman::Crypto.encrypt(password, key.chomp), options[:file])
84
87
 
88
+ manager.add(options[:account], options[:username], password, key)
85
89
  puts 'Password successfully added'.colorize(:green)
86
90
 
87
91
  elsif options[:delete]
88
92
 
89
- Passman.delete(options[:delete], options[:file])
93
+ manager.delete(options[:delete])
90
94
  puts 'Password deleted'.colorize(:green)
91
95
 
92
96
  elsif options[:list]
93
97
 
94
- Passman.database(options[:file]).each do |account, data|
98
+ list = manager.list
99
+ puts 'No accounts stored' if list.empty?
100
+ list.each do |account, data|
95
101
  puts account.colorize(:yellow) + ' -> ' + data['username']
96
102
  end
97
103
 
98
104
  elsif options[:generate]
99
105
 
100
- puts Passman.generate_password(options[:length])
106
+ puts manager.generate_password(options[:length])
101
107
 
102
108
  elsif options[:retreive]
103
109
 
104
- account = Passman.get(options[:retreive], options[:file])
105
- print 'Insert your symmetric-key: '
110
+ unless manager.exist?(options[:retreive])
111
+ puts "The account doesn't exist"
112
+ exit
113
+ end
114
+
115
+ print 'Insert your symmetric-key:'
106
116
  key = STDIN.noecho(&:gets)
117
+ raise ArgumentError, 'Key cannot be empty' if key.empty?
107
118
  puts ''
108
- puts "Account: #{options[:retreive]}, Username: #{account['username']}, Password: #{Passman::Crypto.decrypt(account['password'], key)}"
119
+ account = manager.get(options[:retreive], key)
120
+ puts(
121
+ 'Account: ' + "#{account[0]}".colorize(:yellow) +
122
+ ', Username: ' + "#{account[1]['username']}".colorize(:yellow) +
123
+ ', Password: ' + "#{account[1]['password']}".colorize(:yellow)
124
+ )
125
+
126
+ elsif options[:remove]
127
+
128
+ manager.delete(options[:remove])
129
+ puts 'Deleted account'.colorize(:red)
109
130
 
110
131
  else
111
132
 
@@ -1,44 +1,7 @@
1
- require_relative 'passman/crypto'
1
+ require 'passman/crypto'
2
+ require 'passman/manager'
2
3
  require 'passman/password_generator'
3
4
  require 'passman/version'
4
- require 'json'
5
5
 
6
6
  module Passman
7
- DEFAULT_FILE = 'passman.json'.freeze
8
-
9
- def self.generate_password(length)
10
- Passman::PasswordGenerator.generate(length / 2)
11
- end
12
-
13
- def self.add(account, username, encrypted_password, file = nil)
14
- path = DEFAULT_FILE if file.nil?
15
- db = database(path)
16
- db[account.to_s] = { username: username, password: encrypted_password }
17
- write_database(db, path)
18
- end
19
-
20
- def self.delete(account, file = nil)
21
- path = DEFAULT_FILE if file.nil?
22
- db = database(path)
23
- db.delete(account.to_s)
24
- write_database(db, path)
25
- end
26
-
27
- def self.get(account, key, file = nil)
28
- path = DEFAULT_FILE if file.nil?
29
- db = database(path)
30
- db[account.to_s]
31
- end
32
-
33
- def self.database(file)
34
- return JSON.parse(File.read(file)) if File.exist?(file)
35
- {}
36
- end
37
-
38
- def self.write_database(data, path)
39
- File.delete(path) if File.exist?(path)
40
- file = File.open(path, 'w+')
41
- file.write(JSON.generate(data))
42
- file.close
43
- end
44
7
  end
@@ -3,11 +3,13 @@ require 'base64'
3
3
 
4
4
  module Passman
5
5
  class Crypto
6
+ MINIMUM_SIZE_KEY = 32
7
+
6
8
  class << self
7
9
  def encrypt(password, key)
8
10
  cipher = new_cipher
9
11
  cipher.encrypt
10
- cipher.key = key
12
+ cipher.key = sanitize_key(key)
11
13
  encrypted_password = cipher.update(password) + cipher.final
12
14
  Base64.encode64(encrypted_password)
13
15
  end
@@ -15,7 +17,7 @@ module Passman
15
17
  def decrypt(encrypted_password, key)
16
18
  cipher = new_cipher
17
19
  cipher.decrypt
18
- cipher.key = key
20
+ cipher.key = sanitize_key(key)
19
21
  decrypted_password = cipher.update(Base64.decode64(encrypted_password))
20
22
  decrypted_password << cipher.final
21
23
  end
@@ -25,6 +27,13 @@ module Passman
25
27
  def new_cipher
26
28
  OpenSSL::Cipher::AES.new(256, 'CBC')
27
29
  end
30
+
31
+ def sanitize_key(key)
32
+ raise ArgumentError, 'No key provided.' if key.nil? || key.empty?
33
+ sanitized = key
34
+ sanitized += key while sanitized.length < MINIMUM_SIZE_KEY
35
+ sanitized
36
+ end
28
37
  end
29
38
  end
30
39
  end
@@ -0,0 +1,78 @@
1
+ require 'passman/crypto'
2
+ require 'passman/password_generator'
3
+ require 'json'
4
+
5
+ module Passman
6
+ class Manager
7
+ DEFAULT_PATH = 'passman.json'.freeze
8
+
9
+ def initialize(file = nil)
10
+ @file_path = DEFAULT_PATH
11
+ @file_path = file unless file.nil?
12
+ end
13
+
14
+ def generate_password(length = 32)
15
+ Passman::PasswordGenerator.generate(length)
16
+ end
17
+
18
+ def add(account, username, password, key)
19
+ validate_add_arguments(account, username, password, key)
20
+ db = database
21
+ db[account.to_s] = { username: username, password: Passman::Crypto.encrypt(password, key) }
22
+ store_data(db)
23
+ end
24
+
25
+ def delete(account)
26
+ raise ArgumentError, 'No account provided.' unless valid?(account)
27
+ db = database
28
+ db.delete(account.to_s)
29
+ store_data(db)
30
+ end
31
+
32
+ def get(account, key)
33
+ validate_get_arguments(account, key)
34
+ data = database[account.to_s]
35
+ [account.to_s, { 'username' => data['username'],
36
+ 'password' => Passman::Crypto.decrypt(data['password'], key) }]
37
+ end
38
+
39
+ def exist?(account)
40
+ raise ArgumentError, 'No account provided.' unless valid?(account)
41
+ !(!database[account.to_s])
42
+ end
43
+
44
+ def list
45
+ database
46
+ end
47
+
48
+ private
49
+
50
+ def validate_add_arguments(account, username, password, key)
51
+ raise ArgumentError, 'No account provided.' unless valid?(account)
52
+ raise ArgumentError, 'No username provided.' unless valid?(username)
53
+ raise ArgumentError, 'No password provided.' unless valid?(password)
54
+ raise ArgumentError, 'No key provided.' unless valid?(key)
55
+ end
56
+
57
+ def validate_get_arguments(account, key)
58
+ raise ArgumentError, 'No account provided.' unless valid?(account)
59
+ raise ArgumentError, 'No key provided.' unless valid?(key)
60
+ end
61
+
62
+ def valid?(argument)
63
+ !(argument.nil? || argument.empty?)
64
+ end
65
+
66
+ def database
67
+ return JSON.parse(File.read(@file_path)) if File.exist?(@file_path)
68
+ {}
69
+ end
70
+
71
+ def store_data(data)
72
+ File.delete(@file_path) if File.exist?(@file_path)
73
+ file = File.open(@file_path, 'w+')
74
+ file.write(JSON.generate(data))
75
+ file.close
76
+ end
77
+ end
78
+ end
@@ -3,7 +3,7 @@ require 'securerandom'
3
3
  module Passman
4
4
  class PasswordGenerator
5
5
  def self.generate(length)
6
- SecureRandom.hex(length)
6
+ SecureRandom.hex(length.to_i / 2)
7
7
  end
8
8
  end
9
9
  end
@@ -1,3 +1,3 @@
1
1
  module Passman
2
- VERSION = '0.0.1'.freeze
2
+ VERSION = '0.0.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Bezdjian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-23 00:00:00.000000000 Z
11
+ date: 2016-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -103,6 +103,7 @@ files:
103
103
  - bin/passman
104
104
  - lib/passman.rb
105
105
  - lib/passman/crypto.rb
106
+ - lib/passman/manager.rb
106
107
  - lib/passman/password_generator.rb
107
108
  - lib/passman/version.rb
108
109
  - passman.gemspec