dragons_keep 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,29 @@
1
+ source "http://rubygems.org"
2
+
3
+ # ruby gems needed for Dragon's Keep
4
+ gem 'ezcrypto'
5
+ gem 'uuid'
6
+ # using datamapper instead of activerecord
7
+ # Active record Gems
8
+ #gem 'activerecord', "3.0.0.beta3"
9
+ #gem 'sqlite3-ruby'
10
+ #
11
+ # Data Mapper gems 0.10.2
12
+ gem 'dm-core', "0.10.2"
13
+ gem 'do_sqlite3', '0.10.2'
14
+
15
+ # Data Mapper gems 1.0.0
16
+ #gem 'data_mapper', "1.0.0"
17
+ #gem 'dm-sqlite-adapter', "1.0.0"
18
+
19
+ # Wxruby renames gem for 1.9.1 support
20
+ if (RUBY_PLATFORM =~ /linux$/) == nil
21
+ #Decide which gem to load based on version of ruby installed
22
+ if (RUBY_VERSION =~/^1.9/) != nil
23
+ gem 'wxruby-ruby19'
24
+ else
25
+ gem 'wxruby'
26
+ end
27
+ else
28
+ gem 'wxruby', "2.0.1"
29
+ end
data/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ == dragons_keep
2
+
3
+ Put appropriate LICENSE for your project here.
data/README ADDED
@@ -0,0 +1,3 @@
1
+ == dragons_keep
2
+
3
+ You should document your project here.
@@ -0,0 +1,59 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+
6
+ require 'rubygems'
7
+ require 'rake'
8
+ require 'rake/clean'
9
+ require 'rake/gempackagetask'
10
+ require 'rake/rdoctask'
11
+ require 'rake/testtask'
12
+ require 'bundler'
13
+
14
+
15
+ spec = Gem::Specification.new do |s|
16
+ s.name = 'dragons_keep'
17
+ s.version = '0.5.0'
18
+ s.has_rdoc = true
19
+ s.extra_rdoc_files = ['README', 'LICENSE']
20
+ s.summary = 'Secure Password Keeper Application'
21
+ s.description = s.summary
22
+ s.author = 'Allan Davis'
23
+ s.email = 'javaalley@gmail.com'
24
+ s.homepage = 'http://github.com/javaalley/dragons_keep'
25
+ s.executables = ['dragons_keep']
26
+ s.files = %w(LICENSE README Rakefile Gemfile) + Dir.glob("{bin,lib,spec,db}/**/*")
27
+ s.require_path = "lib"
28
+ s.bindir = "bin"
29
+ s.add_bundler_dependencies
30
+ end
31
+
32
+ Rake::GemPackageTask.new(spec) do |p|
33
+ p.gem_spec = spec
34
+ p.need_tar = true
35
+ p.need_zip = true
36
+ end
37
+
38
+ Rake::RDocTask.new do |rdoc|
39
+ files =['README', 'LICENSE', 'lib/**/*.rb']
40
+ rdoc.rdoc_files.add(files)
41
+ rdoc.main = "README" # page to start on
42
+ rdoc.title = "dragons_keep Docs"
43
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
44
+ rdoc.options << '--line-numbers'
45
+ end
46
+
47
+ Rake::TestTask.new do |t|
48
+ t.test_files = FileList['test/**/*.rb']
49
+ end
50
+
51
+ #desc "Migrate the database through migrations scripts"
52
+ #task :migrate => :enviroment do
53
+ # ActiveRecord::Migrator.migrate('db/migrations', ENV["VERSION"]? ENV["VERSION"].to_i : nil)
54
+ #end
55
+ #
56
+ #task :enviroment do
57
+ # ActiveRecord::Base.establish_connection(YAML::load(File.open('config/database.yml')))
58
+ # ActiveRecord::Base.logger = Logger.new(File.open('database.log', 'a'))
59
+ #end
@@ -0,0 +1,17 @@
1
+ #! /usr/bin/env ruby
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+ require 'rubygems'
5
+ begin
6
+ require 'bundler'
7
+ Bundler.setup
8
+ rescue
9
+ end
10
+
11
+ # Set the path to load from the lib and main directory
12
+ path = File.expand_path(File.dirname(__FILE__))
13
+ $: << path
14
+ $: << File.join(path, "..", "lib")
15
+
16
+ load "dragons_keep.rb"
17
+
@@ -0,0 +1 @@
1
+ @"ruby.exe" "%~dpn0" %*
@@ -0,0 +1,19 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ class CreateAccounts < ActiveRecord::Migration
5
+ def self.up
6
+ create_table :accounts do |t|
7
+ t.string :name
8
+ t.string :password
9
+ t.string :salt
10
+ t.string :url
11
+ t.string :user_name
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ def self.down
17
+ drop_table :accounts
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ #! /usr/etc ruby
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+ require 'rubygems'
5
+ #require 'bundler'
6
+ #Bundler.setup
7
+
8
+ # Set the path to load from the lib and main directory
9
+ path = File.expand_path(File.dirname(__FILE__))
10
+ $LOAD_PATH.insert 0, path
11
+ #puts "LOAD_PATH"
12
+ #puts $LOAD_PATH
13
+ #$: << File.join(path, "..", "lib")
14
+
15
+ require 'wx'
16
+ require 'dragons_keep/keeps_main'
17
+ require 'ezcrypto'
18
+ require 'uuid'
19
+
20
+ module DragonsKeep
21
+
22
+ class DragonsKeepApp < Wx::App
23
+ def on_init()
24
+ self.app_name = "Dragon's Keep"
25
+ @frame = KeepsMain.new "Dragon's Keep"
26
+ @frame.center_on_screen(Wx::BOTH)
27
+ @frame.show
28
+ end
29
+ end
30
+ end
31
+
32
+ dk = DragonsKeep::DragonsKeepApp.new
33
+ dk.main_loop
@@ -0,0 +1,99 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+ require 'dm-core'
4
+ require 'ezcrypto'
5
+ module DragonsKeep
6
+ # Account class to store accounts and passwords into a keeper system
7
+ class Account
8
+ include DataMapper::Resource
9
+ #Data Mapper properties
10
+ property :id, Serial
11
+ property :name, String, :length => 100
12
+ property :password, String, :length => 100
13
+ property :salt, String, :length => 100
14
+ property :user_name, String, :length => 100
15
+ property :url, String, :length => 100
16
+
17
+ #register callbacks
18
+ before :save, :before_create
19
+
20
+
21
+ # Transient storage of unencrypted password and confirmation field
22
+ attr_accessor :unencrypted_password
23
+ attr_reader :password_confirmation
24
+
25
+ # create writer for password confirmation
26
+ def password_confirmation=(value)
27
+ @password_confirmation = value
28
+ @unencrypted = true
29
+ end
30
+
31
+ # loading data validate password filed and check status
32
+ def after_initialize
33
+ @unencrypted = self.password.nil?
34
+ end
35
+
36
+ # Before create data set salt and encrypt password
37
+ def before_create
38
+ raise PasswordException, "Password is not Encrypted" if self.new_password? && self.unencrypted?
39
+ end
40
+
41
+ # are we re defining the account password
42
+ def new_password?()
43
+ return !(self.unencrypted_password.blank? and self.password_confirmation.blank?)
44
+ end
45
+
46
+ # Encrypt the password
47
+ # encrypt_pass = Given password when user created the account information
48
+ def encrypt_password(encrypt_pass)
49
+ if self.unencrypted? && self.unencrypted_password == self.password_confirmation
50
+ self.create_salt
51
+ self.password = Base64.encode64(EzCrypto::Key.encrypt_with_password(encrypt_pass, self.salt, self.unencrypted_password))
52
+ @unencrypted = false
53
+ end
54
+ end
55
+
56
+ # Decrypt the password
57
+ # encrypt_pass = Given password when user created the account information
58
+ def decrpyt_password(encrypt_pass)
59
+ if !(self.unencrypted?)
60
+ self.unencrypted_password = EzCrypto::Key.decrypt_with_password(encrypt_pass, self.salt, Base64.decode64( self.password))
61
+ @unencrypted = true
62
+ self.password_confirmation=""
63
+ end
64
+ end
65
+
66
+ # Is the password encrypted?
67
+ def unencrypted?
68
+ return (@unencrypted.nil?)? self.password.nil?: @unencrypted
69
+ end
70
+
71
+ # Generate a random password
72
+ # length_of_password = Length of the password to generate
73
+ # special_char = Can this password need to contain Special Characters
74
+ def generate_password( length_of_pass, special_char )
75
+ chars = []
76
+ ("a".."z").each {|ele| chars << ele}
77
+ ("A".."Z").each {|ele| chars << ele}
78
+ ("0".."9").each {|ele| chars << ele}
79
+ if(special_char)
80
+ ["@", "!", "_",].each {|ele| chars << ele}
81
+ end
82
+ newpass = ""
83
+ 1.upto(length_of_pass) { |i| newpass << chars[rand(chars.size-1)] }
84
+ #self.password
85
+ self.unencrypted_password = newpass
86
+ self.password_confirmation = newpass
87
+ @unencrypted = true
88
+ end
89
+
90
+ # Create the salt
91
+ def create_salt
92
+ self.salt = UUID.generate(:compact)
93
+ end
94
+ end
95
+
96
+ # Error on Passwords Encryption or validation
97
+ class PasswordException < RuntimeError
98
+ end
99
+ end
@@ -0,0 +1,85 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+ require 'dragons_keep/account'
4
+ require 'dm-core'
5
+ require 'ezcrypto'
6
+ require 'uuid'
7
+ require 'digest/sha1'
8
+
9
+ module DragonsKeep
10
+ class AccountController
11
+ attr_reader :encrypt_pass
12
+ attr_accessor :database
13
+
14
+ def encrypt_pass=(pass)
15
+ @encrypt_pass = Digest::SHA1.hexdigest(pass)
16
+ end
17
+
18
+ def establish_connection
19
+ migrate = false
20
+ if !(File.exist?(self.database))
21
+ migrate = true
22
+ end
23
+
24
+ #DataMapper::Logger.new $stdout, :debug
25
+
26
+ DataMapper.setup :default, "sqlite3://#{self.database}"
27
+ if migrate
28
+ DataMapper.auto_migrate!
29
+ else
30
+ validate_connection
31
+ end
32
+ @connection = true
33
+ end
34
+ # Check the first record in the database and decrypt the password to see if the password is valid
35
+ def validate_connection
36
+ account = Account.first
37
+ if ! account.nil?
38
+ self.decrypt!(account)
39
+ end
40
+ end
41
+
42
+ def initialize(database=nil, password=nil)
43
+ @connection = false
44
+ if(!(database.nil?))
45
+ self.database = File.expand_path database
46
+ end
47
+ if (!(password.nil?))
48
+ self.encrypt_pass = password
49
+ end
50
+ end
51
+
52
+ def list()
53
+ if @connection
54
+ return Account.all
55
+ end
56
+
57
+ end
58
+ def save!(account)
59
+ if @connection
60
+ if account.unencrypted?
61
+ account.encrypt_password(self.encrypt_pass)
62
+ end
63
+ return account.save()
64
+ end
65
+ end
66
+
67
+ def get(id)
68
+ if @connection
69
+ return Account.get id
70
+ end
71
+ end
72
+
73
+ def decrypt!(account)
74
+ begin
75
+ account.decrpyt_password self.encrypt_pass
76
+ rescue OpenSSL::Cipher::CipherError
77
+ raise PasswordException, "Password is invalid"
78
+ end
79
+ end
80
+
81
+ def delete(account)
82
+ account.destroy
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,103 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+ require 'wx'
4
+ require 'dragons_keep/generate_password_dialog'
5
+
6
+ module DragonsKeep
7
+ class AccountDialog < Wx::Dialog
8
+ ID_USER_NAME = 103
9
+ ID_ACCOUNT_NAME = 101
10
+ ID_URL = 102
11
+ ID_PASSWORD = 104
12
+ ID_GENERATE_PASSWORD = 105
13
+ ID_SAVE = 106
14
+ ID_COPY_CLIP = 107
15
+ ID_CANCEL = 108
16
+
17
+ def initialize parent, id, title
18
+ super parent, id, title
19
+ self.set_size(Wx::Size.new(400, 300))
20
+ main_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
21
+ grid_sizer = Wx::FlexGridSizer.new(4,2,5,5)
22
+
23
+ # Create name entry
24
+ label = Wx::StaticText.new(self, :label=>"Name:")
25
+ grid_sizer.add label, 0, Wx::ALL |Wx::ALIGN_RIGHT
26
+ @name = Wx::TextCtrl.new self, ID_ACCOUNT_NAME
27
+ grid_sizer.add @name, 1, Wx::EXPAND
28
+
29
+ # Create url entry
30
+ label = Wx::StaticText.new(self, :label=>"URL:")
31
+ grid_sizer.add label, 0,Wx::ALL |Wx::ALIGN_RIGHT
32
+ @url = Wx::TextCtrl.new self, ID_URL
33
+ grid_sizer.add @url, 1, Wx::EXPAND
34
+
35
+ # Create User_name entry
36
+ label = Wx::StaticText.new(self, :label=>"User Name:")
37
+ grid_sizer.add label, 0, Wx::ALL |Wx::ALIGN_RIGHT
38
+ @user = Wx::TextCtrl.new self, ID_USER_NAME
39
+ grid_sizer.add @user, 1, Wx::EXPAND
40
+
41
+ # Create password entry
42
+ label = Wx::StaticText.new(self, :label=>"Password:")
43
+ grid_sizer.add label, 0, Wx::ALL |Wx::ALIGN_RIGHT
44
+ @pass = Wx::TextCtrl.new self, ID_PASSWORD, :style=> Wx::TE_PASSWORD
45
+ grid_sizer.add @pass, 1, Wx::EXPAND
46
+ main_sizer.add grid_sizer, 0, Wx::GROW|Wx::ALIGN_CENTER_VERTICAL|Wx::ALL, 5
47
+ grid_sizer.add_growable_col(1)
48
+ # add spacer to grid
49
+ grid_sizer.add(25, 25)
50
+ # Add generate password button
51
+ @gen_button = Wx::Button.new self, ID_GENERATE_PASSWORD, "Generate Password..."
52
+ grid_sizer.add @gen_button, 1, Wx::EXPAND
53
+ evt_button(ID_GENERATE_PASSWORD){|evt| self.gen_pass_click(evt)}
54
+ main_sizer.add self.create_separated_button_sizer(Wx::OK|Wx::CANCEL), 1, Wx::ALIGN_RIGHT
55
+ self.set_sizer main_sizer
56
+
57
+ end
58
+
59
+ def gen_pass_click(event)
60
+ # display generate pass dialog
61
+ gen_dialog = GeneratePasswordDialog.new self, -1, "Generate Password"
62
+ if gen_dialog.show_modal() == Wx::ID_OK
63
+ @account.generate_password gen_dialog.password_length, gen_dialog.use_special_chars?
64
+ @pass.value = @account.unencrypted_password
65
+ end
66
+ end
67
+
68
+ def account
69
+ save_account
70
+ @account
71
+ end
72
+
73
+ def account=(account)
74
+ @account = account
75
+ load_account
76
+ end
77
+
78
+ private
79
+ def save_account
80
+ if not @account.blank?
81
+ if @account.unencrypted_password != @pass.value && @account.password_confirmation.blank?
82
+ password_dialog = Wx::PasswordEntryDialog.new(self, "Please confirm the password")
83
+ if password_dialog.show_modal == Wx::ID_OK
84
+ @account.password_confirmation = password_dialog.get_value
85
+ @account.unencrypted_password = @pass.value
86
+ end
87
+ end
88
+ @account.name = @name.value
89
+ @account.user_name = @user.value
90
+ @account.url = @url.value
91
+ end
92
+ end
93
+ def load_account
94
+ if not @account.name.blank?
95
+ @name.value = @account.name
96
+ @url.value = @account.url
97
+ @user.value = @account.user_name
98
+ @pass.value = @account.unencrypted_password.blank? ? @account.password : @account.unencrypted_password
99
+ end
100
+ end
101
+
102
+ end
103
+ end