reedb 0.10.rc1

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.
@@ -0,0 +1,94 @@
1
+ # ====================================================
2
+ # Copyright 2015 Random Robot Softworks (see @author)
3
+ # @author: Leander Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ require_relative 'encryption'
11
+ require 'aes'
12
+
13
+ module Reedb
14
+ class RAES < MCypher
15
+ def initialize
16
+ super # => Super constructor
17
+ end
18
+
19
+ # Starts the encryption and loads a key by either generating a new one
20
+ # or loading an encrypted one from file.
21
+ #
22
+ def start_encryption(password, raw_key = nil)
23
+ if raw_key != nil
24
+ # => Decrypting key with user password
25
+ @key = AES.decrypt(raw_key, password)
26
+ else
27
+ # => Generating new key and encrypting it with user pw
28
+ @key = AES.key
29
+ key_encrypted = AES.encrypt(@key, password)
30
+ end
31
+
32
+ # => At this point @key should be the unencrypted key!
33
+ @init = true
34
+ return key_encrypted
35
+ end
36
+
37
+ # Tries to remove the unencryted key from memory as best as possible.
38
+ # Stops the encryption and prevents further decrypts to occur.
39
+ def stop_encryption
40
+ remove_instance_variable(:@key)
41
+ @init = false
42
+ end
43
+
44
+ # Encrypt the clear text using the encryption key
45
+ # Returns a base64 encoded string
46
+ # Throws exceptions
47
+ #
48
+ def encrypt(data)
49
+ begin
50
+ return AES.encrypt(data, @key) unless @key.nil?
51
+ rescue Exception => e
52
+ puts e.message
53
+ raise EncryptionFailedError.new, "An error was encountered while encrypting data"
54
+ end
55
+ end
56
+
57
+ # Decrypt the cypher text using the encryption key
58
+ # Returns the original clear text.
59
+ # Throws exceptions
60
+ #
61
+ def decrypt(data)
62
+ begin
63
+ return AES.decrypt(data, @key) unless @key.nil?
64
+ rescue Exception => e
65
+ puts e.message
66
+ raise DecryptionFailedError.new, "An error was encountered while decrypting data"
67
+ end
68
+ end
69
+
70
+ # Starts the shift of the main password and creates a new key (cipher) to encrypt with the new pw
71
+ #
72
+ def init_shift
73
+ @tmp_key = AES.key
74
+ end
75
+
76
+ # Change the encryption cipher for a file in the vault.
77
+ #
78
+ def shift_cipher(file)
79
+ temp = AES.decrypt(file, @key) unless @key.nil?
80
+ return AES.encrypt(temp, @tmp_key)
81
+ end
82
+
83
+ # Returns new encrypted key
84
+ #
85
+ def finalise_shift(fresh)
86
+ @key = @tmp_key # => Finishing the cipher shift
87
+ key_encrypted = AES.encrypt(@tmp_key, fresh)
88
+ remove_instance_variable(:@tmp_key) # => Removing insecure imprint
89
+
90
+ return key_encrypted # => To be stored in the new config file!
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,64 @@
1
+ # ====================================================
2
+ # Copyright 2015 Random Robot Softworks (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 2.1
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ require 'digest'
11
+
12
+
13
+ # Master crypt module to be extended by specific cyphers
14
+ module Reedb
15
+ class MCypher
16
+
17
+ # Attribute reader to get init state of crypt module
18
+ #
19
+ attr_reader :init
20
+
21
+ def initialize()
22
+ @init = false
23
+ end
24
+
25
+ def start_encryption
26
+ end
27
+
28
+ def stop_encryption
29
+ end
30
+
31
+ def encrypt(string)
32
+ end
33
+
34
+ def decrypt(string)
35
+ end
36
+ end
37
+
38
+ class SecurityUtils
39
+
40
+ # => Returns 190 bit tiger hash
41
+ # DO NOT USE FOR PASSWORD HASHING!
42
+ # Used to hash file-names in vaults
43
+ #
44
+ def self.tiger_hash(string)
45
+ if Reedb::verbose?
46
+ DaemonLogger.write("[FIX ME]: t_hash is a broken function!", "warn")
47
+ end
48
+ return self.sha512_hash("#{string}")
49
+ # Digest::Tiger.hexdigest("#{string}")
50
+ end
51
+
52
+ # => Returns 64 byte sha hash.
53
+ # DO NOT USE FOR PASSWORD HASHING!
54
+ # Used for integrety checking files
55
+ #
56
+ def self.sha512_hash(string)
57
+ return Digest::SHA256.hexdigest("#{string}")
58
+ end
59
+
60
+ def self.name_col_hash(string)
61
+ return "---#{string}"
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,15 @@
1
+ # ====================================================
2
+ # Copyright 2015 Random Robot Softworks (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 2.1
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ module Reedb
11
+ class MLE
12
+
13
+ end
14
+ end
15
+
@@ -0,0 +1,131 @@
1
+ # Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm).
2
+ # Copyright (c) 2013, Taylor Hornby
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # 1. Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ # POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ require 'securerandom'
29
+ require 'openssl'
30
+ require 'base64'
31
+
32
+ # Salted password hashing with SHA2.
33
+ # Authors: @RedragonX (dicesoft.net), havoc AT defuse.ca
34
+ # @SpaceKookie, spacekookie AT c-base.org
35
+ #
36
+ # www: http://crackstation.net/hashing-security.htm
37
+ module Reedb
38
+
39
+ class SecureHash
40
+
41
+ # Constants for the hashing process.
42
+ # Can be changed without breaking existing hashes!
43
+ PBKDF2_ITERATIONS = 10000
44
+ SALT_BYTE_SIZE = 32
45
+ HASH_BYTE_SIZE = 24
46
+
47
+ HASH_SECTIONS = 3
48
+ SECTION_DELIMITER = '::'
49
+ ITERATIONS_INDEX = 0
50
+ SALT_INDEX = 1
51
+ HASH_INDEX = 2
52
+
53
+ def self.secure_hash password
54
+ salt = SecureRandom.base64(SALT_BYTE_SIZE)
55
+ sha256 = OpenSSL::Digest::SHA256.new
56
+ len = sha256.digest_length
57
+ pbkdf2 = OpenSSL::PKCS5.pbkdf2_hmac(
58
+ password,
59
+ salt,
60
+ PBKDF2_ITERATIONS,
61
+ len,
62
+ sha256
63
+ )
64
+
65
+ return [PBKDF2_ITERATIONS, salt, Base64.encode64( pbkdf2 )].join( SECTION_DELIMITER )
66
+ end
67
+
68
+ # Checks if a password is correct given a hash of the correct one.
69
+ # correctHash must be a hash string generated with createHash.
70
+ def self.validate_pw(password, correctHash)
71
+ params = correctHash.split(SECTION_DELIMITER)
72
+ return false if params.length != HASH_SECTIONS
73
+
74
+ salt = params[SALT_INDEX]
75
+ hash = [HASH_INDEX]
76
+
77
+ sha256 = OpenSSL::Digest::SHA256.new
78
+ len = sha256.digest_length
79
+
80
+ confirmed = Base64.decode64(params[HASH_INDEX])
81
+ test_hash = OpenSSL::PKCS5.pbkdf2_hmac(
82
+ password,
83
+ salt,
84
+ PBKDF2_ITERATIONS,
85
+ len,
86
+ sha256
87
+ )
88
+
89
+ return confirmed == test_hash
90
+ end
91
+
92
+ # Run tests to ensure the module is functioning properly.
93
+ # Returns true if all tests succeed, false if not.
94
+ def self.runSelfTests
95
+ puts "Sample hashes:"
96
+ 3.times { puts secure_hash("password") }
97
+
98
+ puts "\nRunning self tests..."
99
+ @@allPass = true
100
+
101
+ correctPassword = 'aaaaaaaaaa'
102
+ wrongPassword = 'aaaaaaaaab'
103
+ hash = secure_hash(correctPassword)
104
+
105
+ assert( validate_pw( correctPassword, hash ) == true, "correct password" )
106
+ assert( validate_pw( wrongPassword, hash ) == false, "wrong password" )
107
+
108
+ h1 = hash.split( SECTION_DELIMITER )
109
+ h2 = secure_hash( correctPassword ).split( SECTION_DELIMITER )
110
+ assert( h1[HASH_INDEX] != h2[HASH_INDEX], "different hashes" )
111
+ assert( h1[SALT_INDEX] != h2[SALT_INDEX], "different salt" )
112
+
113
+ if @@allPass
114
+ puts "*** ALL TESTS PASS ***"
115
+ else
116
+ puts "*** FAILURES ***"
117
+ end
118
+
119
+ return @@allPass
120
+ end
121
+
122
+ def self.assert( truth, msg )
123
+ if truth
124
+ puts "PASS [#{msg}]"
125
+ else
126
+ puts "FAIL [#{msg}]"
127
+ @@allPass = false
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,14 @@
1
+ # ====================================================
2
+ # Copyright 2015 Random Robot Softworks (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 2.1
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ module Reedb
11
+ class Fish
12
+
13
+ end
14
+ end
@@ -0,0 +1,97 @@
1
+ # ====================================================
2
+ # Copyright 2015 Lonely Robot (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ require 'logger'
11
+
12
+ module Reedb
13
+
14
+ # A logger that gets bound to a vault and logs vault activity in the
15
+ # vaults logs/ directory.
16
+ # It's using the Ruby internal logging library to split up logs into date blocks.
17
+ # (Each day is one log file).
18
+ #
19
+ class VaultLogger
20
+
21
+ @@logger = nil
22
+
23
+ # Sets up a logger on a vault and loads existing logs if they exist.
24
+ # Logs are limited not in size but only by dates. Vault logs don't contain whitespaces.
25
+ #
26
+ def self.setup(path)
27
+ log_path = "#{path}/logs/#{Reedb::Utilities.get_time(true)}.log"
28
+ @@logger = Logger.new("#{log_path}")
29
+ end
30
+
31
+
32
+ # Writes something to the current vault log (under #{@path}/logs/)
33
+ # Possible parameters are:
34
+ # 'debug':: Throwing every operation at the log.
35
+ # 'info':: Default logging level for most situations and events.
36
+ # 'warn':: Logs a warning. Should be event that won't impact stability.
37
+ # 'error':: Logs an error. Should be recoverable event.
38
+ # 'fatal':: Logs a fatal crash. Should make the Reepass daemon crash!
39
+ def self.write(message, level = "")
40
+ if level == "warn"
41
+ @@logger.warn(message)
42
+
43
+ elsif level == "debug"
44
+ @@logger.debug(message)
45
+
46
+ elsif level == "error"
47
+ @@logger.error(message)
48
+
49
+ elsif level == "fatal"
50
+ @@logger.fatal(message)
51
+
52
+ else
53
+ @@logger.info(message)
54
+ end
55
+ end
56
+ end
57
+
58
+ class DaemonLogger
59
+
60
+ @@logger = nil
61
+
62
+ # Sets up a logger on a vault and loads existing logs if they exist.
63
+ # Logs are limited not in size but only by dates. Vault logs don't contain whitespaces.
64
+ #
65
+ def self.setup(path)
66
+ log_path = "#{path}/#{Reedb::Utilities.get_time(true)}.log"
67
+ @@logger = Logger.new("#{log_path}")
68
+ end
69
+
70
+
71
+ # Writes something to the current vault log (under #{@path}/logs/)
72
+ # Possible parameters are:
73
+ # 'debug':: Throwing every operation at the log.
74
+ # 'info':: Default logging level for most situations and events.
75
+ # 'warn':: Logs a warning. Should be event that won't impact stability.
76
+ # 'error':: Logs an error. Should be recoverable event.
77
+ # 'fatal':: Logs a fatal crash. Should make the Reepass daemon crash!
78
+ def self.write(message, level = "")
79
+ if level == "warn"
80
+ @@logger.warn(message)
81
+
82
+ elsif level == "debug"
83
+ @@logger.debug(message)
84
+
85
+ elsif level == "error"
86
+ @@logger.error(message)
87
+
88
+ elsif level == "fatal"
89
+ @@logger.fatal(message)
90
+
91
+ else
92
+ @@logger.info(message)
93
+ end
94
+ end
95
+ end # End of class
96
+
97
+ end
@@ -0,0 +1,28 @@
1
+ # ====================================================
2
+ # Copyright 2015 Lonely Robot (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ module Reedb
11
+
12
+ # Handler class to map vaults in the reedb api to a set
13
+ class MetaVault
14
+ attr_accessor :name, :path, :size, :uuid
15
+
16
+ def initialize(name, path, size, uuid)
17
+ @name = name
18
+ @path = path
19
+ @size = size
20
+ @uuid = uuid
21
+ end
22
+
23
+ # Used to compare vaults
24
+ def includes?(name) return (@name == name) end
25
+ def includes?(name, path) return (@name == name && @path == path) end
26
+ def to_s() return "'#{@name}'@'#{@path}', size: #{@size}" end
27
+ end
28
+ end