Browse Source

passes up deriveKeyPair fn instead of raw master_key

Kieran Gibb 2 years ago
parent
commit
cd8a61ac2f
No known key found for this signature in database
4 changed files with 76 additions and 32 deletions
  1. 6
    8
      index.js
  2. 27
    0
      lib/keys.js
  3. 3
    1
      package.json
  4. 40
    23
      test/index.test.js

+ 6
- 8
index.js View File

@@ -6,6 +6,7 @@ const mkdirp = require('mkdirp')
6 6
 const logger = require('./logger')
7 7
 const crypto = require('cobox-crypto')
8 8
 const constants = require('cobox-constants')
9
+const { loadParentKey, saveParentKey } = require('./lib/keys')
9 10
 
10 11
 const CONFIG_FILE = 'config.yml'
11 12
 const IDENTITY_SUBKEY_ID = 0
@@ -44,15 +45,12 @@ class CoBoxConfig {
44 45
       this.load()
45 46
     }
46 47
 
47
-    var masterKeyPath = path.join(this.root, 'master_key')
48
-    if (!fs.existsSync(masterKeyPath)) {
49
-      this.masterKey = crypto.masterKey()
50
-      fs.writeFileSync(masterKeyPath, this.masterKey, { mode: fs.constants.S_IRUSR })
51
-    } else {
52
-      this.masterKey = fs.readFileSync(masterKeyPath)
53
-    }
48
+    var parentKey = loadParentKey(this.root) || crypto.masterKey()
49
+    saveParentKey(this.root, parentKey)
50
+
51
+    this.deriveKeyPair = crypto.keyPair.bind(null, parentKey)
52
+    this.identity = crypto.keyPair(parentKey, IDENTITY_SUBKEY_ID)
54 53
 
55
-    this.identity = crypto.keyPair(this.masterKey, IDENTITY_SUBKEY_ID)
56 54
     this.logger = logger(path.join(this.root, 'logs', logfile))
57 55
     this.log = this.logger('cobox-config')
58 56
     this.groups = KeyHandler(this._groups)

+ 27
- 0
lib/keys.js View File

@@ -0,0 +1,27 @@
1
+const mkdirp = require('mkdirp')
2
+const fs = require('fs')
3
+const path = require('path')
4
+const assert = require('assert')
5
+
6
+function saveParentKey (storage, encryptionKey) {
7
+  var keyPath = path.join(storage, 'parent_key')
8
+  if (!fs.existsSync(keyPath)) {
9
+    mkdirp.sync(path.dirname(keyPath))
10
+    fs.writeFileSync(keyPath, encryptionKey, {
11
+      mode: fs.constants.S_IRUSR
12
+    })
13
+  }
14
+
15
+  assert(fs.existsSync(keyPath), 'failed to store parent_key')
16
+}
17
+
18
+function loadParentKey (storage) {
19
+  try { return fs.readFileSync(path.join(storage, 'parent_key')) }
20
+  catch (err) { return }
21
+}
22
+
23
+module.exports = {
24
+  loadParentKey,
25
+  saveParentKey
26
+}
27
+

+ 3
- 1
package.json View File

@@ -7,13 +7,15 @@
7 7
     "test": "test"
8 8
   },
9 9
   "dependencies": {
10
-    "cobox-crypto": "^1.2.0",
11 10
     "cobox-constants": "^1.0.1",
11
+    "cobox-crypto": "^1.2.0",
12 12
     "debug": "^4.1.1",
13 13
     "js-yaml": "^3.13.1",
14 14
     "mkdirp": "^0.5.1",
15 15
     "os": "^0.1.1",
16 16
     "pino": "^5.13.2",
17
+    "proxyquire": "^2.1.3",
18
+    "sinon": "^8.1.1",
17 19
     "urlsafe-base64": "^1.0.0"
18 20
   },
19 21
   "devDependencies": {

+ 40
- 23
test/index.test.js View File

@@ -4,6 +4,9 @@ const crypto = require('cobox-crypto')
4 4
 const fs = require('fs')
5 5
 const path = require('path')
6 6
 const yaml = require('js-yaml')
7
+const sinon = require('sinon')
8
+const proxyquire = require('proxyquire')
9
+const mkdirp = require('mkdirp')
7 10
 
8 11
 const { tmp, cleanup } = require('./util')
9 12
 
@@ -18,41 +21,55 @@ describe('load', (context) => {
18 21
   context('default', (assert, next) => {
19 22
     var storage = tmp()
20 23
     var config = Config(storage)
21
-    assert.ok(config.groups.list() instanceof Array, 'groups list defaults to empty Array')
22
-    assert.ok(config.replicators.list() instanceof Array, 'replicators list defaults to empty Array')
23
-    next()
24
+    assert.ok(config.groups instanceof KeyHandler, 'groups uses KeyHandler')
25
+    assert.ok(config.replicators instanceof KeyHandler, 'replicators uses KeyHandler')
26
+    assert.ok(config.devices instanceof KeyHandler, 'devices uses KeyHandler')
24 27
     cleanup(storage, next)
25 28
   })
26 29
 })
27 30
 
28
-describe('master_key', (context) => {
29
-  context('default', (assert, next) => {
31
+describe('parent_key', (context) => {
32
+  context('constructor() - generates and saves new parent_key', (assert, next) => {
30 33
     var storage = tmp()
31
-    var config = Config(storage)
34
+    var spy = sinon.spy(crypto)
35
+    var saveStub = sinon.stub().returns(true)
32 36
 
33
-    var masterKey = config.masterKey
34
-    assert.ok(masterKey, 'generates a master key')
37
+    var ProxyConfig = proxyquire('../', {
38
+      'cobox-crypto': spy,
39
+      './lib/keys': { saveParentKey: saveStub }
40
+    })
35 41
 
36
-    fs.readFile(path.join(storage, 'master_key'), (err, data) => {
37
-      assert.same(Buffer.from(data).toString('hex'), masterKey.toString('hex'), 'keys match')
42
+    var config = ProxyConfig(storage)
38 43
 
39
-      fs.writeFile(path.join(storage, 'master_key'), 'Woof Woof', (err) => {
40
-        assert.ok(err, 'throws an error')
41
-        assert.ok(err.code, 'EACCES', 'invalid permissions')
42
-        assert.ok(err.message, `permission denied, open '${storage}'`)
44
+    assert.ok(config, 'config created')
45
+    assert.ok(spy.masterKey.calledOnce, 'calls crypto.masterKey()')
46
+    assert.ok(saveStub.calledOnce, 'saves parent key')
43 47
 
44
-        cleanup(storage, next)
45
-      })
46
-    })
48
+    cleanup(storage, next)
47 49
   })
48 50
 
49
-  context('reload', (assert, next) => {
51
+  context('constructor() - loads parent_key from path', (assert, next) => {
50 52
     var storage = tmp()
51
-    var config = Config(storage)
52
-    var masterKey = config.masterKey
53
-    config = Config(storage)
54
-    var key = config.masterKey
55
-    assert.same(key, masterKey, 'reloads the same master_key')
53
+    var address = crypto.address()
54
+    var parentKey = crypto.masterKey()
55
+
56
+    var keyPath = path.join(storage, 'parent_key')
57
+    mkdirp.sync(path.dirname(keyPath))
58
+    fs.writeFileSync(keyPath, parentKey, { mode: fs.constants.S_IRUSR })
59
+
60
+    var loadStub = sinon.stub().returns(parentKey)
61
+    var saveStub = sinon.stub().returns(true)
62
+
63
+    var ProxyConfig = proxyquire('../', { './lib/keys': {
64
+      loadParentKey: loadStub,
65
+      saveParentKey: saveStub
66
+    }
67
+    })
68
+
69
+    var group = ProxyConfig(storage, address)
70
+
71
+    assert.ok(loadStub.calledWith(storage), 'key is loaded')
72
+    assert.ok(saveStub.calledWith(storage, parentKey), 'key is saved')
56 73
     cleanup(storage, next)
57 74
   })
58 75
 })