adamantite 0.0.3 → 0.0.6

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,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