safedb 0.5.1005 → 0.7.1001
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +1 -1
- data/genius-decision.txt +25 -0
- data/lib/cli.rb +155 -8
- data/lib/controller/{admin/auth.rb → abstract/authenticate.rb} +1 -2
- data/lib/controller/{controller.rb → abstract/controller.rb} +45 -24
- data/lib/controller/{edit/editverse.rb → abstract/edit_verse.rb} +0 -0
- data/lib/controller/{query/queryverse.rb → abstract/query_verse.rb} +0 -0
- data/lib/controller/{admin → access}/README.md +0 -0
- data/lib/controller/access/banner.txt +6 -0
- data/lib/controller/{admin → access}/init.rb +4 -4
- data/lib/controller/{admin → access}/login.rb +28 -23
- data/lib/controller/{admin → access}/logout.rb +0 -0
- data/lib/controller/{admin → access}/token.rb +0 -0
- data/lib/controller/{admin → access}/use.rb +0 -0
- data/lib/controller/api/docker/docker.rb +4 -22
- data/lib/controller/api/git/git.rb +104 -0
- data/lib/controller/api/terraform/README.md +23 -2
- data/lib/controller/api/terraform/terraform.rb +38 -7
- data/lib/controller/{admin → book}/commit.rb +2 -3
- data/lib/controller/{admin → book}/diff.rb +0 -0
- data/lib/controller/{admin → book}/export.rb +0 -0
- data/lib/controller/{admin → book}/import.rb +0 -0
- data/lib/controller/{admin → book}/refresh.rb +2 -2
- data/lib/controller/{admin → book}/view.rb +0 -0
- data/lib/{modules/storage/git.store.rb → controller/db/model_git_service.rb} +0 -0
- data/lib/controller/db/pull.rb +69 -0
- data/lib/controller/db/push.rb +352 -0
- data/lib/controller/db/remote.rb +108 -0
- data/lib/controller/edit/generate.rb +1 -1
- data/lib/controller/edit/keys.rb +72 -0
- data/lib/controller/edit/paste.rb +36 -0
- data/lib/controller/files/write.rb +11 -3
- data/lib/controller/misc/wipe.rb +23 -0
- data/lib/controller/navigate/at.rb +42 -0
- data/lib/controller/{admin → navigate}/goto.rb +0 -0
- data/lib/controller/{admin → navigate}/open.rb +0 -0
- data/lib/controller/query/copy.rb +32 -95
- data/lib/controller/query/tell.rb +36 -0
- data/lib/controller/requirer.rb +4 -4
- data/lib/controller/visit/README.md +34 -0
- data/lib/controller/visit/visit.rb +33 -0
- data/lib/manual/copy-paste.md +19 -2
- data/lib/{modules/README.md → manual/crypto-math.md} +0 -0
- data/lib/manual/push-pull.md +46 -0
- data/lib/manual/remote.md +62 -0
- data/lib/model/coordinates.rb +59 -0
- data/lib/model/{safe_tree.rb → file_tree.rb} +11 -6
- data/lib/model/indices.rb +113 -8
- data/lib/model/master.rb +40 -0
- data/lib/model/{state.migrate.rb → state_evolve.rb} +13 -5
- data/lib/model/{state.inspect.rb → state_query.rb} +5 -1
- data/lib/plugin/github.rb +53 -0
- data/lib/{modules/cryptology → utils/ciphers}/aes-256.rb +0 -0
- data/lib/{modules/cryptology → utils/ciphers}/blowfish.rb +0 -0
- data/lib/{modules/cryptology → utils/ciphers}/cipher.rb +0 -0
- data/lib/{modules/cryptology → utils/ciphers}/crypt.io.rb +0 -0
- data/lib/utils/keys/key.rb +44 -0
- data/lib/utils/keys/keypair.rb +52 -0
- data/lib/utils/logs/logger.rb +1 -1
- data/lib/utils/store/datastore.rb +1 -1
- data/lib/utils/store/github.rb +27 -0
- data/lib/utils/time/timestamp.rb +91 -0
- data/lib/version.rb +1 -1
- data/safedb.gemspec +2 -0
- metadata +75 -32
- data/lib/controller/verse.rb +0 -20
- data/lib/modules/storage/coldstore.rb +0 -186
- data/lib/utils/store/test-commands.sh +0 -24
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
#### create a remote backend store from which you can `safe push` and `safe pull` your encrypted database assets.
|
3
|
+
|
4
|
+
# provision a github repository backend
|
5
|
+
|
6
|
+
We want to provision (create) the safe's remote (github) backend so that we can access it from different machines. This is how we provision a Github remote backend do it.
|
7
|
+
|
8
|
+
### safe remote --provision
|
9
|
+
|
10
|
+
Before you use safe remote to provision a github git repository backend for your crypts ensure that
|
11
|
+
|
12
|
+
- you have a github account (with username)
|
13
|
+
- you have created a (40 character hexadecimal) github access token
|
14
|
+
- you have inserted this data at a suitable chapter and verse
|
15
|
+
- you run **`safe remote --provision`** from this opened book/chapter/verse
|
16
|
+
|
17
|
+
Below is the sequence of commands leading up to **`safe remote --provision`**
|
18
|
+
|
19
|
+
```
|
20
|
+
safe init db.admin
|
21
|
+
safe login db.admin
|
22
|
+
safe open remote.backend github
|
23
|
+
safe put @github.token 43210fedcba43210fedcba43210fedcba43210fedcba
|
24
|
+
safe configure backend db.admin/remote.backend/github
|
25
|
+
safe remote --provision
|
26
|
+
```
|
27
|
+
|
28
|
+
## focus | safe put @github.token
|
29
|
+
|
30
|
+
**@todo** - *we need to refactor out this business of configuring the backend. This should be done **automagically** by the remote commaand expecting to be at the correct book/chapter/verse*
|
31
|
+
|
32
|
+
safe knows how to talk to the Github Rest API as long as you provide a github access token. [Visit how to acquire a Github access token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line).
|
33
|
+
|
34
|
+
## safe configure @github.token
|
35
|
+
|
36
|
+
The **`safe configure`** command tell's safe which book, chapter and verse (in our case db.admin/remote.backend/github) that contains the backend repository access properties.
|
37
|
+
|
38
|
+
## safe remote --provision
|
39
|
+
|
40
|
+
A number of setup tasks are executed when you ask that the backend repository be created.
|
41
|
+
|
42
|
+
- a repository is created in github
|
43
|
+
- the git fetch (https) and git push (ssh) urls are fabricated
|
44
|
+
- the fetch url is written into the master keys file
|
45
|
+
- the push url is written to the configured chapter/verse location
|
46
|
+
- a ssh public/private keypair (using EC25519) is created
|
47
|
+
- the private and public keys are placed within the chapter/verse
|
48
|
+
- the public (deploy) key is registered with the github repository
|
49
|
+
|
50
|
+
Now you are ready to push and pull.
|
51
|
+
|
52
|
+
Visit the [safe push](push-pull) and [safe pull](push-pull) documentation to discover howto use your safe database on as many machines as you need.
|
53
|
+
|
54
|
+
|
55
|
+
## where is the safe database?
|
56
|
+
|
57
|
+
A safe database is always encrypted at rest and consiss of just 3 simple parts
|
58
|
+
|
59
|
+
- **backend** - a set of encrypted files kept either in **`~/.safedb.net/safedb-master-crypts`** or in a git repository
|
60
|
+
- **frontend** - a single state tracking file called <tt>safedb-dataase-tracker.ini</tt> (usually) on a removable drive
|
61
|
+
- one password - known by the database owner allowing them to login and access the information held within the database
|
62
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
# Coordinates point to either a book, or a book/chapter or a book/chapter/verse
|
6
|
+
# location. The location pointed to may or may not exist and even if they do they
|
7
|
+
# may not be accessible if they exist within a book that (as of yet) we have not
|
8
|
+
# logged into.
|
9
|
+
class Coordinates
|
10
|
+
|
11
|
+
|
12
|
+
# Initialize coordinates to a location within a book and/or chapter and/or verse.
|
13
|
+
#
|
14
|
+
# @param coordinates_str [String]
|
15
|
+
# this parameter should be a book/chapter/verse separated
|
16
|
+
# by forward slashes.
|
17
|
+
def initialize( coordinates_str )
|
18
|
+
|
19
|
+
KeyError.not_new( coordinates_str, self )
|
20
|
+
@coords_list = @coords_list.split( "/" )
|
21
|
+
bcv_error_msg = "Invalid / separated book chapter and verse coordinates ~> #{@coords_list}"
|
22
|
+
raise ArgumentError.new( bcv_error_msg ) unless @coords_list.length() == 3
|
23
|
+
|
24
|
+
@book_name = @coords_list[ 0 ].strip()
|
25
|
+
@chapter_name = @coords_list[ 1 ].strip()
|
26
|
+
@verse_name = @coords_list[ 2 ].strip()
|
27
|
+
|
28
|
+
log.info(x) { "Initializing a book chapter and verse coordinate within book [#{@book_name}]." }
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# Do the (book, chapter or verse) that our said coordinates point
|
34
|
+
# to exist.
|
35
|
+
def exists?()
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# Do our coordinates point to an existing verse in a chapter within
|
40
|
+
# the current logged in book.
|
41
|
+
def is_verse?()
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# Do our coordinates point to an existing chapter within the currently
|
46
|
+
# logged in book.
|
47
|
+
def is_chapter?()
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Do our coordinates point to any currently logged in book.
|
52
|
+
def is_book?()
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
end
|
@@ -22,9 +22,12 @@ module SafeDb
|
|
22
22
|
end
|
23
23
|
|
24
24
|
|
25
|
+
# Get the path to the folder that holds the master crypts for the
|
26
|
+
# book ID specified in the parameter.
|
27
|
+
# @param book_id [String] the identifier of the book in question
|
28
|
+
# @return [File] path to the master crypts folder for the book
|
25
29
|
def self.master_crypts_folder( book_id )
|
26
|
-
|
27
|
-
return File.join( master_crypts_folder, "safedb.book.#{book_id}" )
|
30
|
+
return File.join( Indices::MASTER_CRYPTS_FOLDER_PATH, "safedb.book.#{book_id}" )
|
28
31
|
end
|
29
32
|
|
30
33
|
|
@@ -34,14 +37,16 @@ module SafeDb
|
|
34
37
|
|
35
38
|
|
36
39
|
def self.branch_crypts_folder( book_id, branch_id )
|
37
|
-
|
38
|
-
return File.join( branch_crypts_folder, "safedb-branch-#{book_id}-#{branch_id}" )
|
40
|
+
return File.join( Indices::BRANCH_CRYPTS_FOLDER_PATH, "safedb-branch-#{book_id}-#{branch_id}" )
|
39
41
|
end
|
40
42
|
|
41
43
|
|
44
|
+
# Get the path to the branch indices file for the branch ID
|
45
|
+
# specified in the parameter.
|
46
|
+
# @param branch_id [String] the identifier of the branch in question
|
47
|
+
# @return [File] path to the branch indices file for the given branch
|
42
48
|
def self.branch_indices_filepath( branch_id )
|
43
|
-
|
44
|
-
return File.join( branch_indices_folder, "safedb-indices-#{branch_id}.ini" )
|
49
|
+
return File.join( Indices::BRANCH_INDICES_FOLDER_PATH, "safedb-indices-#{branch_id}.ini" )
|
45
50
|
end
|
46
51
|
|
47
52
|
|
data/lib/model/indices.rb
CHANGED
@@ -16,26 +16,119 @@ module SafeDb
|
|
16
16
|
# The desired length of a safe book ergonomic identifier.
|
17
17
|
SAFE_BOOK_ID_LENGTH = 12
|
18
18
|
|
19
|
+
# The file-system location of the safe database tree
|
20
|
+
SAFE_DATABASE_FOLDER = File.join( Dir.home, ".#{SAFE_URL_NAME}" )
|
21
|
+
|
19
22
|
# The fully qualified domain name of the safedb home website
|
20
23
|
SAFE_GEM_WEBSITE = "https://www.#{SAFE_URL_NAME}"
|
21
24
|
|
22
25
|
# The safe database github clonable url for the ruby software
|
23
26
|
SAFE_GITHUB_URL = "https://github.com/devops4me/#{SAFE_URL_NAME}"
|
24
27
|
|
25
|
-
# The name
|
28
|
+
# The name of the master crypts folder.
|
26
29
|
MASTER_CRYPTS_FOLDER_NAME = "safedb-master-crypts"
|
27
30
|
|
28
|
-
# The
|
29
|
-
|
31
|
+
# The path to the master crypts folder.
|
32
|
+
MASTER_CRYPTS_FOLDER_PATH = File.join( SAFE_DATABASE_FOLDER, MASTER_CRYPTS_FOLDER_NAME )
|
33
|
+
|
34
|
+
# The path to the master crypts .git directory.
|
35
|
+
MASTER_CRYPTS_GIT_PATH = File.join( MASTER_CRYPTS_FOLDER_PATH, ".git" )
|
36
|
+
|
37
|
+
# The name of the branch indices folder.
|
38
|
+
BRANCH_INDICES_FOLDER_NAME = "safedb-branch-keys"
|
39
|
+
|
40
|
+
# The path to the branch indices folder.
|
41
|
+
BRANCH_INDICES_FOLDER_PATH = File.join( SAFE_DATABASE_FOLDER, BRANCH_INDICES_FOLDER_NAME )
|
30
42
|
|
31
|
-
# The name
|
43
|
+
# The name of the branch crypts folder.
|
32
44
|
BRANCH_CRYPTS_FOLDER_NAME = "safedb-branch-crypts"
|
33
45
|
|
34
|
-
# The
|
35
|
-
|
46
|
+
# The path to the branch crypts folder.
|
47
|
+
BRANCH_CRYPTS_FOLDER_PATH = File.join( SAFE_DATABASE_FOLDER, BRANCH_CRYPTS_FOLDER_NAME )
|
48
|
+
|
49
|
+
# The master indices file name
|
50
|
+
MASTER_INDICES_FILE_NAME = "safedb-master-keys.ini"
|
36
51
|
|
37
52
|
# The path to the master indices file
|
38
|
-
MASTER_INDICES_FILEPATH = File.join( SAFE_DATABASE_FOLDER,
|
53
|
+
MASTER_INDICES_FILEPATH = File.join( SAFE_DATABASE_FOLDER, MASTER_INDICES_FILE_NAME )
|
54
|
+
|
55
|
+
# The path to the remote storage configuration INI file
|
56
|
+
MACHINE_CONFIG_FILEPATH = File.join( SAFE_DATABASE_FOLDER, "safedb-remote-storage.ini" )
|
57
|
+
|
58
|
+
# The name of the machine removable drive path location directive
|
59
|
+
MACHINE_REMOVABLE_DRIVE_PATH = "removable.drive"
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
# The keyname whose value denotes a local folder path to clone to
|
64
|
+
GIT_CLONE_BASE_PATH = "git.clone.base.path"
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
# The name of the keys section that holds remote mirror properties
|
70
|
+
REMOTE_MIRROR_SECTION_NAME = "remote.mirror"
|
71
|
+
|
72
|
+
# The name of the property that points to the book/chapter/verse (page)
|
73
|
+
REMOTE_MIRROR_PAGE_NAME = "remote.mirror.page"
|
74
|
+
|
75
|
+
# The ending of the private key filename for remote mirror push access
|
76
|
+
REMOTE_MIRROR_PRIVATE_KEY_POSTFIX = "private-key.pem"
|
77
|
+
|
78
|
+
# The key name that holds the remote mirror private key filename
|
79
|
+
REMOTE_PRIVATE_KEY_KEYNAME = "private.key.filename"
|
80
|
+
|
81
|
+
# The key name that holds the remote mirror ssh config host value
|
82
|
+
REMOTE_MIRROR_SSH_HOST_KEYNAME = "ssh.config.host"
|
83
|
+
|
84
|
+
# The path to the SSH directory
|
85
|
+
SSH_DIRECTORY_PATH = File.join( Dir.home(), ".ssh" )
|
86
|
+
|
87
|
+
# The path to the SSH config file
|
88
|
+
SSH_CONFIG_FILE_PATH = File.join( SSH_DIRECTORY_PATH, "config" )
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
# This access token allows us to talk to the Github API
|
95
|
+
GITHUB_ACCESS_TOKEN = "@github.access.token"
|
96
|
+
|
97
|
+
# Github repository keyname
|
98
|
+
GIT_REPOSITORY_NAME_KEYNAME = "repository.name"
|
99
|
+
|
100
|
+
# Github Username Keyname
|
101
|
+
GIT_REPOSITORY_USER_KEYNAME = "repository.user"
|
102
|
+
|
103
|
+
# Github Host Keyname
|
104
|
+
GIT_REPOSITORY_HOST_KEYNAME = "repository.host"
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
# Keyname for when the last backend push occured
|
110
|
+
REMOTE_LAST_PUSH_ON = "last.push.on"
|
111
|
+
|
112
|
+
# Keyname for the user and hostname that evoked the last push
|
113
|
+
REMOTE_LAST_PUSH_BY = "last.push.by"
|
114
|
+
|
115
|
+
# Keyname for the ID of the last push (Usually Git Commit Reference)
|
116
|
+
REMOTE_LAST_PUSH_ID = "last.push.id"
|
117
|
+
|
118
|
+
# Private Key Default Key Name
|
119
|
+
PRIVATE_KEY_DEFAULT_KEY_NAME = "private.key"
|
120
|
+
|
121
|
+
# Public Key Default Key Name
|
122
|
+
PUBLIC_KEY_DEFAULT_KEY_NAME = "public.key"
|
123
|
+
|
124
|
+
# The parameter key name to configure the backend coordinates
|
125
|
+
CONFIGURE_BACKEND_KEY_NAME = "backend"
|
126
|
+
|
127
|
+
# The name of the remote database git pull url key
|
128
|
+
REMOTE_DATABASE_GIT_PULL_URL = "git.pull.url"
|
129
|
+
|
130
|
+
# The name of the remote database git push url key
|
131
|
+
REMOTE_DATABASE_GIT_PUSH_URL = "git.push.url"
|
39
132
|
|
40
133
|
# The desired length of a content identifier
|
41
134
|
CONTENT_ID_LENGTH = 14
|
@@ -90,7 +183,7 @@ module SafeDb
|
|
90
183
|
|
91
184
|
# Character (randomly) repeated to mask credentials
|
92
185
|
# Asterices, hyphens, plus and equal signs are common alternatives.
|
93
|
-
SECRET_MASK_STRING = "*" * rand(
|
186
|
+
SECRET_MASK_STRING = "*" * rand( 18 .. 30 )
|
94
187
|
|
95
188
|
# The birthday (initialization time) of this safe book.
|
96
189
|
SAFE_BOOK_INITIALIZE_TIME = "book.init.time"
|
@@ -125,6 +218,18 @@ module SafeDb
|
|
125
218
|
# Handle to the simple name of the ingested file in the submap verse
|
126
219
|
INGESTED_FILE_BASE_NAME_KEY = "file.name"
|
127
220
|
|
221
|
+
# The permission setting (chmod) key name
|
222
|
+
FILE_CHMOD_PERMISSIONS_KEY = "file.access"
|
223
|
+
|
224
|
+
# The keypair name prefix for private keys.
|
225
|
+
PRIVATE_KEY_PREFIX = "private.key"
|
226
|
+
|
227
|
+
# The keypair name prefix for public keys.
|
228
|
+
PUBLIC_KEY_PREFIX = "public.key"
|
229
|
+
|
230
|
+
# Elliptic Curve SSL Key Type
|
231
|
+
ELLIPTIC_CURVE_KEY_TYPE = "secp384r1"
|
232
|
+
|
128
233
|
|
129
234
|
end
|
130
235
|
|
data/lib/model/master.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
# This master data structure controls the key publicly visible properties for
|
6
|
+
# the safe database be it in a local or remote location.
|
7
|
+
#
|
8
|
+
# This object mapper seals away details of the persistence engine involved.
|
9
|
+
# Who knows, it could be a local drive, an S3 bucket and even a database.
|
10
|
+
class Master
|
11
|
+
|
12
|
+
# Initialize an instance of this safe database's master properties.
|
13
|
+
def initialize()
|
14
|
+
@master = DataMap.new( Indices::MASTER_INDICES_FILEPATH )
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
# Get the coordinates (book, chapter and verse) of the verse that holds
|
19
|
+
# the remote backend properties. An exception will be thrown if no backend
|
20
|
+
# coordinates have been set.
|
21
|
+
# @return [String] the backend coordinates to set
|
22
|
+
def get_backend_coordinates()
|
23
|
+
@master.use( Indices::REMOTE_MIRROR_SECTION_NAME )
|
24
|
+
return @master.get( Indices::REMOTE_MIRROR_PAGE_NAME )
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Set the coordinates (book, chapter and verse) of the verse that holds
|
29
|
+
# the remote backend properties.
|
30
|
+
# @param backend_coordinates [String] the backend coordinates to set
|
31
|
+
def set_backend_coordinates( backend_coordinates )
|
32
|
+
@master.use( Indices::REMOTE_MIRROR_SECTION_NAME )
|
33
|
+
@master.set( Indices::REMOTE_MIRROR_PAGE_NAME, backend_coordinates )
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
@@ -10,7 +10,7 @@ module SafeDb
|
|
10
10
|
# - <tt>commit</tt> - transfers state from branch to master
|
11
11
|
# - <tt>refresh</tt> - transfers state from master to branch
|
12
12
|
#
|
13
|
-
class
|
13
|
+
class EvolveState
|
14
14
|
|
15
15
|
# The login process recycles the content encryption key by regenerating the human
|
16
16
|
# key from the password text and salts and then accessing the old crypt key, generating
|
@@ -42,7 +42,7 @@ module SafeDb
|
|
42
42
|
# used for the asymmetric decryption of the content ciphertext which is in a
|
43
43
|
# file marked with the content identifier also within the book keys.
|
44
44
|
#
|
45
|
-
# @param
|
45
|
+
# @param human_secret [String]
|
46
46
|
# the secret text that can potentially be cryptographically weak (low entropy).
|
47
47
|
# This text is severely strengthened and morphed into a key using multiple key
|
48
48
|
# derivation functions like <b>PBKDF2, BCrypt</b> and <b>SCrypt</b>.
|
@@ -54,22 +54,30 @@ module SafeDb
|
|
54
54
|
# The key ring only stores the salts. This means the secret text based key can
|
55
55
|
# only be regenerated at the next login, which explains the inter-branch label.
|
56
56
|
#
|
57
|
-
|
57
|
+
# @return [Boolean]
|
58
|
+
# return false if failure decrypting with human password occurs.
|
59
|
+
# True is returned if the login logic completes naturally.
|
60
|
+
def self.login( book_keys, human_secret )
|
58
61
|
|
59
62
|
the_book_id = book_keys.section()
|
60
63
|
|
61
|
-
old_human_key = KdfApi.regenerate_from_salts(
|
64
|
+
old_human_key = KdfApi.regenerate_from_salts( human_secret, book_keys )
|
65
|
+
is_correct_password = old_human_key.can_decrypt_key( book_keys.get( Indices::CRYPT_CIPHER_TEXT ) )
|
66
|
+
return false unless is_correct_password
|
67
|
+
|
62
68
|
the_crypt_key = old_human_key.do_decrypt_key( book_keys.get( Indices::CRYPT_CIPHER_TEXT ) )
|
63
69
|
plain_content = Content.unlock_master( the_crypt_key, book_keys )
|
64
70
|
|
65
71
|
first_login_since_boot = StateInspect.is_first_login?( book_keys )
|
66
72
|
the_crypt_key = Key.from_random if first_login_since_boot
|
67
|
-
recycle_keys( the_crypt_key, the_book_id,
|
73
|
+
recycle_keys( the_crypt_key, the_book_id, human_secret, book_keys, plain_content )
|
68
74
|
set_bootup_id( book_keys ) if first_login_since_boot
|
69
75
|
|
70
76
|
branch_id = Identifier.derive_branch_id( Branch.to_token() )
|
71
77
|
clone_book_into_branch( the_book_id, branch_id, book_keys, the_crypt_key )
|
72
78
|
|
79
|
+
return true
|
80
|
+
|
73
81
|
end
|
74
82
|
|
75
83
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module SafeDb
|
4
4
|
|
5
|
-
# State queries are related to {
|
5
|
+
# State queries are related to {EvolveState} but they simple ask for information
|
6
6
|
# about the state without changing any state.
|
7
7
|
#
|
8
8
|
class StateInspect
|
@@ -42,6 +42,9 @@ module SafeDb
|
|
42
42
|
branch_key_ciphertext = branch_keys.get( Indices::CRYPT_CIPHER_TEXT )
|
43
43
|
branch_key = KeyDerivation.regenerate_shell_key( Branch.to_token() )
|
44
44
|
|
45
|
+
return branch_key.can_decrypt_key( branch_key_ciphertext )
|
46
|
+
|
47
|
+
=begin
|
45
48
|
begin
|
46
49
|
branch_key.do_decrypt_key( branch_key_ciphertext )
|
47
50
|
return true
|
@@ -50,6 +53,7 @@ module SafeDb
|
|
50
53
|
log.warn(x) { "Login failure error message is #{e.message}" }
|
51
54
|
return false
|
52
55
|
end
|
56
|
+
=end
|
53
57
|
|
54
58
|
end
|
55
59
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
# This class knows how to talk to Github and callers can delegate common
|
6
|
+
# github functionality like creating repositories, listing repositories,
|
7
|
+
# downloading repositories and the like.
|
8
|
+
#
|
9
|
+
class Github
|
10
|
+
|
11
|
+
# Initialize an instance of this safe database's master properties.
|
12
|
+
def initialize()
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# Test the Github api using curl
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com
|
23
|
+
#
|
24
|
+
#
|
25
|
+
|
26
|
+
|
27
|
+
@master = DataMap.new( Indices::MASTER_INDICES_FILEPATH )
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
# Get the coordinates (book, chapter and verse) of the verse that holds
|
32
|
+
# the remote backend properties. An exception will be thrown if no backend
|
33
|
+
# coordinates have been set.
|
34
|
+
# @return [String] the backend coordinates to set
|
35
|
+
def get_backend_coordinates()
|
36
|
+
@master.use( Indices::REMOTE_MIRROR_SECTION_NAME )
|
37
|
+
return @master.get( Indices::REMOTE_MIRROR_PAGE_NAME )
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# Set the coordinates (book, chapter and verse) of the verse that holds
|
42
|
+
# the remote backend properties.
|
43
|
+
# @param backend_coordinates [String] the backend coordinates to set
|
44
|
+
def set_backend_coordinates( backend_coordinates )
|
45
|
+
@master.use( Indices::REMOTE_MIRROR_SECTION_NAME )
|
46
|
+
@master.set( Indices::REMOTE_MIRROR_PAGE_NAME, backend_coordinates )
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/utils/keys/key.rb
CHANGED
@@ -478,6 +478,50 @@ module SafeDb
|
|
478
478
|
end
|
479
479
|
|
480
480
|
|
481
|
+
# Return true if this key object can decrypt the parameter ciphertext that
|
482
|
+
# represents a key.
|
483
|
+
#
|
484
|
+
# The parameter cipher text must comprise of an 80 character key and a 16
|
485
|
+
# character random initialization vector (IV). When transformed to a bit string
|
486
|
+
# of ones and zeroes, the bit string length must be <tt>96 * 8 = 768</tt>.
|
487
|
+
#
|
488
|
+
# @param key_iv_ciphertext [String]
|
489
|
+
# Provide the ciphertext produced by our sister key encryption method.
|
490
|
+
# The ciphertext should hold 96 bytes which equates to 128 base64 characters.
|
491
|
+
# The random initialization vector (iv) accounts for the first 16 bytes.
|
492
|
+
# The actual crypt ciphertext then accounts for the final 80 bytes.
|
493
|
+
#
|
494
|
+
# @return [Boolean]
|
495
|
+
# return true if the ciphertext is of the expected length and the
|
496
|
+
# <tt>dry run of the decrypt operation</tt> completes without a
|
497
|
+
# cipher error from {OpenSSL::Cipher::CipherError} being thrown.
|
498
|
+
#
|
499
|
+
def can_decrypt_key( key_iv_ciphertext )
|
500
|
+
|
501
|
+
bit_text = Key64.to_bits( key_iv_ciphertext )
|
502
|
+
ciphertext_size_msg = "Expected bit length of #{EXPECTED_CIPHER_BIT_LENGTH} not #{bit_text.length}."
|
503
|
+
is_expected_length = bit_text.length == EXPECTED_CIPHER_BIT_LENGTH
|
504
|
+
log.warn(x) { ciphertext_size_msg } unless is_expected_length
|
505
|
+
return false unless is_expected_length
|
506
|
+
|
507
|
+
the_cipher = OpenSSL::Cipher::AES256.new(:CBC)
|
508
|
+
the_cipher.decrypt()
|
509
|
+
rawbytes = [ bit_text ].pack("B*")
|
510
|
+
the_cipher.key = to_aes_key()
|
511
|
+
the_cipher.iv = rawbytes[ 0 .. ( RANDOM_IV_BYTE_COUNT - 1 ) ]
|
512
|
+
|
513
|
+
begin
|
514
|
+
the_cipher.update( rawbytes[ RANDOM_IV_BYTE_COUNT .. -1 ] ) + the_cipher.final
|
515
|
+
return true
|
516
|
+
rescue OpenSSL::Cipher::CipherError => e
|
517
|
+
log.warn(x) { "Auth failure decrypting this ciphertext ~~ #{key_iv_ciphertext}" }
|
518
|
+
log.warn(x) { "Auth (maybe login failure) error message is ~~ #{e.message}" }
|
519
|
+
return false
|
520
|
+
end
|
521
|
+
|
522
|
+
end
|
523
|
+
|
524
|
+
|
481
525
|
# Use the {OpenSSL::Cipher::AES256} block cipher in CBC mode and the binary
|
482
526
|
# 256bit representation of this key to encrypt the parameter plaintext using
|
483
527
|
# the parameter random initialization vector.
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
module SafeDb
|
5
|
+
|
6
|
+
# This class creates and represents an Elliptic Curve cryptographic key.
|
7
|
+
# The generated key can then be comsumed via its various aspects like its
|
8
|
+
# ssh formatted public key and/or the pem formatted private key.
|
9
|
+
class Keypair
|
10
|
+
|
11
|
+
# Generate an elliptic curve cryptographic keypair. After the key is
|
12
|
+
# generated, both the public and private keys can be retrieved through
|
13
|
+
# the accessors.
|
14
|
+
#
|
15
|
+
def initialize
|
16
|
+
|
17
|
+
@ec_keypair = OpenSSL::PKey::EC.new( Indices::ELLIPTIC_CURVE_KEY_TYPE )
|
18
|
+
@ec_keypair.generate_key!
|
19
|
+
|
20
|
+
log.info(x) { "An elliptic curve keypair has just been generated." }
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Get the private key aspect of this elliptic curve cryptographic key
|
26
|
+
# in PEM format.
|
27
|
+
# @return [String] the PEM formatted private key
|
28
|
+
def private_key_pem()
|
29
|
+
return @ec_keypair.to_pem()
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# Get the public key aspect of this elliptic curve cryptographic key
|
34
|
+
# in the long line SSH format. This format states the key type which
|
35
|
+
# will be **ecdsa-sha2-nistp384** followed by base64 encoded data.
|
36
|
+
#
|
37
|
+
# The returned one line public key will likely contain forward slashes
|
38
|
+
# and possibly equal signs at the end of the string.
|
39
|
+
#
|
40
|
+
# @return [String] the SSH formatted public key prefixed by the key type
|
41
|
+
def public_key_ssh()
|
42
|
+
require 'net/ssh'
|
43
|
+
key_type = @ec_keypair.ssh_type()
|
44
|
+
key_data = [ @ec_keypair.to_blob ].pack('m0')
|
45
|
+
return "#{key_type} #{key_data}"
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
data/lib/utils/logs/logger.rb
CHANGED
@@ -88,7 +88,7 @@ module LogImpl
|
|
88
88
|
def get_logger
|
89
89
|
|
90
90
|
file_logger = Logger.new @@log_path
|
91
|
-
file_logger.level = Logger::
|
91
|
+
file_logger.level = Logger::DEBUG
|
92
92
|
original_formatter = Logger::Formatter.new
|
93
93
|
|
94
94
|
file_logger.formatter = proc { |severity, datetime, progname, msg|
|
@@ -5,7 +5,7 @@ module SafeDb
|
|
5
5
|
|
6
6
|
require 'json'
|
7
7
|
|
8
|
-
# A Key/Value database knows how to manipulate a JSON
|
8
|
+
# A Key/Value database knows how to manipulate a JSON backend data structure
|
9
9
|
# (put, add etc) <b>after reading and then decrypting it</b> from a
|
10
10
|
# file and <b>before encrypting and then writing it</b> to a file.
|
11
11
|
#
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
module SafeDb
|
5
|
+
|
6
|
+
# The Github class uses the REST API to talk to Github and create, query,
|
7
|
+
# change and delete assets within a specified hosted git repository.
|
8
|
+
class Github
|
9
|
+
|
10
|
+
# Initialize a Github repository given the parameter name.
|
11
|
+
# the parameter JSON string.
|
12
|
+
#
|
13
|
+
# @param repository_name [String] name of the Github repository
|
14
|
+
#
|
15
|
+
def initialize( repository_name )
|
16
|
+
|
17
|
+
data_db = DataStore.new()
|
18
|
+
data_db.merge!( JSON.parse( db_json_string ) )
|
19
|
+
return data_db
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|