passbox 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +61 -21
- data/bin/passbox +28 -33
- data/lib/passbox.rb +8 -1
- data/lib/passbox/accounts.rb +75 -0
- data/lib/passbox/auth.rb +57 -23
- data/lib/passbox/crud/create.rb +121 -0
- data/lib/passbox/crud/delete.rb +13 -0
- data/lib/passbox/crud/read.rb +33 -0
- data/lib/passbox/crud/update.rb +36 -0
- data/lib/passbox/helpers/colourize.rb +27 -0
- data/lib/passbox/helpers/options.rb +37 -0
- data/lib/passbox/helpers/strings.rb +53 -0
- data/lib/passbox/init.rb +4 -2
- data/lib/passbox/version +1 -1
- metadata +15 -8
- data/lib/passbox/crud.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f7ecaf34fb41df4dc4b08c057d4850dd824fb2008f42af37900fada39b55dab
|
4
|
+
data.tar.gz: faaca8fd5355c9ee2b519afbfe6190efe20bb9f53cb2ac4731547d3f12d62f6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa21924d9a86c26eb5c4cbeefaa376fb46bc9dee134d308f2b51994f1c74a5b90ee81df72c0ca551a8bb2a9ec0a35c559af1068dcc39ac17a7f0e7f1fd3e822b
|
7
|
+
data.tar.gz: 762e06d5b9a53e9787c6b63aaa1410f6aded92a527e8a6b6350b7610497e94cd9d3ac21b1bdac59bf046c48eaa80933a412a89eb9fb931e715a3394cd8672f3e
|
data/LICENSE
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Kaushal Rupani
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -5,6 +5,8 @@ A Ruby based minimalistic offline cli password manager using strong AES encrypti
|
|
5
5
|
## Table of Contents
|
6
6
|
- [1. Introduction](#introduction)
|
7
7
|
- [2. Installation](#install)
|
8
|
+
- [2a. Homebrew](#brew)
|
9
|
+
- [2b. Rubygems](#gem)
|
8
10
|
- [3. Usage](#usage)
|
9
11
|
- [3a. Initial Setup](#init)
|
10
12
|
- [3b. Add a new password](#add)
|
@@ -28,11 +30,21 @@ Note: I wouldn't say its uncrackable as nothing in the world is.
|
|
28
30
|
|
29
31
|
## <a name="install"></a> 2. Installation
|
30
32
|
Passbox currently only supports Linux/MacOS based envvrionments.
|
31
|
-
|
32
|
-
|
33
|
+
|
34
|
+
### <a name="brew"></a> 2a. Homebrew
|
35
|
+
Easiest way to install on macos is using [Homebrew](https://brew.sh)
|
36
|
+
```console
|
37
|
+
$ brew tap krupani/homebrew-formulae
|
38
|
+
$ brew install passbox
|
39
|
+
```
|
40
|
+
|
41
|
+
### <a name="gem"></a> 2b. Rubygems
|
42
|
+
If you have a working installation of ruby, passbox can be installed as a rubygem simply by using gem command.
|
43
|
+
|
44
|
+
```console
|
45
|
+
$ gem install passbox
|
46
|
+
```
|
33
47
|
|
34
|
-
``` gem install passbox ```
|
35
|
-
|
36
48
|
|
37
49
|
## <a name="usage"></a> 3. Usage
|
38
50
|
As mentioned above, passbox is a cli based utility. Below are few basic functions which you can perform.
|
@@ -41,25 +53,45 @@ As mentioned above, passbox is a cli based utility. Below are few basic function
|
|
41
53
|
Before starting, you need to setup the passbox utility which will include creating a base directory and creating your master password.
|
42
54
|
This can be easily done using the init command as follows:
|
43
55
|
|
44
|
-
```
|
56
|
+
```console
|
57
|
+
$ passbox init
|
58
|
+
```
|
45
59
|
|
46
60
|
This will ask you create a master password, its recommended you create this one time master password really complex and more than 10 characters to make it really difficult to brute force.
|
47
61
|
|
48
62
|
### <a name="add"></a> 3b. Add a new password
|
49
63
|
Once passbox is setup, you can start adding password. It can be done using the create command which can be used as follows:
|
50
64
|
|
51
|
-
```
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
-
|
57
|
-
-
|
65
|
+
```console
|
66
|
+
$ passbox add
|
67
|
+
```
|
68
|
+
|
69
|
+
This command will give you an option to chose the type of secret you want to add into passbox:
|
70
|
+
- Login
|
71
|
+
- Username<sup>*</sup>
|
72
|
+
- Password<sup>*</sup>
|
73
|
+
- Url (optional)
|
74
|
+
- Note (optional)
|
75
|
+
- Pin (Pin)
|
76
|
+
- Pin<sup>*</sup>
|
77
|
+
- Note (optional)
|
78
|
+
- Credit / Debit Card
|
79
|
+
- Card Number<sup>*</sup>
|
80
|
+
- Card Expiry<sup>*</sup>
|
81
|
+
- Card CVV<sup>*</sup>
|
82
|
+
- Card Pin (optional)
|
83
|
+
- Note (optional)
|
84
|
+
|
85
|
+
After chosing an option above, the utility will ask you 2 questions:
|
86
|
+
- to create a new account name.
|
87
|
+
- to enter your master password for authentication purposes.
|
58
88
|
|
59
89
|
### <a name="read"></a> 3c. Read an existing password
|
60
90
|
Once you have saved your password, you can view them as and when needed, authenticating using your master password and entering your account name of the password you want to view, as follows :
|
61
91
|
|
62
|
-
```
|
92
|
+
```console
|
93
|
+
$ passbox read
|
94
|
+
```
|
63
95
|
|
64
96
|
This command will ask you 2 questions:
|
65
97
|
- to enter you account name for which you want to view the password.
|
@@ -68,28 +100,36 @@ This command will ask you 2 questions:
|
|
68
100
|
### <a name="update"></a> 3d. Update an existing password
|
69
101
|
You can update your account details (username and password) when needed, authenticating using your master password and entering your account name you need to update :
|
70
102
|
|
71
|
-
```
|
103
|
+
```console
|
104
|
+
$ passbox update
|
105
|
+
```
|
72
106
|
|
73
|
-
This command will ask you
|
107
|
+
This command will first ask you 2 questions:
|
74
108
|
- First to enter you account name for which you want to update the password.
|
75
109
|
- Next, to enter you master password for authentication purposes.
|
76
|
-
|
77
|
-
|
110
|
+
|
111
|
+
Then depending the account type, appropriate fields will be asked to be filled. If you wish to not change the exisitng value, just hit enter and move onto next field or enter a new value to update the field to new value.
|
78
112
|
|
79
113
|
### <a name="delete"></a> 3e. Delete an existing account
|
80
114
|
You can delete an existing account, if you do not need it anymore. It can be done using the delete command and does not require any kind of authentication.
|
81
115
|
|
82
|
-
```
|
116
|
+
```console
|
117
|
+
$ passbox delete
|
118
|
+
```
|
83
119
|
|
84
|
-
This command will
|
120
|
+
This command will first ask you 2 questions:
|
121
|
+
- First to enter you account name which you want to delete.
|
122
|
+
- Next, to enter you master password for authentication purposes.
|
85
123
|
|
86
124
|
### <a name="list"></a> 3f. List all available accounts
|
87
125
|
You can list all accounts you have using the following command without any authentication required.
|
88
126
|
|
89
|
-
```
|
127
|
+
```console
|
128
|
+
$ passbox list
|
129
|
+
```
|
90
130
|
|
91
131
|
## <a name="contributing"></a> 4. Contributing
|
92
132
|
Ideas and suggestions are always always most welcome. Please fork this code and feel free to add any updates, suggestions etc and create a pull request.
|
93
133
|
|
94
134
|
## <a name="issues"></a> 5. Issues
|
95
|
-
If you face any problem related to syntax, usability, documentation then please raise an [
|
135
|
+
If you face any problem related to syntax, usability, documentation then please raise an [issue](https://github.com/krupani/passbox/issues) . Please note to add details of the issue you are facing.
|
data/bin/passbox
CHANGED
@@ -5,64 +5,59 @@ require 'passbox'
|
|
5
5
|
def print_help
|
6
6
|
puts <<HELP
|
7
7
|
|
8
|
-
|
8
|
+
Commands
|
9
9
|
|
10
|
-
|
10
|
+
-v, version Prints the version of passbox.
|
11
|
+
Usage: passbox version | passbox -v | passbox --version
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
Usage: passbox --version | passbox -v
|
13
|
+
-h, help Prints help information
|
14
|
+
Usage: passbox help | passbox -h | passbox --help
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
-i, init Setup a passbox store and create master password.
|
17
|
+
Usage: passbox init | passbox -i
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
ls, list Lists all accounts in passbox.
|
20
|
+
Usage: passbox list | passbox ls
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
(No authentication required.)
|
22
|
+
+, add add a new account into passbox.
|
23
|
+
Usage: passbox add | passbox +
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
(Authentication required.)
|
25
|
+
=, read read an account present in passbox.
|
26
|
+
Usage: passbox read | passbox =
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
existing account present in passbox.
|
36
|
-
(Authentication required.)
|
37
|
-
|
38
|
-
delete : delete an account from passbox.
|
39
|
-
(Authentication required.)
|
28
|
+
++, update update details of an account present in passbox.
|
29
|
+
Usage: passbox update | passbox ++
|
30
|
+
|
31
|
+
-, delete delete an account from passbox.
|
32
|
+
Usage: passbox delete | passbox del | passbox -
|
40
33
|
|
41
34
|
HELP
|
42
35
|
end
|
43
36
|
|
44
37
|
if ARGV.length == 0
|
45
38
|
print_help
|
46
|
-
|
39
|
+
elsif ARGV.length == 1
|
47
40
|
cmd = ARGV.shift
|
48
41
|
case(cmd.downcase)
|
49
42
|
when "help", "--help", "-h"
|
50
43
|
print_help
|
51
44
|
when 'version', '--version', '-v'
|
52
45
|
puts File.read(File.expand_path("../../lib/passbox/version", __FILE__))
|
53
|
-
when "init"
|
46
|
+
when "init", "-i"
|
54
47
|
init
|
55
|
-
when "add"
|
48
|
+
when "+", "add"
|
56
49
|
create_pass
|
57
|
-
when "read"
|
50
|
+
when "=", "read"
|
58
51
|
read_pass
|
59
|
-
when "update"
|
52
|
+
when "++", "update"
|
60
53
|
update_pass
|
61
|
-
when "delete"
|
54
|
+
when "-", "delete", "del"
|
62
55
|
delete_pass
|
63
|
-
when "list"
|
56
|
+
when "list", "ls"
|
64
57
|
list_of_accounts
|
65
58
|
else
|
66
|
-
puts "Invalid Command. Enter 'passbox help' to show usage"
|
59
|
+
puts "Invalid Command. Enter 'passbox help' to show usage.".red
|
67
60
|
end
|
61
|
+
else
|
62
|
+
puts "Too many arguments. Enter 'passbox help' to show usage.".red
|
68
63
|
end
|
data/lib/passbox.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
require 'passbox/aes'
|
2
2
|
require 'passbox/auth'
|
3
3
|
require 'passbox/init'
|
4
|
-
require 'passbox/
|
4
|
+
require 'passbox/accounts'
|
5
|
+
require 'passbox/crud/create'
|
6
|
+
require 'passbox/crud/read'
|
7
|
+
require 'passbox/crud/update'
|
8
|
+
require 'passbox/crud/delete'
|
9
|
+
require 'passbox/helpers/options'
|
10
|
+
require 'passbox/helpers/colourize'
|
11
|
+
require 'passbox/helpers/strings'
|
5
12
|
include Passbox
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Passbox
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
def list_of_accounts
|
5
|
+
check_passbox
|
6
|
+
empty = true
|
7
|
+
files_ext = Dir["#{$pbdir}/*.pb"]
|
8
|
+
print "\nLogin & Passwords\n".bold.cyan if files_ext.size != 0
|
9
|
+
files_ext.each_with_index do |file,i|
|
10
|
+
print "#{i+1}. #{file.split('/').last.split('.').first}\n".cyan
|
11
|
+
empty = false
|
12
|
+
end
|
13
|
+
files_ext = Dir["#{$pbdir}/*.pn"]
|
14
|
+
print "\nAccount Pins\n".bold.magenta if files_ext.size != 0
|
15
|
+
files_ext.each_with_index do |file,i|
|
16
|
+
print "#{i+1}. #{file.split('/').last.split('.').first}\n".magenta
|
17
|
+
empty = false
|
18
|
+
end
|
19
|
+
files_ext = Dir["#{$pbdir}/*.cc"]
|
20
|
+
print "\nCredit & Debit Cards\n".bold.yellow if files_ext.size != 0
|
21
|
+
files_ext.each_with_index do |file,i|
|
22
|
+
print "#{i+1}. #{file.split('/').last.split('.').first}\n".yellow
|
23
|
+
empty = false
|
24
|
+
end
|
25
|
+
print no_accounts.yellow if empty
|
26
|
+
end
|
27
|
+
|
28
|
+
def verify_account
|
29
|
+
print enter_account_name
|
30
|
+
acc = user_input
|
31
|
+
files = Dir.glob("#{$pbdir}/#{acc}.{pb,pn,cc}")
|
32
|
+
if files.size == 0
|
33
|
+
print account_not_found
|
34
|
+
exit(0)
|
35
|
+
elsif files.size == 1
|
36
|
+
return files.first
|
37
|
+
else
|
38
|
+
files.each_with_index do |file, i|
|
39
|
+
filename = file.split("/").last.split(".").first
|
40
|
+
fileext = file.split("/").last.split(".").last
|
41
|
+
case fileext
|
42
|
+
when "pb"
|
43
|
+
print "\n#{i+1}: #{filename} - Login & Password Category"
|
44
|
+
when "pn"
|
45
|
+
print "\n#{i+1}: #{filename} - Account Pins Category"
|
46
|
+
when "cc"
|
47
|
+
print "\n#{i+1}: #{filename} - Credit/Debit Card Category"
|
48
|
+
else
|
49
|
+
# do nothing
|
50
|
+
end
|
51
|
+
end
|
52
|
+
print multiple_accounts
|
53
|
+
option = user_input.to_i
|
54
|
+
if (1..files.size).include?(option)
|
55
|
+
return files[option-1]
|
56
|
+
else
|
57
|
+
print invalid_selection.red
|
58
|
+
exit(0)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def does_account_exists(acc, type)
|
64
|
+
files = Dir.glob("#{$pbdir}/#{acc}.{pb,pn,cc}")
|
65
|
+
if files.size == 0
|
66
|
+
return false
|
67
|
+
else
|
68
|
+
files.each do |file|
|
69
|
+
return true if (file.split(".").last == $options[type])
|
70
|
+
end
|
71
|
+
return false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/lib/passbox/auth.rb
CHANGED
@@ -3,37 +3,71 @@ module Passbox
|
|
3
3
|
require 'digest'
|
4
4
|
|
5
5
|
def get_password_from_user(action=:account)
|
6
|
-
|
7
|
-
|
6
|
+
case action
|
7
|
+
when :account
|
8
|
+
print enter_account_password
|
8
9
|
return password_input(action)
|
9
|
-
|
10
|
+
when :pin
|
11
|
+
print enter_account_pin
|
12
|
+
return password_input(action)
|
13
|
+
when :cvv
|
14
|
+
print enter_cc_cvv
|
15
|
+
return password_input(action)
|
16
|
+
when :card_pin
|
17
|
+
print enter_cc_pin
|
18
|
+
return password_input(action)
|
19
|
+
when :master
|
20
|
+
attempt = 0
|
10
21
|
while(true)
|
11
|
-
|
22
|
+
attempt = attempt + 1;
|
23
|
+
print create_master_password
|
12
24
|
pass256 = password_input(action)
|
13
|
-
|
25
|
+
if pass256
|
26
|
+
print re_enter_master_password
|
27
|
+
re_pass256 = password_input(action)
|
28
|
+
if re_pass256 == pass256
|
29
|
+
print pb_setup_complete.bold.green
|
30
|
+
return pass256
|
31
|
+
else
|
32
|
+
print passwords_mismatch.bold.red
|
33
|
+
exit(0);
|
34
|
+
end
|
35
|
+
else
|
36
|
+
print password_validation.red
|
37
|
+
end
|
38
|
+
if attempt == 3
|
39
|
+
print too_many_attempts.bold.red
|
40
|
+
exit(0)
|
41
|
+
end
|
14
42
|
end
|
15
|
-
|
16
|
-
print
|
43
|
+
when :auth
|
44
|
+
print enter_master_password
|
17
45
|
return password_input(action)
|
18
46
|
end
|
19
47
|
end
|
20
48
|
|
21
49
|
def password_input(action)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
50
|
+
begin
|
51
|
+
pass = STDIN.noecho(&:gets).chomp
|
52
|
+
rescue Interrupt
|
53
|
+
puts thank_you.cyan
|
54
|
+
exit(0)
|
55
|
+
end
|
56
|
+
case action
|
57
|
+
when :master, :auth
|
58
|
+
if (pass.length < 8)
|
59
|
+
if (action == :master)
|
60
|
+
return false
|
61
|
+
elsif (action == :auth)
|
62
|
+
print invalid_password.bold.red
|
63
|
+
exit(0)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
return Digest::SHA256.hexdigest(pass)
|
67
|
+
end
|
34
68
|
else
|
35
69
|
print("\n")
|
36
|
-
return
|
70
|
+
return pass
|
37
71
|
end
|
38
72
|
end
|
39
73
|
|
@@ -41,11 +75,11 @@ module Passbox
|
|
41
75
|
pass256User = get_password_from_user(:auth)
|
42
76
|
pass256File = decrypt($passfile, pass256User)
|
43
77
|
if pass256File == pass256User
|
44
|
-
print
|
78
|
+
print auth_success.bold.green
|
45
79
|
return pass256File
|
46
80
|
else
|
47
|
-
print
|
48
|
-
|
81
|
+
print auth_failed.bold.red
|
82
|
+
exit(0)
|
49
83
|
end
|
50
84
|
end
|
51
85
|
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Passbox
|
2
|
+
|
3
|
+
def create_pass
|
4
|
+
check_passbox
|
5
|
+
option = select_option
|
6
|
+
key = passbox_auth
|
7
|
+
acc = create_account(option, key)
|
8
|
+
case option
|
9
|
+
when 1
|
10
|
+
login(acc, key)
|
11
|
+
when 2
|
12
|
+
pin(acc, key)
|
13
|
+
when 3
|
14
|
+
cc(acc, key)
|
15
|
+
else
|
16
|
+
exit(0)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_account(option, key)
|
21
|
+
attempts = 0
|
22
|
+
while(true)
|
23
|
+
if attempts == 3
|
24
|
+
print too_many_attempts.bold.red
|
25
|
+
exit(0)
|
26
|
+
end
|
27
|
+
print enter_account_name
|
28
|
+
acc = user_input.downcase
|
29
|
+
if acc.empty?
|
30
|
+
print account_name_blank.red
|
31
|
+
attempts = attempts + 1
|
32
|
+
next;
|
33
|
+
end
|
34
|
+
if (acc.count("a-z0-9_-") == acc.length)
|
35
|
+
account_exists = does_account_exists(acc, option)
|
36
|
+
if account_exists
|
37
|
+
print account_already_exists.red
|
38
|
+
attempts = attempts + 1
|
39
|
+
next;
|
40
|
+
end
|
41
|
+
break
|
42
|
+
else
|
43
|
+
print account_name_invalid
|
44
|
+
attempts = attempts + 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
return acc
|
48
|
+
end
|
49
|
+
|
50
|
+
def login(acc, key, action=:create)
|
51
|
+
attempts = 0
|
52
|
+
hash = {}
|
53
|
+
hash["username"] = fill_manadatory_field(enter_username, username_blank, action)
|
54
|
+
hash["password"] = fill_manadatory_field("", password_blank, action, :account)
|
55
|
+
print enter_url
|
56
|
+
url = user_input
|
57
|
+
hash["url"] = url unless url.empty?
|
58
|
+
print enter_note
|
59
|
+
note = user_input
|
60
|
+
hash["note"] = note unless note.empty?
|
61
|
+
return hash if action == :update
|
62
|
+
json = hash.to_json
|
63
|
+
encrypt(json, key, "#{$pbdir}/#{acc}.pb")
|
64
|
+
print "Account #{acc} has been successfully created!! \n\n".green
|
65
|
+
end
|
66
|
+
|
67
|
+
def pin(acc, key, action = :create)
|
68
|
+
attempts = 0
|
69
|
+
hash = {}
|
70
|
+
hash["pin"] = fill_manadatory_field("", pin_blank, action, :pin)
|
71
|
+
print enter_note
|
72
|
+
note = user_input
|
73
|
+
hash["note"] = note unless note.empty?
|
74
|
+
return hash if action == :update
|
75
|
+
json = hash.to_json
|
76
|
+
encrypt(json, key, "#{$pbdir}/#{acc}.pn")
|
77
|
+
print "Account #{acc} has been successfully created!! \n\n".green
|
78
|
+
end
|
79
|
+
|
80
|
+
def cc(acc, key, action = :create)
|
81
|
+
attempts = 0
|
82
|
+
hash = {}
|
83
|
+
hash["card_number"] = fill_manadatory_field(enter_cc_no, cc_no_blank, action)
|
84
|
+
hash["card_expiry"] = fill_manadatory_field(enter_cc_exp, cc_exp_blank, action)
|
85
|
+
hash["card_cvv"] = fill_manadatory_field("", cc_cvv_blank, action, :cvv)
|
86
|
+
cc_pin = get_password_from_user(:card_pin)
|
87
|
+
hash["card_pin"] = cc_pin unless cc_pin.empty?
|
88
|
+
print enter_note
|
89
|
+
note = user_input
|
90
|
+
hash["note"] = note unless note.empty?
|
91
|
+
return hash if action == :update
|
92
|
+
json = hash.to_json
|
93
|
+
encrypt(json, key, "#{$pbdir}/#{acc}.cc")
|
94
|
+
print "Account #{acc} has been successfully created!! \n\n".green
|
95
|
+
end
|
96
|
+
|
97
|
+
def fill_manadatory_field(enter_message, blank_message, action=:create, type=nil)
|
98
|
+
attempts = 0
|
99
|
+
while(true)
|
100
|
+
if attempts == 3
|
101
|
+
print too_many_attempts.bold.red
|
102
|
+
exit(0)
|
103
|
+
end
|
104
|
+
if (type.nil?)
|
105
|
+
print enter_message
|
106
|
+
field = user_input
|
107
|
+
else
|
108
|
+
field = get_password_from_user(type)
|
109
|
+
end
|
110
|
+
if field.empty?
|
111
|
+
if (action == :create)
|
112
|
+
print blank_message.red
|
113
|
+
attempts = attempts + 1
|
114
|
+
next;
|
115
|
+
end
|
116
|
+
end
|
117
|
+
return field
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Passbox
|
2
|
+
|
3
|
+
def delete_pass
|
4
|
+
check_passbox
|
5
|
+
filename = verify_account
|
6
|
+
key = passbox_auth
|
7
|
+
if key
|
8
|
+
File.delete(filename)
|
9
|
+
print "\nYour account #{filename.split("/").last.split(".").first} has been deleted!!\n\n".bold.yellow
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Passbox
|
2
|
+
|
3
|
+
def read_pass(action=:display)
|
4
|
+
check_passbox
|
5
|
+
filename = verify_account
|
6
|
+
key = passbox_auth
|
7
|
+
|
8
|
+
if key
|
9
|
+
data = JSON.parse(decrypt(filename, key))
|
10
|
+
return data, filename, key if (action == :update)
|
11
|
+
case filename.split(".").last
|
12
|
+
when "pb"
|
13
|
+
print "\nusername : #{data['username']}\n"
|
14
|
+
print "password : #{data['password']}\n"
|
15
|
+
print "url : #{data['url']}\n" if data['url']
|
16
|
+
print "note : #{data['note']}\n" if data['note']
|
17
|
+
print "\n"
|
18
|
+
when "pn"
|
19
|
+
print "\npin : #{data['pin']}\n"
|
20
|
+
print "note : #{data['note']}\n" if data['note']
|
21
|
+
print "\n"
|
22
|
+
when "cc"
|
23
|
+
print "\ncard number : #{data['card_number']}\n"
|
24
|
+
print "expiry : #{data['card_expiry']}\n"
|
25
|
+
print "cvv : #{data['card_cvv']}\n" if data['card_cvv']
|
26
|
+
print "card pin : #{data['card_pin']}\n" if data['card_pin']
|
27
|
+
print "note : #{data['note']}\n" if data['note']
|
28
|
+
print "\n"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Passbox
|
2
|
+
|
3
|
+
def update_pass
|
4
|
+
existing, filename, key = read_pass(:update)
|
5
|
+
update_details(existing, filename, key)
|
6
|
+
print account_update_success.green
|
7
|
+
end
|
8
|
+
|
9
|
+
def update_details(existing, filename, key)
|
10
|
+
print update_instructions.yellow
|
11
|
+
change_flag = false
|
12
|
+
case filename.split(".").last
|
13
|
+
when "pb"
|
14
|
+
updated = login(nil, key, :update)
|
15
|
+
existing["username"] = updated["username"] unless updated["username"].empty?
|
16
|
+
existing["password"] = updated["password"] unless updated["password"].empty?
|
17
|
+
existing["url"] = updated["url"] unless (updated["url"].nil? || updated["url"].empty?)
|
18
|
+
existing["note"] = updated["note"] unless (updated["note"].nil? || updated["note"].empty?)
|
19
|
+
when "pn"
|
20
|
+
updated = pin(nil, key, :update)
|
21
|
+
existing["pin"] = updated["pin"] unless updated["pin"].empty?
|
22
|
+
existing["note"] = updated["note"] unless (updated["note"].nil? || updated["note"].empty?)
|
23
|
+
when "cc"
|
24
|
+
updated = cc(nil, key, :update)
|
25
|
+
existing["card_number"] = updated["card_number"] unless updated["card_number"].empty?
|
26
|
+
existing["card_expiry"] = updated["card_expiry"] unless updated["card_expiry"].empty?
|
27
|
+
existing["card_cvv"] = updated["card_cvv"] unless updated["card_cvv"].empty?
|
28
|
+
existing["card_pin"] = updated["card_pin"] unless (updated["card_pin"].nil? || updated["card_pin"].empty?)
|
29
|
+
existing["note"] = updated["note"] unless (updated["note"].nil? || updated["note"].empty?)
|
30
|
+
else
|
31
|
+
# do nothing
|
32
|
+
end
|
33
|
+
encrypt(existing.to_json, key, filename)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
def black; "\e[30m#{self}\e[0m" end
|
4
|
+
def red; "\e[31m#{self}\e[0m" end
|
5
|
+
def green; "\e[32m#{self}\e[0m" end
|
6
|
+
def yellow; "\e[33m#{self}\e[0m" end
|
7
|
+
def blue; "\e[34m#{self}\e[0m" end
|
8
|
+
def magenta; "\e[35m#{self}\e[0m" end
|
9
|
+
def cyan; "\e[36m#{self}\e[0m" end
|
10
|
+
def gray; "\e[37m#{self}\e[0m" end
|
11
|
+
|
12
|
+
def bg_black; "\e[40m#{self}\e[0m" end
|
13
|
+
def bg_red; "\e[41m#{self}\e[0m" end
|
14
|
+
def bg_green; "\e[42m#{self}\e[0m" end
|
15
|
+
def bg_brown; "\e[43m#{self}\e[0m" end
|
16
|
+
def bg_blue; "\e[44m#{self}\e[0m" end
|
17
|
+
def bg_magenta; "\e[45m#{self}\e[0m" end
|
18
|
+
def bg_cyan; "\e[46m#{self}\e[0m" end
|
19
|
+
def bg_gray; "\e[47m#{self}\e[0m" end
|
20
|
+
|
21
|
+
def bold; "\e[1m#{self}\e[22m" end
|
22
|
+
def italic; "\e[3m#{self}\e[23m" end
|
23
|
+
def underline; "\e[4m#{self}\e[24m" end
|
24
|
+
def blink; "\e[5m#{self}\e[25m" end
|
25
|
+
def reverse_color; "\e[7m#{self}\e[27m" end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Passbox
|
2
|
+
|
3
|
+
def display_add_options
|
4
|
+
print "\n1. Password"
|
5
|
+
print "\n2. Pin"
|
6
|
+
print "\n3. Debit/Credit Card"
|
7
|
+
print "\nPlease select one of the above options: "
|
8
|
+
return user_input.to_i
|
9
|
+
end
|
10
|
+
|
11
|
+
def select_option
|
12
|
+
attempt = 0
|
13
|
+
while(true)
|
14
|
+
attempt = attempt + 1
|
15
|
+
option = display_add_options
|
16
|
+
if (1..3).include?(option)
|
17
|
+
return option
|
18
|
+
else
|
19
|
+
print "\nInvalid selection. Please try again!!\n".red
|
20
|
+
end
|
21
|
+
if attempt==3
|
22
|
+
print "\nToo many invalid attempts. Bye!!\n\n".bold.red
|
23
|
+
exit(0)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def user_input
|
29
|
+
begin
|
30
|
+
return gets.chomp
|
31
|
+
rescue Interrupt
|
32
|
+
puts "\n\nThank you for using passbox. Bye!!\n".cyan
|
33
|
+
exit(0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Passbox
|
2
|
+
|
3
|
+
def account_name_blank; return "Account Name cannot be empty, try again!!\n"; end
|
4
|
+
def username_blank; return "Username cannot be empty, try again!!\n"; end
|
5
|
+
def password_blank; return "Password cannot be empty, try again!!\n"; end
|
6
|
+
def pin_blank; return "Pin cannot be empty, try again!!\n"; end
|
7
|
+
def cc_no_blank; return "Credit/Debit Card cannot be empty, try again!!\n"; end
|
8
|
+
def cc_exp_blank; return "Card Expiry cannot be empty, try again!!\n"; end
|
9
|
+
def cc_cvv_blank; return "Card CVV cannot be empty, try again!!\n"; end
|
10
|
+
|
11
|
+
# init.rb
|
12
|
+
def pb_already_setup; return "Your passbox is already setup. Please type 'passbox help' to see usage.\n"; end
|
13
|
+
def pb_not_setup; return "Passbox is not setup, use 'passbox init' command to start.\n"; end
|
14
|
+
|
15
|
+
# accounts.rb
|
16
|
+
def no_accounts; return "\nIts all empty here!! Use 'passbox add' to create new account.\n\n"; end
|
17
|
+
def enter_account_name; return "Please enter you account name: "; end
|
18
|
+
def account_not_found; return "Account not found, Use 'passbox list' to see all your existing accounts.\n"; end
|
19
|
+
def multiple_accounts; return "\nMultiple accounts found, please chose one: "; end
|
20
|
+
def invalid_selection; return "\nInvalid selection. Try again. Bye!!\n\n"; end
|
21
|
+
|
22
|
+
# create.rb
|
23
|
+
def too_many_attempts; return "\nToo many attempts. Start again!!\n\n"; end
|
24
|
+
def enter_account_name; return "\nEnter you account name (alphabets/numbers/underscore/dash): "; end
|
25
|
+
def account_already_exists; return "Account Name already exists, try different name!!\n"; end
|
26
|
+
def account_name_invalid; return "Alphabets, Numbers, Underscore and Dashes only, try again please!!\n"; end
|
27
|
+
def enter_username; return "Please enter in your username: "; end
|
28
|
+
def enter_url; return "Please enter in the login url: "; end
|
29
|
+
def enter_note; return "Enter note to self (optional): "; end
|
30
|
+
def enter_cc_no; return "Please enter in your credit/debit card number: "; end
|
31
|
+
def enter_cc_exp; return "Please enter your card expiry: "; end
|
32
|
+
|
33
|
+
# update.rb
|
34
|
+
def account_update_success; return "\nAccount details has been successfully updated!! \n"; end
|
35
|
+
def update_instructions; return "\nHit enter for no change or input a new value. \n"; end
|
36
|
+
|
37
|
+
# auth.rb
|
38
|
+
def enter_account_password; return "Please enter your Account Password: "; end
|
39
|
+
def enter_account_pin; return "Please enter you Account Pin: "; end
|
40
|
+
def enter_cc_cvv; return "Please enter you Card CVV: "; end
|
41
|
+
def enter_cc_pin; return "Please enter you Card Pin: "; end
|
42
|
+
def create_master_password; return "Please create your master password (min 8 chars): "; end
|
43
|
+
def re_enter_master_password; return "\nPlease re-enter your master password: "; end
|
44
|
+
def pb_setup_complete; return "\n\nPassbox setup complete. Use 'passbox help' to explore.\n\n"; end
|
45
|
+
def passwords_mismatch; return "\n\nPasswords don't match. Try again!!\n\n"; end
|
46
|
+
def password_validation; return "\nPassword should be minimum 8 characters, try again!!\n"; end
|
47
|
+
def enter_master_password; return "Please enter your Master Password: "; end
|
48
|
+
def thank_you; return "\n\nThank you for using passbox. Bye!!\n"; end
|
49
|
+
def invalid_password; return "\nInvalid Password!!\n"; end
|
50
|
+
def auth_success; return "Authentication Successful!!\n"; end
|
51
|
+
def auth_failed; return "Authentication Failed!!\n"; end
|
52
|
+
|
53
|
+
end
|
data/lib/passbox/init.rb
CHANGED
@@ -3,13 +3,14 @@ module Passbox
|
|
3
3
|
homedir = Dir.home
|
4
4
|
$pbdir = homedir+"/.passbox"
|
5
5
|
$passfile = $pbdir+"/pass.mp"
|
6
|
+
$options = {1=>"pb", 2=>"pn", 3=>"cc"}
|
6
7
|
|
7
8
|
def init
|
8
9
|
pass256=""
|
9
10
|
|
10
11
|
if (Dir.exists?($pbdir))
|
11
12
|
if(File.exists?($passfile))
|
12
|
-
print
|
13
|
+
print pb_already_setup
|
13
14
|
return
|
14
15
|
else
|
15
16
|
pass256 = get_password_from_user(:master)
|
@@ -23,7 +24,8 @@ module Passbox
|
|
23
24
|
|
24
25
|
def check_passbox
|
25
26
|
if !File.exists?($passfile)
|
26
|
-
print
|
27
|
+
print pb_not_setup
|
28
|
+
exit(0)
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
data/lib/passbox/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kaushal Rupani
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A gem to store and manage password offline, encrypted using AES 256 strong
|
14
14
|
encryption.
|
@@ -22,22 +22,29 @@ files:
|
|
22
22
|
- README.md
|
23
23
|
- bin/passbox
|
24
24
|
- lib/passbox.rb
|
25
|
+
- lib/passbox/accounts.rb
|
25
26
|
- lib/passbox/aes.rb
|
26
27
|
- lib/passbox/auth.rb
|
27
|
-
- lib/passbox/crud.rb
|
28
|
+
- lib/passbox/crud/create.rb
|
29
|
+
- lib/passbox/crud/delete.rb
|
30
|
+
- lib/passbox/crud/read.rb
|
31
|
+
- lib/passbox/crud/update.rb
|
32
|
+
- lib/passbox/helpers/colourize.rb
|
33
|
+
- lib/passbox/helpers/options.rb
|
34
|
+
- lib/passbox/helpers/strings.rb
|
28
35
|
- lib/passbox/init.rb
|
29
36
|
- lib/passbox/version
|
30
37
|
homepage: https://github.com/krupani/passbox
|
31
38
|
licenses:
|
32
39
|
- MIT
|
33
40
|
metadata: {}
|
34
|
-
post_install_message:
|
41
|
+
post_install_message:
|
35
42
|
rdoc_options: []
|
36
43
|
require_paths:
|
37
44
|
- lib
|
38
45
|
required_ruby_version: !ruby/object:Gem::Requirement
|
39
46
|
requirements:
|
40
|
-
- - "
|
47
|
+
- - ">="
|
41
48
|
- !ruby/object:Gem::Version
|
42
49
|
version: '2'
|
43
50
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -46,8 +53,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
53
|
- !ruby/object:Gem::Version
|
47
54
|
version: '0'
|
48
55
|
requirements: []
|
49
|
-
rubygems_version: 3.
|
50
|
-
signing_key:
|
56
|
+
rubygems_version: 3.2.3
|
57
|
+
signing_key:
|
51
58
|
specification_version: 4
|
52
59
|
summary: 'PassBox gem : AES encrypted offline password manager'
|
53
60
|
test_files: []
|
data/lib/passbox/crud.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module Passbox
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
def verify_account
|
5
|
-
print "Please enter you account name (case-sensitive): "
|
6
|
-
acc = gets.chomp
|
7
|
-
if (!File.exists?("#{$pbdir}/#{acc}.pb"))
|
8
|
-
print "Account not found, Use 'passbox list' to see all your existing accounts.\n"
|
9
|
-
exit(0)
|
10
|
-
end
|
11
|
-
return acc
|
12
|
-
end
|
13
|
-
|
14
|
-
def creds(acc, key)
|
15
|
-
print "Please enter in your account username: "
|
16
|
-
uname = gets.chomp
|
17
|
-
pass = get_password_from_user(:account)
|
18
|
-
hash = {:username => uname, :password => pass}
|
19
|
-
json = hash.to_json
|
20
|
-
encrypt(json, key, "#{$pbdir}/#{acc}.pb")
|
21
|
-
end
|
22
|
-
|
23
|
-
def create_pass
|
24
|
-
check_passbox
|
25
|
-
key = passbox_auth
|
26
|
-
if key
|
27
|
-
while(true)
|
28
|
-
print "\nEnter you account name (alphabets/numbers only): "
|
29
|
-
acc = gets.chomp.downcase
|
30
|
-
if (acc.count("a-z0-9") == acc.length)
|
31
|
-
break
|
32
|
-
else
|
33
|
-
"\nAccount name can only have Alphabets and Numbers (no special characters), try again!!"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
creds(acc,key)
|
38
|
-
print "Account #{acc} has been successfully created!! \n"
|
39
|
-
end
|
40
|
-
|
41
|
-
def read_pass
|
42
|
-
check_passbox
|
43
|
-
acc=verify_account
|
44
|
-
key = passbox_auth
|
45
|
-
if key
|
46
|
-
data = JSON.parse(decrypt("#{$pbdir}/#{acc}.pb", key))
|
47
|
-
print "username : #{data['username']}\n"
|
48
|
-
print "password : #{data['password']}\n"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def update_pass
|
53
|
-
check_passbox
|
54
|
-
acc=verify_account
|
55
|
-
key = passbox_auth
|
56
|
-
creds(acc,key)
|
57
|
-
print "Account details has been successfully updated!! \n"
|
58
|
-
end
|
59
|
-
|
60
|
-
def delete_pass
|
61
|
-
check_passbox
|
62
|
-
acc = verify_account
|
63
|
-
if key
|
64
|
-
File.delete("#{$pbdir}/#{acc}.pb")
|
65
|
-
print("\nAccount #{acc} has been deleted!!")
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def list_of_accounts
|
70
|
-
check_passbox
|
71
|
-
files_ext = Dir["#{$pbdir}/*.pb"]
|
72
|
-
files_ext.each_with_index do |file,i|
|
73
|
-
print "#{i+1}. #{file.split('/').last.split('.').first}\n"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|