adamantite 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,6 @@
1
- require "base/editor/password_object_editor"
1
+ # frozen_string_literal: true
2
+
3
+ require 'base/editor/password_object_editor'
2
4
 
3
5
  module Adamantite
4
6
  module GUI
@@ -9,63 +11,63 @@ module Adamantite
9
11
  # This holds the final user produced by the form
10
12
  # And, a user can be optionally passed (e.g. `user_form(user: someuser)`) when editing an existing user
11
13
  option :password_object, default: nil
12
- option :on_save, default: lambda { |password_object| }
13
- option :master_pw
14
- option :master_pw_salt
14
+ option :on_save, default: ->(password_object) {}
15
+ option :adamantite
15
16
 
16
17
  before_body do
17
- @password_object_editor = Adamantite::Base::Editor::PasswordObjectEditor.new(master_pw, master_pw_salt, password_object)
18
+ @password_object_editor = Base::Editor::PasswordObjectEditor.new(adamantite, password_object)
18
19
  end
19
20
 
20
- body {
21
- window('Password Form', 50, 50) { |password_object_form_editor|
21
+ body do
22
+ window('Password Form', 50, 50) do |password_object_form_editor|
22
23
  margined true
23
24
 
24
- vertical_box {
25
- form {
26
- entry {
25
+ vertical_box do
26
+ form do
27
+ entry do
27
28
  label 'Website Title'
28
29
  text <=> [@password_object_editor.editable_password_object, :website_title]
29
- }
30
- entry {
30
+ end
31
+ entry do
31
32
  label 'Username'
32
33
  text <=> [@password_object_editor.editable_password_object, :username]
33
- }
34
+ end
34
35
 
35
- password_entry {
36
+ password_entry do
36
37
  label 'Password'
37
38
  text <=> [@password_object_editor.editable_password_object, :password]
38
- }
39
- password_entry {
39
+ end
40
+ password_entry do
40
41
  label 'Password Confirmation'
41
42
  text <=> [@password_object_editor.editable_password_object, :password_confirmation]
42
- }
43
- }
44
- horizontal_box {
43
+ end
44
+ end
45
+
46
+ horizontal_box do
45
47
  stretchy false
46
48
 
47
- button('Save') {
49
+ button('Save') do
48
50
  on_clicked do
49
51
  self.password_object = @password_object_editor.save
50
52
  on_save.call(password_object)
51
53
  password_object_form_editor.destroy
52
54
  end
53
- }
55
+ end
54
56
 
55
- button('Cancel') {
57
+ button('Cancel') do
56
58
  on_clicked do
57
59
  @password_object_editor.cancel
58
60
  password_object_form_editor.destroy
59
61
  end
60
- }
61
- }
62
- }
62
+ end
63
+ end
64
+ end
63
65
 
64
66
  on_closing do
65
67
  @password_object_editor.cancel
66
68
  end
67
- }
68
- }
69
+ end
70
+ end
69
71
  end
70
72
  end
71
73
  end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Adamantite
2
4
  module GUI
3
5
  module Request
4
6
  class AddPasswordRequest
5
-
6
7
  attr_accessor :website_title, :username, :password, :password_confirmation, :password_saved
7
8
 
8
9
  def initialize(master_password, master_password_salt)
@@ -12,13 +13,13 @@ module Adamantite
12
13
  end
13
14
 
14
15
  def confirm_and_add_password!
15
- if @password == @password_confirmation
16
- @password_saved = true
17
- pw_info_for_file = make_pw_info(@username, @password, @master_password, @master_password_salt)
18
- write_pw_to_file(@website_title, **pw_info_for_file)
19
- end
16
+ return unless @password == @password_confirmation
17
+
18
+ @password_saved = true
19
+ pw_info_for_file = make_pw_info(@username, @password, @master_password, @master_password_salt)
20
+ write_pw_to_file(@website_title, **pw_info_for_file)
20
21
  end
21
22
  end
22
23
  end
23
24
  end
24
- end
25
+ end
@@ -1,23 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base/adamantite'
4
+
1
5
  module Adamantite
2
6
  module GUI
3
7
  module Request
4
8
  class LoginRequest
5
9
 
6
- attr_accessor :master_password, :master_password_salt, :authenticated
10
+ attr_accessor :adamantite, :master_password, :authenticated
7
11
 
8
12
  def authenticate!
9
- user_master_pw_info = get_master_pw_info
10
- master_pw_hash = user_master_pw_info['password']
11
- master_pw_salt = user_master_pw_info['salt']
12
- master_pw_comparator = generate_master_pw_comparator(master_pw_hash)
13
-
14
- if master_pw_comparator == master_password + master_pw_salt
15
- @authenticated = true
16
- @master_password = master_password
17
- @master_password_salt = master_pw_salt
18
- end
13
+ @adamantite = Base::Adamantite.new(master_password)
14
+ @adamantite.authenticate!
15
+ @authenticated = @adamantite.authenticated?
19
16
  end
20
17
  end
21
18
  end
22
19
  end
23
- end
20
+ end
@@ -1,20 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base/adamantite'
4
+
1
5
  module Adamantite
2
6
  module GUI
3
7
  module Request
4
8
  class SetMasterPasswordRequest
5
-
6
9
  attr_accessor :new_master_pw, :new_master_pw_confirmation, :success
7
10
 
8
11
  def set_master_password!
9
12
  @success = false
10
- if @new_master_pw == @new_master_pw_confirmation
11
- master_pw_info = generate_master_pw_hash(@new_master_pw)
12
- write_pw_to_file('master', password: master_pw_info[:master_pw_hash], salt: master_pw_info[:salt])
13
- @success = true
14
- end
15
- @success
13
+ adamantite = Base::Adamantite.new(@new_master_pw)
14
+ @success = adamantite.serialize_master_password(@new_master_pw, @new_master_pw_confirmation)
16
15
  end
17
16
  end
18
17
  end
19
18
  end
20
- end
19
+ end
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Adamantite
2
4
  module GUI
3
5
  module Request
4
6
  class UpdateMasterPasswordRequest
7
+ attr_accessor :new_master_pw, :new_master_pw_confirmation, :adamantite
5
8
 
6
- attr_accessor :new_master_pw, :new_master_pw_confirmation, :adamantite_object
7
-
8
- def initialize(adamantite_object)
9
- @adamantite_object = adamantite_object
9
+ def initialize(adamantite)
10
+ @adamantite = adamantite
10
11
  end
11
12
  end
12
13
  end
13
14
  end
14
- end
15
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Adamantite
2
4
  module GUI
3
5
  module Screen
@@ -6,13 +8,13 @@ module Adamantite
6
8
 
7
9
  option :password_title
8
10
 
9
- body {
10
- window('Adamantite - Copy Password', 400, 100) {
11
+ body do
12
+ window('Adamantite - Copy Password', 400, 100) do
11
13
  margined true
12
14
  label("Copied password for #{password_title} to your clipboard.")
13
- }
14
- }
15
+ end
16
+ end
15
17
  end
16
18
  end
17
19
  end
18
- end
20
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module PWManager
3
4
  module GUI
@@ -7,19 +8,19 @@ module PWManager
7
8
 
8
9
  option :login_request
9
10
 
10
- body {
11
- window('Adamantite - Login', 400, 100) {
11
+ body do
12
+ window('Adamantite - Login', 400, 100) do
12
13
  margined true
13
14
 
14
- vertical_box {
15
- form {
16
- password_entry {
15
+ vertical_box do
16
+ form do
17
+ password_entry do
17
18
  label 'Master Password'
18
19
  text <=> [login_request, :master_password]
19
- }
20
- }
20
+ end
21
+ end
21
22
 
22
- button('Login') {
23
+ button('Login') do
23
24
  on_clicked do
24
25
  login_request.authenticate!
25
26
  # Destroy window if password is correct.
@@ -28,11 +29,11 @@ module PWManager
28
29
  ::LibUI.quit
29
30
  end
30
31
  end
31
- }
32
- }
33
- }
34
- }
32
+ end
33
+ end
34
+ end
35
+ end
35
36
  end
36
37
  end
37
38
  end
38
- end
39
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Adamantite
2
4
  module GUI
3
5
  module Screen
@@ -6,21 +8,21 @@ module Adamantite
6
8
 
7
9
  option :set_master_password_request
8
10
 
9
- body {
10
- window('Adamantite - Create Master Password', 450, 150) {
11
+ body do
12
+ window('Adamantite - Create Master Password', 450, 150) do
11
13
  margined true
12
- vertical_box {
13
- form {
14
- password_entry {
14
+ vertical_box do
15
+ form do
16
+ password_entry do
15
17
  label 'Master Password'
16
18
  text <=> [set_master_password_request, :new_master_pw]
17
- }
18
- password_entry {
19
+ end
20
+ password_entry do
19
21
  label 'Master Password Confirmation'
20
22
  text <=> [set_master_password_request, :new_master_pw_confirmation]
21
- }
22
- }
23
- button('Set Master Password') {
23
+ end
24
+ end
25
+ button('Set Master Password') do
24
26
  on_clicked do
25
27
  set_master_password_request.set_master_password!
26
28
  if set_master_password_request.success
@@ -31,11 +33,11 @@ module Adamantite
31
33
  set_master_password_request.new_master_pw_confirmation = ''
32
34
  end
33
35
  end
34
- }
35
- }
36
- }
37
- }
36
+ end
37
+ end
38
+ end
39
+ end
38
40
  end
39
41
  end
40
42
  end
41
- end
43
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Adamantite
2
4
  module GUI
3
5
  module Screen
@@ -6,14 +8,14 @@ module Adamantite
6
8
 
7
9
  option :password
8
10
 
9
- body {
10
- window('Adamantite - Show Password', 400, 100) {
11
+ body do
12
+ window('Adamantite - Show Password', 400, 100) do
11
13
  margined true
12
14
 
13
- label("#{password}")
14
- }
15
- }
15
+ label(password.to_s)
16
+ end
17
+ end
16
18
  end
17
19
  end
18
20
  end
19
- end
21
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Adamantite
2
4
  module GUI
3
5
  module Screen
@@ -6,26 +8,27 @@ module Adamantite
6
8
 
7
9
  option :update_master_password_request
8
10
 
9
- body {
10
- window('Adamantite - Update Master Password', 450, 150) {
11
+ body do
12
+ window('Adamantite - Update Master Password', 450, 150) do
11
13
  margined true
12
- vertical_box {
13
- form {
14
- password_entry {
14
+ vertical_box do
15
+ form do
16
+ password_entry do
15
17
  label 'New Master Password'
16
18
  text <=> [update_master_password_request, :new_master_pw]
17
- }
18
- password_entry {
19
+ end
20
+ password_entry do
19
21
  label 'New Master Password Confirmation'
20
22
  text <=> [update_master_password_request, :new_master_pw_confirmation]
21
- }
22
- }
23
- button('Update') {
23
+ end
24
+ end
25
+ button('Update') do
24
26
  on_clicked do
25
27
  new_master_pw = update_master_password_request.new_master_pw
26
28
  new_master_pw_confirmation = update_master_password_request.new_master_pw_confirmation
27
- success = update_master_password_request.adamantite_object.update_master_password!(new_master_pw, new_master_pw_confirmation)
28
- if success
29
+ pass = update_master_password_request.adamantite.update_master_password!(new_master_pw,
30
+ new_master_pw_confirmation)
31
+ if pass
29
32
  body_root.destroy
30
33
  ::LibUI.quit
31
34
  else
@@ -33,10 +36,10 @@ module Adamantite
33
36
  update_master_password_request.new_master_pw_confirmation = ''
34
37
  end
35
38
  end
36
- }
37
- }
38
- }
39
- }
39
+ end
40
+ end
41
+ end
42
+ end
40
43
  end
41
44
  end
42
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adamantite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Bruemmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-11 00:00:00.000000000 Z
11
+ date: 2023-11-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A local password manager written in Ruby.
14
14
  email: jakebruemmer@gmail.com
@@ -19,11 +19,10 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - bin/adamantite
21
21
  - lib/adamantite.rb
22
- - lib/adamantite_command_line.rb
23
22
  - lib/base/adamantite.rb
24
23
  - lib/base/editor/password_object_editor.rb
25
24
  - lib/base/password_object.rb
26
- - lib/file_utils/file_utils.rb
25
+ - lib/file_utils/adamantite_file_utils.rb
27
26
  - lib/gui/form/password_object_form_window.rb
28
27
  - lib/gui/request/add_password_request.rb
29
28
  - lib/gui/request/login_request.rb
@@ -34,7 +33,6 @@ files:
34
33
  - lib/gui/screen/set_master_password_screen.rb
35
34
  - lib/gui/screen/show_screen.rb
36
35
  - lib/gui/screen/update_master_password_screen.rb
37
- - lib/pw_utils/pw_utils.rb
38
36
  homepage: https://github.com/jakebruemmer/adamantite
39
37
  licenses:
40
38
  - MIT
@@ -47,7 +45,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
47
45
  requirements:
48
46
  - - ">="
49
47
  - !ruby/object:Gem::Version
50
- version: '0'
48
+ version: 3.1.0
51
49
  required_rubygems_version: !ruby/object:Gem::Requirement
52
50
  requirements:
53
51
  - - ">="
@@ -1,95 +0,0 @@
1
- require "bcrypt"
2
- require "openssl"
3
- require "base64"
4
- require "json"
5
- require "io/console"
6
-
7
- require "file_utils/file_utils"
8
- require "pw_utils/pw_utils"
9
-
10
- include Adamantite::FileUtils
11
- include Adamantite::PWUtils
12
-
13
- puts "Welcome to Adamantite."
14
-
15
- if pw_file_exists?('master')
16
- user_master_pw_info = get_master_pw_info
17
- master_pw_hash = user_master_pw_info['password']
18
- master_pw_salt = user_master_pw_info['salt']
19
-
20
- master_pw = IO::console.getpass("Please enter your master password:")
21
- master_pw_comparator = BCrypt::Password.new(master_pw_hash)
22
-
23
- while master_pw_comparator != master_pw + master_pw_salt
24
- puts "Entered password didn't match."
25
- master_pw = IO::console.getpass("Please enter your master password:")
26
- master_pw_hash = BCrypt::Password.create(master_pw + user_master_pw_info['salt'])
27
- end
28
-
29
- puts "Master password successfully entered."
30
- puts "Here are your stored passwords:"
31
- get_stored_pws.each_with_index do |pw, index|
32
- puts "#{index + 1}. #{pw}"
33
- end
34
-
35
- puts "Would you like to enter another password? (Y/N)"
36
- response = gets.chomp
37
- while !["Y", "N"].include?(response)
38
- puts "Please enter Y or N"
39
- end
40
-
41
- if response == "Y"
42
- puts "What do you want to call this password?"
43
- title = gets.chomp
44
- puts "What is the username for #{title}?"
45
- username = gets.chomp
46
- pw = IO::console.getpass("Enter the password for this site.")
47
- pw_confirmation = IO::console.getpass("Confirm the password for this site.")
48
-
49
- while pw != pw_confirmation
50
- puts "Those didn't match, please enter them again."
51
- pw = IO::console.getpass("Enter the password for this site.")
52
- pw_confirmation = IO::console.getpass("Confirm the password for this site.")
53
- end
54
-
55
- pw_info_for_file = make_pw_info(username, pw, master_pw, master_pw_salt)
56
- write_pw_to_file(title, **pw_info_for_file)
57
- puts "Successfully stored password for #{title}."
58
-
59
- elsif response == "N"
60
- puts "Exiting"
61
- end
62
-
63
- puts "Here are your stored passwords:"
64
- stored_pws = get_stored_pws
65
- stored_pws.each_with_index do |pw, index|
66
- puts "#{index + 1}. #{pw}"
67
- end
68
-
69
- puts "Enter the number of the password that you would like to retrieve."
70
- pw_entry = gets.chomp.to_i
71
-
72
- pw_info = get_pw_file(stored_pws[pw_entry - 1])
73
- stored_pw_selection = decrypt_pw(pw_info["iv"], pw_info['password'], master_pw, master_pw_salt)
74
-
75
- IO.popen('pbcopy', 'w') { |f| f << stored_pw_selection }
76
-
77
- puts "Your password has been copied to your clipboard."
78
-
79
- else
80
- puts "You don't have a master password. Please enter one now."
81
- master_pw = IO::console.getpass("Enter your master password:")
82
- master_pw_confirmation = IO::console.getpass("Confirm your master password:")
83
-
84
- while master_pw != master_pw_confirmation
85
- puts "Those didn't match, please enter them again."
86
- master_pw = IO::console.getpass("Enter your master password:")
87
- master_pw_confirmation = IO::console.getpass("Confirm your master password:")
88
- end
89
-
90
- master_pw_info = generate_master_pw_hash(master_pw)
91
-
92
- write_pw_to_file('master', password: master_pw_info[:master_pw_hash], salt: master_pw_info[:salt])
93
-
94
- puts "Wrote master pw to file."
95
- end
@@ -1,55 +0,0 @@
1
- require "json"
2
-
3
- module Adamantite
4
- module FileUtils
5
- def home_dir
6
- ENV['HOME']
7
- end
8
-
9
- def pwmanager_dir
10
- File.join(home_dir, '.pwmanager')
11
- end
12
-
13
- def pwmanager_dir_exists?
14
- Dir.exists?(pwmanager_dir)
15
- end
16
-
17
- def make_pwmanager_dir
18
- Dir.mkdir(pwmanager_dir)
19
- end
20
-
21
- def pw_file(title)
22
- File.join(pwmanager_dir, title)
23
- end
24
-
25
- def pw_file_exists?(title)
26
- File.exists?(pw_file(title))
27
- end
28
-
29
- def write_pw_to_file(title, **kwargs)
30
- if !pwmanager_dir_exists?
31
- make_pwmanager_dir
32
- end
33
-
34
- File.open(pw_file(title), "w") do |f|
35
- JSON.dump(kwargs, f)
36
- end
37
- end
38
-
39
- def delete_pw_file(title)
40
- File.delete(pw_file(title))
41
- end
42
-
43
- def get_pw_file(title)
44
- JSON.load_file(pw_file(title))
45
- end
46
-
47
- def get_master_pw_info
48
- get_pw_file('master')
49
- end
50
-
51
- def get_stored_pws
52
- Dir.entries(pwmanager_dir).filter { |f| ![".", "..", "master"].include?(f) }
53
- end
54
- end
55
- end
@@ -1,40 +0,0 @@
1
- require "bcrypt"
2
- require "openssl"
3
- require "base64"
4
-
5
- module Adamantite
6
- module PWUtils
7
-
8
- def make_pw_info(username, pw, master_pw, master_pw_salt)
9
- cipher = OpenSSL::Cipher::AES256.new(:CBC)
10
- cipher.encrypt
11
- iv = cipher.random_iv
12
- cipher.key = Digest::MD5.hexdigest(master_pw + master_pw_salt)
13
- cipher_text = cipher.update(pw) + cipher.final
14
- utf8_cipher_text = Base64.encode64(cipher_text).encode('utf-8')
15
- utf8_iv = Base64.encode64(iv).encode('utf-8')
16
-
17
- {username: username, password: utf8_cipher_text, iv: utf8_iv}
18
- end
19
-
20
- def decrypt_pw(iv, pw_hash, master_pw, master_pw_salt)
21
- decrypt_cipher = OpenSSL::Cipher::AES256.new(:CBC)
22
- decrypt_cipher.decrypt
23
- iv = Base64.decode64(iv.encode('ascii-8bit'))
24
- decrypt_cipher.iv = iv
25
- decrypt_cipher.key = Digest::MD5.hexdigest(master_pw + master_pw_salt)
26
- decrypt_text = Base64.decode64(pw_hash.encode('ascii-8bit'))
27
- decrypt_cipher.update(decrypt_text) + decrypt_cipher.final
28
- end
29
-
30
- def generate_master_pw_hash(master_pw)
31
- salt = BCrypt::Engine.generate_salt
32
- master_pw_hash = BCrypt::Password.create(master_pw + salt)
33
- {'salt': salt, 'master_pw_hash': master_pw_hash}
34
- end
35
-
36
- def generate_master_pw_comparator(master_pw_hash)
37
- BCrypt::Password.new(master_pw_hash)
38
- end
39
- end
40
- end