corestore 5.8.0 → 6.0.0-alpha.1

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.
package/lib/keys.js ADDED
@@ -0,0 +1,120 @@
1
+ // TODO: Extract this into a standalone module
2
+ const fs = require('fs').promises
3
+ const p = require('path')
4
+ const os = require('os')
5
+
6
+ const raf = require('random-access-file')
7
+ const sodium = require('sodium-universal')
8
+ const blake2b = require('blake2b-universal')
9
+
10
+ const SYSTEM_PROFILE_STORAGE = p.join(os.homedir(), '.hyperspace', 'profiles')
11
+ const DEFAULT_PROFILE_NAME = 'default'
12
+ const PROFILE_FILENAME = 'profile'
13
+
14
+ const DEFAULT_TOKEN = Buffer.alloc(0)
15
+ const NAMESPACE = Buffer.from('@hyperspace/key-manager')
16
+
17
+ module.exports = class KeyManager {
18
+ constructor (profile, opts = {}) {
19
+ this.profile = profile
20
+ }
21
+
22
+ _sign (keyPair, message) {
23
+ if (!keyPair._secretKey) throw new Error('Invalid key pair')
24
+ const signature = Buffer.allocUnsafe(sodium.crypto_sign_BYTES)
25
+ sodium.crypto_sign_detached(signature, message, keyPair._secretKey)
26
+ return signature
27
+ }
28
+
29
+ createSecret (name, token) {
30
+ return deriveSeed(this.profile, token, name)
31
+ }
32
+
33
+ createHypercoreKeyPair (name, token) {
34
+ const keyPair = {
35
+ publicKey: Buffer.allocUnsafe(sodium.crypto_sign_PUBLICKEYBYTES),
36
+ _secretKey: Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES),
37
+ sign: (msg) => this._sign(keyPair, msg)
38
+ }
39
+
40
+ sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair._secretKey, this.createSecret(name, token))
41
+
42
+ return keyPair
43
+ }
44
+
45
+ static createToken () {
46
+ return randomBytes(32)
47
+ }
48
+
49
+ static async forProfile (name, opts = {}) {
50
+ if (typeof name === 'object') {
51
+ opts = name
52
+ name = null
53
+ }
54
+ const profilePath = p.join(opts.dir || SYSTEM_PROFILE_STORAGE, name || DEFAULT_PROFILE_NAME)
55
+
56
+ let { profile, err } = await fs.readFile(profilePath).then(profile => ({ profile }), err => ({ err }))
57
+ if (err) {
58
+ if (err.code !== 'ENOENT') throw err
59
+ profile = randomBytes(32)
60
+ await fs.mkdir(p.dirname(profilePath), { recursive: true })
61
+ await fs.writeFile(profilePath, profile)
62
+ }
63
+
64
+ return new this(profile, opts)
65
+ }
66
+
67
+ static async fromStorage (storage, opts = {}) {
68
+ if (typeof storage === 'string') {
69
+ const root = storage
70
+ storage = path => raf(p.join(root, path))
71
+ }
72
+ if (typeof storage !== 'object' && typeof storage !== 'function') throw new Error('Storage must be a random-access-storage instance or a Function')
73
+ const profileStorage = typeof storage === 'function' ? storage(opts.name || PROFILE_FILENAME) : storage
74
+
75
+ const profile = await new Promise((resolve, reject) => {
76
+ profileStorage.stat((err, st) => {
77
+ if (err && err.code !== 'ENOENT') return reject(err)
78
+ if (err || st.size < 32 || opts.overwrite) {
79
+ const key = randomBytes(32)
80
+ return profileStorage.write(0, key, err => {
81
+ if (err) return reject(err)
82
+ profileStorage.close(err => {
83
+ if (err) return reject(err)
84
+ return resolve(key)
85
+ })
86
+ })
87
+ }
88
+ profileStorage.read(0, 32, (err, key) => {
89
+ if (err) return reject(err)
90
+ profileStorage.close(err => {
91
+ if (err) return reject(err)
92
+ return resolve(key)
93
+ })
94
+ })
95
+ })
96
+ })
97
+
98
+ return new this(profile, opts)
99
+ }
100
+ }
101
+
102
+ function deriveSeed (profile, token, name, output) {
103
+ if (token && token.length < 32) throw new Error('Token must be a Buffer with length >= 32')
104
+ if (!name || typeof name !== 'string') throw new Error('name must be a String')
105
+ if (!output) output = Buffer.alloc(32)
106
+
107
+ blake2b.batch(output, [
108
+ NAMESPACE,
109
+ token || DEFAULT_TOKEN,
110
+ Buffer.from(Buffer.byteLength(name, 'ascii') + '\n' + name, 'ascii')
111
+ ], profile)
112
+
113
+ return output
114
+ }
115
+
116
+ function randomBytes (n) {
117
+ const buf = Buffer.allocUnsafe(n)
118
+ sodium.randombytes_buf(buf)
119
+ return buf
120
+ }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "corestore",
3
- "version": "5.8.0",
4
- "description": "A Hypercore factory that stores and replicates linked cores.",
3
+ "version": "6.0.0-alpha.1",
4
+ "description": "A Hypercore factory that simplifies managing collections of cores.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "standard && tape test/*.js"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/andrewosh/corestore.git"
11
+ "url": "git+https://github.com/hypercore-protocol/corestore.git"
12
12
  },
13
13
  "keywords": [
14
14
  "corestore"
@@ -16,25 +16,21 @@
16
16
  "author": "Andrew Osheroff <andrewosh@gmail.com>",
17
17
  "license": "MIT",
18
18
  "bugs": {
19
- "url": "https://github.com/andrewosh/corestore/issues"
19
+ "url": "https://github.com/hypercore-protocol/corestore/issues"
20
20
  },
21
- "homepage": "https://github.com/andrewosh/corestore#readme",
21
+ "homepage": "https://github.com/hypercore-protocol/corestore#readme",
22
22
  "devDependencies": {
23
- "random-access-file": "^2.1.4",
24
- "random-access-memory": "^3.1.1",
25
- "standard": "^12.0.1",
26
- "tape": "^4.10.1"
23
+ "random-access-memory": "^3.1.2",
24
+ "standardx": "^7.0.0",
25
+ "tape": "^5.3.1",
26
+ "tmp-promise": "^3.0.2"
27
27
  },
28
28
  "dependencies": {
29
- "call-me-maybe": "^1.0.1",
30
- "dat-encoding": "^5.0.1",
31
- "derive-key": "^1.0.0",
32
- "derived-key-storage": "^2.1.0",
33
- "fd-lock": "^1.0.2",
34
- "hypercore": "^9.0.0",
35
- "hypercore-crypto": "^2.0.0",
36
- "hypercore-protocol": "^8.0.0",
37
- "nanoresource": "^1.3.0",
38
- "refpool": "^1.2.0"
29
+ "blake2b-universal": "^1.0.1",
30
+ "derive-key": "^1.0.1",
31
+ "hypercore": "next",
32
+ "hypercore-crypto": "^2.3.0",
33
+ "random-access-file": "^2.2.0",
34
+ "sodium-universal": "^3.0.4"
39
35
  }
40
36
  }