Browse Source

Merge branch 'development' of CoBox/cobox-crypto into master

kyphae 2 years ago
parent
commit
67131cd491
5 changed files with 219 additions and 81 deletions
  1. 51
    32
      index.js
  2. 0
    12
      lib/keypair.lua
  3. 2
    1
      package.json
  4. 68
    35
      test/index.test.js
  5. 98
    1
      yarn.lock

+ 51
- 32
index.js View File

@@ -1,16 +1,31 @@
1 1
 const sodium = require('sodium-native')
2 2
 const crypto = require('hypercore-crypto')
3 3
 const assert = require('assert')
4
-
5
-module.exports = () => new Crypto()
4
+const bip39 = require('bip39')
6 5
 
7 6
 class Crypto {
7
+  randomBytes (length) {
8
+    return crypto.randomBytes(length)
9
+  }
10
+
8 11
   masterKey () {
9 12
     const key = sodium.sodium_malloc(sodium.crypto_kdf_KEYBYTES)
10 13
     sodium.crypto_kdf_keygen(key)
11 14
     return key
12 15
   }
13 16
 
17
+  address () {
18
+    return this.randomBytes(sodium.crypto_secretbox_KEYBYTES)
19
+  }
20
+
21
+  encryptionKey (encryptionKey) {
22
+    var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES)
23
+    if (encryptionKey && Buffer.isBuffer(encryptionKey)) key.copy(encryptionKey)
24
+    else if (encryptionKey && typeof encryptionKey === 'string') key.write(encryptionKey)
25
+    else sodium.randombytes_buf(key)
26
+    return key
27
+  }
28
+
14 29
   keyPair (masterKey, id, ctxt = 'cobox') {
15 30
     const context = sodium.sodium_malloc(sodium.crypto_hash_sha256_BYTES)
16 31
     sodium.crypto_hash_sha256(context, Buffer.from(ctxt))
@@ -20,45 +35,37 @@ class Crypto {
20 35
   }
21 36
 
22 37
   keySet () {
23
-    var publicKey = this.randomBytes(sodium.crypto_secretbox_KEYBYTES)
24
-    var symmetricKey = this.symmetricKey()
25
-    var accessKey = this.pack(publicKey, symmetricKey)
26
-    const encryptionKey = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES)
27
-    sodium.crypto_hash_sha256(encryptionKey, accessKey)
28
-    return { publicKey, symmetricKey, encryptionKey }
29
-  }
30
-
31
-  randomBytes (length) {
32
-    return crypto.randomBytes(length)
33
-  }
34
-
35
-  symmetricKey () {
36
-    var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES)
37
-    sodium.randombytes_buf(key)
38
-    return key
38
+    return {
39
+      address: this.address(),
40
+      encryptionKey: this.encryptionKey()
41
+    }
39 42
   }
40 43
 
41 44
   accessKey () {
42
-    return this.pack(this.randomBytes(sodium.crypto_secretbox_KEYBYTES), this.symmetricKey())
45
+    return this.pack(this.randomBytes(sodium.crypto_secretbox_KEYBYTES), this.encryptionKey())
43 46
   }
44 47
 
45
-  pack (pubKey, symKey) {
46
-    pubKey = this.toBuf(pubKey, sodium.crypto_sign_PUBLICKEYBYTES)
47
-    symKey = this.toBuf(symKey, sodium.crypto_secretbox_KEYBYTES)
48
+  pack (address, encryptionKey) {
49
+    address = this.toBuffer(address, sodium.crypto_sign_PUBLICKEYBYTES)
50
+    encryptionKey = this.toBuffer(encryptionKey, sodium.crypto_secretbox_KEYBYTES)
48 51
     const accessKey = sodium.sodium_malloc(sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_secretbox_KEYBYTES)
49
-    pubKey.copy(accessKey)
50
-    symKey.copy(accessKey, sodium.crypto_secretbox_KEYBYTES)
52
+    address.copy(accessKey)
53
+    encryptionKey.copy(accessKey, sodium.crypto_secretbox_KEYBYTES)
51 54
     return accessKey
52 55
   }
53 56
 
54 57
   unpack (key) {
55
-    key = this.toBuf(key, [sodium.crypto_sign_PUBLICKEYBYTES, sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_secretbox_KEYBYTES])
56
-    if (key.length === sodium.crypto_sign_PUBLICKEYBYTES) return { publicKey: key }
57
-    const publicKey = key.slice(0, sodium.crypto_sign_PUBLICKEYBYTES)
58
-    const symmetricKey = key.slice(sodium.crypto_secretbox_KEYBYTES)
59
-    const encryptionKey = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES)
60
-    sodium.crypto_hash_sha256(encryptionKey, key)
61
-    return { publicKey, symmetricKey, encryptionKey }
58
+    key = this.toBuffer(key, [sodium.crypto_sign_PUBLICKEYBYTES, sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_secretbox_KEYBYTES])
59
+
60
+    if (key.length === sodium.crypto_sign_PUBLICKEYBYTES) return { address: key }
61
+
62
+    const address = key.slice(0, sodium.crypto_sign_PUBLICKEYBYTES)
63
+    const encryptionKey = key.slice(sodium.crypto_secretbox_KEYBYTES)
64
+
65
+    return {
66
+      address,
67
+      encryptionKey
68
+    }
62 69
   }
63 70
 
64 71
   isKey (key) {
@@ -68,7 +75,8 @@ class Crypto {
68 75
       length === sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_secretbox_KEYBYTES
69 76
   }
70 77
 
71
-  toBuf (stringOrBuffer, lengths) {
78
+  toBuffer (stringOrBuffer, lengths) {
79
+    if (!lengths) lengths = [sodium.crypto_sign_PUBLICKEYBYTES, sodium.crypto_secretbox_KEYBYTES]
72 80
     if (typeof lengths === 'number') lengths = [lengths]
73 81
     if ((Buffer.isBuffer(stringOrBuffer)) && (lengths.indexOf(stringOrBuffer.length) > -1)) return stringOrBuffer
74 82
     assert(typeof stringOrBuffer === 'string', 'Key is incorrect type')
@@ -77,6 +85,14 @@ class Crypto {
77 85
     return res
78 86
   }
79 87
 
88
+  keyToMnemonic (key) {
89
+    return bip39.entropyToMnemonic(key)
90
+  }
91
+
92
+  mnemonicToKey (mnemonic) {
93
+    return this.toBuffer(bip39.mnemonicToEntropy(mnemonic), [sodium.crypto_secretbox_KEYBYTES])
94
+  }
95
+
80 96
   encoder (encryptionKey, opts = {}) {
81 97
     var can = Buffer.isBuffer(encryptionKey) &&
82 98
       (encryptionKey.length === sodium.crypto_secretbox_KEYBYTES)
@@ -130,3 +146,6 @@ class Crypto {
130 146
     return encoder
131 147
   }
132 148
 }
149
+
150
+module.exports = new Crypto()
151
+

+ 0
- 12
lib/keypair.lua View File

@@ -1,12 +0,0 @@
1
-data = JSON.decode(DATA)
2
-keyring = ECDH.new(data.curve)
3
-keyring:keygen()
4
-assert(ECDH.checkpub(keyring))
5
-
6
-keypair = JSON.encode({
7
-  curve=data.curve,
8
-  public=keyring:public():base64(),
9
-  private=keyring:private():base64()
10
-})
11
-
12
-print(keypair)

+ 2
- 1
package.json View File

@@ -4,7 +4,7 @@
4 4
   "description": "crypto encoding library for use in cobox",
5 5
   "main": "index.js",
6 6
   "repository": "keybase://team/blockades.cobox/cobox-crypto",
7
-  "author": "cobox-cloud-cooperative",
7
+  "author": "magma collective",
8 8
   "license": "AGPL-3",
9 9
   "scripts": {
10 10
     "test": "tape test/**/*.test.js | tap-spec",
@@ -12,6 +12,7 @@
12 12
   },
13 13
   "dependencies": {
14 14
     "assert": "^2.0.0",
15
+    "bip39": "^3.0.2",
15 16
     "hypercore-crypto": "^1.0.0",
16 17
     "sodium-native": "^2.4.2"
17 18
   },

+ 68
- 35
test/index.test.js View File

@@ -3,29 +3,48 @@ const hypercore = require('hypercore')
3 3
 const path = require('path')
4 4
 const fs = require('fs')
5 5
 
6
-const Crypto = require('../')
7
-const crypto = Crypto()
6
+const crypto = require('../')
8 7
 
9 8
 const { cleanup, tmp } = require('./util')
10 9
 
11 10
 describe('key generation', (context) => {
12
-  context('generate an asymmetric keypair', (assert, next) => {
11
+  context('masterKey()', (assert, next) => {
12
+    const masterKey = crypto.masterKey()
13
+    assert.ok(masterKey, 'key generated successfully')
14
+    next()
15
+  })
16
+
17
+  context('keyPair()', (assert, next) => {
13 18
     const masterKey = crypto.masterKey()
14 19
     const keypair = crypto.keyPair(masterKey, 0)
15
-    assert.ok(keypair, 'Keys successfully generated')
16
-    assert.ok(keypair.publicKey instanceof Buffer, 'Public Key is a buffer')
17
-    assert.ok(keypair.secretKey instanceof Buffer, 'Secret Key s a buffer')
20
+    assert.ok(keypair, 'keys successfully generated')
21
+    assert.ok(keypair.publicKey instanceof Buffer, 'public key is a buffer')
22
+    assert.ok(keypair.secretKey instanceof Buffer, 'secret key is a buffer')
23
+    next()
24
+  })
25
+
26
+  context('encryptionKey()', (assert, next) => {
27
+    const key = crypto.encryptionKey()
28
+    assert.ok(key, 'Key successfully generated')
29
+    assert.ok(key instanceof Buffer, 'key is a secure buffer')
30
+    next()
31
+  })
32
+
33
+  context('encryptionKey(string)', (assert, next) => {
34
+    const key = crypto.encryptionKey(crypto.randomBytes(32).toString('hex'))
35
+    assert.ok(key, 'Key successfully generated')
36
+    assert.ok(key instanceof Buffer, 'key is a secure buffer')
18 37
     next()
19 38
   })
20 39
 
21
-  context('generate a symmetric key', (assert, next) => {
22
-    const key = crypto.symmetricKey()
40
+  context('encryptionKey(buffer)', (assert, next) => {
41
+    const key = crypto.encryptionKey(crypto.randomBytes(32))
23 42
     assert.ok(key, 'Key successfully generated')
24
-    assert.ok(key instanceof Buffer, 'Symmetric key is a buffer')
43
+    assert.ok(key instanceof Buffer, 'key is a secure buffer')
25 44
     next()
26 45
   })
27 46
 
28
-  context('generate an access key', (assert, next) => {
47
+  context('accessKey()', (assert, next) => {
29 48
     const accessKey = crypto.accessKey()
30 49
     assert.ok(accessKey, 'Key successfully generated')
31 50
     assert.same(accessKey.length, 64, 'Read key is 64 bytes')
@@ -33,70 +52,84 @@ describe('key generation', (context) => {
33 52
     next()
34 53
   })
35 54
 
36
-  context('pack an access key', (assert, next) => {
37
-    const pubKey = crypto.randomBytes(32)
38
-    const secretKey = crypto.symmetricKey()
55
+  context('pack(buffer, buffer)', (assert, next) => {
56
+    const address = crypto.randomBytes(32)
57
+    const encryptionKey = crypto.encryptionKey()
39 58
 
40
-    const accessKey = crypto.pack(pubKey, secretKey)
59
+    const accessKey = crypto.pack(address, encryptionKey)
41 60
     assert.ok(accessKey, 'Key successfully generated')
42 61
     assert.ok(accessKey instanceof Buffer, 'Access key is a buffer')
43 62
     assert.same(accessKey.length, 64, 'read key is 64 bytes')
44
-    assert.same(accessKey.slice(0, 32), pubKey)
45
-    assert.same(accessKey.slice(32, 64), secretKey)
63
+    assert.same(accessKey.slice(0, 32), address)
64
+    assert.same(accessKey.slice(32, 64), encryptionKey)
46 65
     next()
47 66
   })
48 67
 
49
-  context('pack an access key given as strings', (assert, next) => {
50
-    const pubKey = crypto.randomBytes(32)
51
-    const secretKey = crypto.symmetricKey()
68
+  context('pack(string, string)', (assert, next) => {
69
+    const address = crypto.randomBytes(32)
70
+    const secretKey = crypto.encryptionKey()
52 71
 
53
-    const accessKey = crypto.pack(pubKey.toString('hex'), secretKey.toString('hex'))
72
+    const accessKey = crypto.pack(address.toString('hex'), secretKey.toString('hex'))
54 73
     assert.ok(accessKey, 'Key successfully generated')
55 74
     assert.ok(accessKey instanceof Buffer, 'Access key is a buffer')
56 75
     assert.same(accessKey.length, 64, 'read key is 64 bytes')
57
-    assert.same(accessKey.slice(0, 32), pubKey)
76
+    assert.same(accessKey.slice(0, 32), address)
58 77
     assert.same(accessKey.slice(32, 64), secretKey)
59 78
     next()
60 79
   })
61 80
 
62
-  context('unpack an access key', (assert, next) => {
81
+  context('unpack(buffer)', (assert, next) => {
63 82
     const accessKey = crypto.accessKey()
64 83
 
65 84
     const keys = crypto.unpack(accessKey)
66
-    const pubKey = accessKey.slice(0, 32)
67
-    const symKey = accessKey.slice(32, 64)
85
+    const address = accessKey.slice(0, 32)
86
+    const encryptionKey = accessKey.slice(32, 64)
68 87
 
69
-    assert.same(keys.publicKey, pubKey, 'Unpacks the public key')
70
-    assert.same(keys.symmetricKey, symKey, 'Unpacks the symmetric key')
88
+    assert.same(keys.address, address, 'Unpacks the public key')
89
+    assert.same(keys.encryptionKey, encryptionKey, 'Unpacks the symmetric key')
71 90
     next()
72 91
   })
73 92
 
74
-  context('check a key is a valid key', (assert, next) => {
93
+  context('isKey()', (assert, next) => {
75 94
     const accessKey = crypto.accessKey()
76 95
     assert.ok(crypto.isKey(accessKey), '64 byte buffer is a valid read/write key')
77 96
     assert.ok(crypto.isKey(accessKey.toString('hex')), '64 byte string is a valid read/write key')
97
+
78 98
     const blindKey = crypto.randomBytes(32)
79 99
     assert.ok(crypto.isKey(blindKey), '32 byte public key is a valid blind replication key')
80 100
     assert.ok(crypto.isKey(blindKey.toString('hex')), '32 byte string is a valid blind replication key')
101
+
81 102
     next()
82 103
   })
83 104
 
84
-  context('unpack an access key given as a string', (assert, next) => {
105
+  context('unpack(string)', (assert, next) => {
85 106
     const accessKey = crypto.accessKey()
86 107
 
87 108
     const keys = crypto.unpack(accessKey.toString('hex'))
88
-    const pubKey = accessKey.slice(0, 32)
89
-    const symKey = accessKey.slice(32, 64)
109
+    const address = accessKey.slice(0, 32)
110
+    const encryptionKey = accessKey.slice(32, 64)
111
+
112
+    assert.same(keys.address, address, 'Unpacks the public key')
113
+    assert.same(keys.encryptionKey, encryptionKey, 'Unpacks the symmetric key')
114
+    next()
115
+  })
116
+
117
+  context('mnemnonic', (assert, next) => {
118
+    const encryptionKey = crypto.encryptionKey()
119
+    const words = crypto.keyToMnemonic(encryptionKey)
120
+    assert.ok(words, 'generates a mnemonic')
121
+    assert.ok(words.split(/\s/).length, 24, '24 words long')
122
+
123
+    var check = crypto.mnemonicToKey(words)
124
+    assert.same(encryptionKey, check, 'returns the correct key')
90 125
 
91
-    assert.same(keys.publicKey, pubKey, 'Unpacks the public key')
92
-    assert.same(keys.symmetricKey, symKey, 'Unpacks the symmetric key')
93 126
     next()
94 127
   })
95 128
 })
96 129
 
97 130
 describe('message encoding', (context) => {
98 131
   context('encrypt and decrypt a message', (assert, next) => {
99
-    const key = crypto.symmetricKey()
132
+    const key = crypto.encryptionKey()
100 133
     const encoder = crypto.encoder(key, { valueEncoding: 'utf-8' })
101 134
 
102 135
     const encrypted = encoder.encode("Hello World")
@@ -117,7 +150,7 @@ describe('hypercore', (context) => {
117 150
   })
118 151
 
119 152
   context('encrypted the log', (assert, next) => {
120
-    const key = crypto.symmetricKey()
153
+    const key = crypto.encryptionKey()
121 154
     const encoder = crypto.encoder(key, { valueEncoding: 'utf-8' })
122 155
     const feed = hypercore(storage, { valueEncoding: encoder })
123 156
 
@@ -138,7 +171,7 @@ describe('hypercore', (context) => {
138 171
   })
139 172
 
140 173
   context('encrypted the log, with a json object', (assert, next) => {
141
-    const key = crypto.symmetricKey()
174
+    const key = crypto.encryptionKey()
142 175
     const encoder = crypto.encoder(key, { valueEncoding: 'json' })
143 176
     const feed = hypercore(storage, { valueEncoding: encoder })
144 177
 

+ 98
- 1
yarn.lock View File

@@ -90,6 +90,11 @@
90 90
     lodash "^4.17.13"
91 91
     to-fast-properties "^2.0.0"
92 92
 
93
+"@types/node@11.11.6":
94
+  version "11.11.6"
95
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
96
+  integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
97
+
93 98
 ansi-regex@^2.0.0:
94 99
   version "2.1.1"
95 100
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@@ -156,6 +161,16 @@ balanced-match@^1.0.0:
156 161
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
157 162
   integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
158 163
 
164
+bip39@^3.0.2:
165
+  version "3.0.2"
166
+  resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.2.tgz#2baf42ff3071fc9ddd5103de92e8f80d9257ee32"
167
+  integrity sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==
168
+  dependencies:
169
+    "@types/node" "11.11.6"
170
+    create-hash "^1.1.0"
171
+    pbkdf2 "^3.0.9"
172
+    randombytes "^2.0.1"
173
+
159 174
 bitfield-rle@^2.2.1:
160 175
   version "2.2.1"
161 176
   resolved "https://registry.yarnpkg.com/bitfield-rle/-/bitfield-rle-2.2.1.tgz#07c910f7e650c005c46d18ee5ca6e62c4baf8310"
@@ -259,6 +274,14 @@ chalk@^2.0.0:
259 274
     escape-string-regexp "^1.0.5"
260 275
     supports-color "^5.3.0"
261 276
 
277
+cipher-base@^1.0.1, cipher-base@^1.0.3:
278
+  version "1.0.4"
279
+  resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
280
+  integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
281
+  dependencies:
282
+    inherits "^2.0.1"
283
+    safe-buffer "^5.0.1"
284
+
262 285
 cliui@^5.0.0:
263 286
   version "5.0.0"
264 287
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
@@ -328,6 +351,29 @@ cp-file@^6.2.0:
328 351
     pify "^4.0.1"
329 352
     safe-buffer "^5.0.1"
330 353
 
354
+create-hash@^1.1.0, create-hash@^1.1.2:
355
+  version "1.2.0"
356
+  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
357
+  integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
358
+  dependencies:
359
+    cipher-base "^1.0.1"
360
+    inherits "^2.0.1"
361
+    md5.js "^1.3.4"
362
+    ripemd160 "^2.0.1"
363
+    sha.js "^2.4.0"
364
+
365
+create-hmac@^1.1.4:
366
+  version "1.1.7"
367
+  resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
368
+  integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
369
+  dependencies:
370
+    cipher-base "^1.0.3"
371
+    create-hash "^1.1.0"
372
+    inherits "^2.0.1"
373
+    ripemd160 "^2.0.0"
374
+    safe-buffer "^5.0.1"
375
+    sha.js "^2.4.8"
376
+
331 377
 cross-spawn@^4:
332 378
   version "4.0.2"
333 379
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
@@ -574,6 +620,14 @@ has@^1.0.1, has@^1.0.3, has@~1.0.3:
574 620
   dependencies:
575 621
     function-bind "^1.1.1"
576 622
 
623
+hash-base@^3.0.0:
624
+  version "3.0.4"
625
+  resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
626
+  integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=
627
+  dependencies:
628
+    inherits "^2.0.1"
629
+    safe-buffer "^5.0.1"
630
+
577 631
 hasha@^3.0.0:
578 632
   version "3.0.0"
579 633
   resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39"
@@ -871,6 +925,15 @@ make-dir@^2.0.0, make-dir@^2.1.0:
871 925
     pify "^4.0.1"
872 926
     semver "^5.6.0"
873 927
 
928
+md5.js@^1.3.4:
929
+  version "1.3.5"
930
+  resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
931
+  integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
932
+  dependencies:
933
+    hash-base "^3.0.0"
934
+    inherits "^2.0.1"
935
+    safe-buffer "^5.1.2"
936
+
874 937
 memory-pager@^1.0.2:
875 938
   version "1.5.0"
876 939
   resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5"
@@ -1120,6 +1183,17 @@ path-type@^3.0.0:
1120 1183
   dependencies:
1121 1184
     pify "^3.0.0"
1122 1185
 
1186
+pbkdf2@^3.0.9:
1187
+  version "3.0.17"
1188
+  resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6"
1189
+  integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==
1190
+  dependencies:
1191
+    create-hash "^1.1.2"
1192
+    create-hmac "^1.1.4"
1193
+    ripemd160 "^2.0.1"
1194
+    safe-buffer "^5.0.1"
1195
+    sha.js "^2.4.8"
1196
+
1123 1197
 pify@^3.0.0:
1124 1198
   version "3.0.0"
1125 1199
   resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
@@ -1208,6 +1282,13 @@ random-access-storage@^1.1.1:
1208 1282
   dependencies:
1209 1283
     inherits "^2.0.3"
1210 1284
 
1285
+randombytes@^2.0.1:
1286
+  version "2.1.0"
1287
+  resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
1288
+  integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
1289
+  dependencies:
1290
+    safe-buffer "^5.1.0"
1291
+
1211 1292
 re-emitter@1.1.3:
1212 1293
   version "1.1.3"
1213 1294
   resolved "https://registry.yarnpkg.com/re-emitter/-/re-emitter-1.1.3.tgz#fa9e319ffdeeeb35b27296ef0f3d374dac2f52a7"
@@ -1318,7 +1399,15 @@ rimraf@^2.6.3:
1318 1399
   dependencies:
1319 1400
     glob "^7.1.3"
1320 1401
 
1321
-safe-buffer@^5.0.1, safe-buffer@^5.1.2:
1402
+ripemd160@^2.0.0, ripemd160@^2.0.1:
1403
+  version "2.0.2"
1404
+  resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
1405
+  integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
1406
+  dependencies:
1407
+    hash-base "^3.0.0"
1408
+    inherits "^2.0.1"
1409
+
1410
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2:
1322 1411
   version "5.2.0"
1323 1412
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
1324 1413
   integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
@@ -1343,6 +1432,14 @@ set-blocking@^2.0.0:
1343 1432
   resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
1344 1433
   integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
1345 1434
 
1435
+sha.js@^2.4.0, sha.js@^2.4.8:
1436
+  version "2.4.11"
1437
+  resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
1438
+  integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
1439
+  dependencies:
1440
+    inherits "^2.0.1"
1441
+    safe-buffer "^5.0.1"
1442
+
1346 1443
 signal-exit@^3.0.0, signal-exit@^3.0.2:
1347 1444
   version "3.0.2"
1348 1445
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"