hypercore 10.31.12 → 10.32.0
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/index.js +15 -4
- package/lib/batch.js +2 -2
- package/lib/core.js +87 -41
- package/lib/merkle-tree.js +27 -2
- package/lib/messages.js +139 -55
- package/lib/multisig.js +46 -45
- package/lib/replicator.js +13 -0
- package/lib/verifier.js +272 -0
- package/package.json +2 -1
- package/lib/manifest.js +0 -222
package/lib/verifier.js
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
const defaultCrypto = require('hypercore-crypto')
|
|
2
|
+
const b4a = require('b4a')
|
|
3
|
+
const c = require('compact-encoding')
|
|
4
|
+
const flat = require('flat-tree')
|
|
5
|
+
const { BAD_ARGUMENT } = require('hypercore-errors')
|
|
6
|
+
|
|
7
|
+
const m = require('./messages')
|
|
8
|
+
const multisig = require('./multisig')
|
|
9
|
+
const caps = require('./caps')
|
|
10
|
+
|
|
11
|
+
class Signer {
|
|
12
|
+
constructor (crypto, index, { signature = 'ed25519', publicKey, namespace = caps.DEFAULT_NAMESPACE } = {}) {
|
|
13
|
+
if (!publicKey) throw BAD_ARGUMENT('public key is required for a signer')
|
|
14
|
+
if (signature !== 'ed25519') throw BAD_ARGUMENT('Only Ed25519 signatures are supported')
|
|
15
|
+
|
|
16
|
+
this.crypto = crypto
|
|
17
|
+
this.signer = index
|
|
18
|
+
this.signature = signature
|
|
19
|
+
this.publicKey = publicKey
|
|
20
|
+
this.namespace = namespace
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
verify (batch, signature) {
|
|
24
|
+
return this.crypto.verify(batch.signable(this.namespace), signature, this.publicKey)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
sign (batch, keyPair) {
|
|
28
|
+
return this.crypto.sign(batch.signable(this.namespace), keyPair.secretKey)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class CompatSigner extends Signer {
|
|
33
|
+
constructor (crypto, index, signer, legacy) {
|
|
34
|
+
super(crypto, index, signer)
|
|
35
|
+
this.legacy = legacy
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
verify (batch, signature) {
|
|
39
|
+
return this.crypto.verify(batch.signableCompat(this.legacy), signature, this.publicKey)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
sign (batch, keyPair) {
|
|
43
|
+
return this.crypto.sign(batch.signableCompat(this.legacy), keyPair.secretKey)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = class Verifier {
|
|
48
|
+
constructor (manifest, { compat = false, crypto = defaultCrypto, legacy = false } = {}) {
|
|
49
|
+
this.compat = compat || manifest === null
|
|
50
|
+
this.manifest = manifest
|
|
51
|
+
this.version = this.compat ? 0 : typeof this.manifest.version === 'number' ? this.manifest.version : 1
|
|
52
|
+
this.hash = manifest.hash || 'blake2b'
|
|
53
|
+
this.allowPatch = !this.compat && !!this.manifest.allowPatch
|
|
54
|
+
this.quorum = this.compat ? 1 : (this.manifest.quorum || 0)
|
|
55
|
+
this.signers = this.manifest.signers.map((s, index) => this.compat ? new CompatSigner(crypto, index, s, legacy) : new Signer(crypto, index, s))
|
|
56
|
+
this.prologue = this.compat ? null : (this.manifest.prologue || null)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_verifyCompat (batch, signature) {
|
|
60
|
+
if (!signature) return false
|
|
61
|
+
|
|
62
|
+
if (this.compat || (!this.allowPatch && this.signers.length === 1)) {
|
|
63
|
+
return !!signature && this.signers[0].verify(batch, signature)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return this._verifyMulti(batch, signature)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_inflate (signature) {
|
|
70
|
+
if (this.version >= 1) return multisig.inflate(signature)
|
|
71
|
+
const { proofs, patch } = multisig.inflatev0(signature)
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
proofs: proofs.map(proofToVersion1),
|
|
75
|
+
patch: patch
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_verifyMulti (batch, signature) {
|
|
80
|
+
if (!signature || this.quorum === 0) return false
|
|
81
|
+
|
|
82
|
+
const { proofs, patch } = this._inflate(signature)
|
|
83
|
+
if (proofs.length < this.quorum) return false
|
|
84
|
+
|
|
85
|
+
const tried = new Uint8Array(this.signers.length)
|
|
86
|
+
const nodes = this.allowPatch && patch.length ? toMap(patch) : null
|
|
87
|
+
|
|
88
|
+
for (let i = 0; i < this.quorum; i++) {
|
|
89
|
+
const inp = proofs[i]
|
|
90
|
+
|
|
91
|
+
let tree = batch
|
|
92
|
+
|
|
93
|
+
if (inp.patch && this.allowPatch) {
|
|
94
|
+
tree = batch.clone()
|
|
95
|
+
|
|
96
|
+
const upgrade = generateUpgrade(nodes, batch.length, inp.patch)
|
|
97
|
+
const proof = { fork: tree.fork, block: null, hash: null, seek: null, upgrade, manifest: null }
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
if (!tree.verifyUpgrade(proof)) return false
|
|
101
|
+
} catch {
|
|
102
|
+
return false
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (inp.signer >= this.signers.length || tried[inp.signer]) return false
|
|
107
|
+
tried[inp.signer] = 1
|
|
108
|
+
|
|
109
|
+
const s = this.signers[inp.signer]
|
|
110
|
+
if (!s.verify(tree, inp.signature)) return false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return true
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
verify (batch, signature) {
|
|
117
|
+
if (this.version !== 1) {
|
|
118
|
+
return this._verifyCompat(batch, signature)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (this.prologue !== null && batch.length <= this.prologue.length) {
|
|
122
|
+
return batch.length === this.prologue.length && b4a.equals(batch.hash(), this.prologue.hash)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return this._verifyMulti(batch, signature)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// TODO: better api for this that is more ... multisig-ey
|
|
129
|
+
sign (batch, keyPair) {
|
|
130
|
+
if (!keyPair || !keyPair.secretKey) throw BAD_ARGUMENT('No key pair was passed')
|
|
131
|
+
if (this.signers.length > 1 || this.allowPatch) throw BAD_ARGUMENT('Can only sign directly for single signers')
|
|
132
|
+
|
|
133
|
+
const signature = this.signers[0].sign(batch, keyPair)
|
|
134
|
+
if (this.version !== 1) return signature
|
|
135
|
+
return this.assemble([{ signer: 0, signature, patch: 0, nodes: null }])
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
assemble (inputs) {
|
|
139
|
+
return this.version === 0 ? multisig.assemblev0(inputs) : multisig.assemble(inputs)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
manifestHash () {
|
|
143
|
+
return manifestHash(this)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
static manifestHash (manifest) {
|
|
147
|
+
return manifestHash(manifest)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
static defaultSignerManifest (publicKey) {
|
|
151
|
+
return {
|
|
152
|
+
version: 1,
|
|
153
|
+
hash: 'blake2b',
|
|
154
|
+
allowPatch: false,
|
|
155
|
+
quorum: 1,
|
|
156
|
+
signers: [{
|
|
157
|
+
signature: 'ed25519',
|
|
158
|
+
namespace: caps.DEFAULT_NAMESPACE,
|
|
159
|
+
publicKey
|
|
160
|
+
}],
|
|
161
|
+
prologue: null
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static createManifest (inp) {
|
|
166
|
+
if (!inp) return null
|
|
167
|
+
|
|
168
|
+
const manifest = {
|
|
169
|
+
version: typeof inp.version === 'number' ? inp.version : 1,
|
|
170
|
+
hash: 'blake2b',
|
|
171
|
+
allowPatch: !!inp.allowPatch,
|
|
172
|
+
quorum: inp.quorum || 0,
|
|
173
|
+
signers: inp.signers.map(parseSigner),
|
|
174
|
+
prologue: null
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (inp.hash && inp.hash !== 'blake2b') throw BAD_ARGUMENT('Only Blake2b hashes are supported')
|
|
178
|
+
|
|
179
|
+
if (inp.prologue) {
|
|
180
|
+
if (!(b4a.isBuffer(inp.prologue.hash) && inp.prologue.hash.byteLength === 32) || !inp.prologue.length) {
|
|
181
|
+
throw BAD_ARGUMENT('Invalid prologue')
|
|
182
|
+
}
|
|
183
|
+
manifest.prologue = inp.prologue
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return manifest
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static isValidManifest (key, manifest) {
|
|
190
|
+
return b4a.equals(key, manifestHash(manifest))
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
static isCompat (key, manifest) {
|
|
194
|
+
return !!(manifest && manifest.signers.length === 1 && b4a.equals(key, manifest.signers[0].publicKey))
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
static sign (manifest, batch, keyPair, opts) {
|
|
198
|
+
const v = new Verifier(manifest, opts)
|
|
199
|
+
return v.sign(batch, keyPair)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function toMap (nodes) {
|
|
204
|
+
const m = new Map()
|
|
205
|
+
for (const node of nodes) m.set(node.index, node)
|
|
206
|
+
return m
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function generateUpgrade (patch, start, length) {
|
|
210
|
+
const upgrade = { start, length, nodes: null, additionalNodes: [] }
|
|
211
|
+
|
|
212
|
+
const from = start * 2
|
|
213
|
+
const to = from + length * 2
|
|
214
|
+
|
|
215
|
+
for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
|
|
216
|
+
if (ite.index + ite.factor / 2 < from) continue
|
|
217
|
+
|
|
218
|
+
if (upgrade.nodes === null && ite.contains(from - 2)) {
|
|
219
|
+
upgrade.nodes = []
|
|
220
|
+
|
|
221
|
+
const root = ite.index
|
|
222
|
+
const target = from - 2
|
|
223
|
+
|
|
224
|
+
ite.seek(target)
|
|
225
|
+
|
|
226
|
+
while (ite.index !== root) {
|
|
227
|
+
ite.sibling()
|
|
228
|
+
if (ite.index > target) upgrade.nodes.push(patch.get(ite.index))
|
|
229
|
+
ite.parent()
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
continue
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (upgrade.nodes === null) upgrade.nodes = []
|
|
236
|
+
upgrade.nodes.push(patch.get(ite.index))
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (upgrade.nodes === null) upgrade.nodes = []
|
|
240
|
+
return upgrade
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function parseSigner (signer) {
|
|
244
|
+
validateSigner(signer)
|
|
245
|
+
return {
|
|
246
|
+
signature: 'ed25519',
|
|
247
|
+
namespace: signer.namespace || caps.DEFAULT_NAMESPACE,
|
|
248
|
+
publicKey: signer.publicKey
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function validateSigner (signer) {
|
|
253
|
+
if (!signer || !signer.publicKey) throw BAD_ARGUMENT('Signer missing public key')
|
|
254
|
+
if (signer.signature && signer.signature !== 'ed25519') throw BAD_ARGUMENT('Only Ed25519 signatures are supported')
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function manifestHash (manifest) {
|
|
258
|
+
const state = { start: 0, end: 32, buffer: null }
|
|
259
|
+
m.manifest.preencode(state, manifest)
|
|
260
|
+
state.buffer = b4a.allocUnsafe(state.end)
|
|
261
|
+
c.raw.encode(state, caps.MANIFEST)
|
|
262
|
+
m.manifest.encode(state, manifest)
|
|
263
|
+
return defaultCrypto.hash(state.buffer)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function proofToVersion1 (proof) {
|
|
267
|
+
return {
|
|
268
|
+
signer: proof.signer,
|
|
269
|
+
signature: proof.signature,
|
|
270
|
+
patch: proof.patch ? proof.patch.length : 0
|
|
271
|
+
}
|
|
272
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.32.0",
|
|
4
4
|
"description": "Hypercore is a secure, distributed append-only log",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"hypercore-crypto": "^3.2.1",
|
|
47
47
|
"hypercore-errors": "^1.1.0",
|
|
48
48
|
"hypercore-id-encoding": "^1.2.0",
|
|
49
|
+
"hypertrace": "^1.2.1",
|
|
49
50
|
"is-options": "^1.0.1",
|
|
50
51
|
"protomux": "^3.5.0",
|
|
51
52
|
"quickbit-universal": "^2.2.0",
|
package/lib/manifest.js
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
const defaultCrypto = require('hypercore-crypto')
|
|
2
|
-
const b4a = require('b4a')
|
|
3
|
-
const c = require('compact-encoding')
|
|
4
|
-
const { BAD_ARGUMENT } = require('hypercore-errors')
|
|
5
|
-
|
|
6
|
-
const m = require('./messages')
|
|
7
|
-
const multisig = require('./multisig')
|
|
8
|
-
const caps = require('./caps')
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
manifestHash,
|
|
12
|
-
isCompat,
|
|
13
|
-
defaultSignerManifest,
|
|
14
|
-
createManifest,
|
|
15
|
-
createVerifier
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
class StaticVerifier {
|
|
19
|
-
constructor (treeHash) {
|
|
20
|
-
this.treeHash = treeHash
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
sign () {
|
|
24
|
-
return null
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
verify (batch, signature) {
|
|
28
|
-
return b4a.equals(batch.hash(), this.treeHash)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
class CompatVerifier {
|
|
33
|
-
constructor (crypto, signer, legacy) {
|
|
34
|
-
validateSigner(signer)
|
|
35
|
-
|
|
36
|
-
this.legacy = legacy
|
|
37
|
-
this.crypto = crypto
|
|
38
|
-
this.publicKey = signer.publicKey
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
sign (batch, keyPair) {
|
|
42
|
-
if (!keyPair || !keyPair.secretKey) throw BAD_ARGUMENT('No signer was passed')
|
|
43
|
-
return this.crypto.sign(batch.signableCompat(this.legacy), keyPair.secretKey)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
verify (batch, signature) {
|
|
47
|
-
if (!signature) return false
|
|
48
|
-
return this.crypto.verify(batch.signableCompat(this.legacy), signature, this.publicKey)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
class SingleVerifier {
|
|
53
|
-
constructor (crypto, signer) {
|
|
54
|
-
validateSigner(signer)
|
|
55
|
-
|
|
56
|
-
this.crypto = crypto
|
|
57
|
-
this.publicKey = signer.publicKey
|
|
58
|
-
this.namespace = signer.namespace
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
sign (batch, keyPair) {
|
|
62
|
-
if (!keyPair || !keyPair.secretKey) throw BAD_ARGUMENT('No signer was passed')
|
|
63
|
-
return this.crypto.sign(batch.signable(this.namespace), keyPair.secretKey)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
verify (batch, signature) {
|
|
67
|
-
if (!signature) return false
|
|
68
|
-
return this.crypto.verify(batch.signable(this.namespace), signature, this.publicKey)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
class MultiVerifier {
|
|
73
|
-
constructor (crypto, multipleSigners) {
|
|
74
|
-
this.signers = multipleSigners.signers
|
|
75
|
-
this.quorum = multipleSigners.quorum
|
|
76
|
-
this.allowPatched = multipleSigners.allowPatched
|
|
77
|
-
this.verifiers = this.signers.map(s => new SingleVerifier(crypto, s))
|
|
78
|
-
|
|
79
|
-
if (this.verifiers.length < this.quorum || (this.quorum === 0)) throw BAD_ARGUMENT('Invalid quorum')
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
sign () {
|
|
83
|
-
throw BAD_ARGUMENT('Multi signature must be provided')
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
verify (batch, signature) {
|
|
87
|
-
if (!signature) return false
|
|
88
|
-
|
|
89
|
-
const inputs = multisig.inflate(signature)
|
|
90
|
-
|
|
91
|
-
if (inputs.length < this.quorum) return false
|
|
92
|
-
|
|
93
|
-
const tried = new Uint8Array(this.verifiers.length)
|
|
94
|
-
|
|
95
|
-
for (let i = 0; i < this.quorum; i++) {
|
|
96
|
-
const inp = inputs[i]
|
|
97
|
-
|
|
98
|
-
let tree = batch
|
|
99
|
-
|
|
100
|
-
if (inp.patch) {
|
|
101
|
-
if (!this.allowPatched) return false
|
|
102
|
-
|
|
103
|
-
tree = batch.clone()
|
|
104
|
-
const proof = { fork: tree.fork, block: null, hash: null, seek: null, upgrade: inp.patch, manifest: null }
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
if (!tree.verifyUpgrade(proof)) return false
|
|
108
|
-
} catch {
|
|
109
|
-
return false
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (inp.signer >= this.verifiers.length || tried[inp.signer]) return false
|
|
114
|
-
tried[inp.signer] = 1
|
|
115
|
-
|
|
116
|
-
if (!this.verifiers[inp.signer].verify(tree, inp.signature)) return false
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return true
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function createVerifier (manifest, { compat = false, crypto = defaultCrypto, legacy = false } = {}) {
|
|
124
|
-
if (compat && manifest.signer) {
|
|
125
|
-
return new CompatVerifier(crypto, manifest.signer, legacy)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (manifest.static) {
|
|
129
|
-
return new StaticVerifier(manifest.static)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (manifest.signer) {
|
|
133
|
-
return new SingleVerifier(crypto, manifest.signer)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (manifest.multipleSigners) {
|
|
137
|
-
return new MultiVerifier(crypto, manifest.multipleSigners)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
throw BAD_ARGUMENT('No signer was provided')
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function createManifest (inp) {
|
|
144
|
-
if (!inp) return null
|
|
145
|
-
|
|
146
|
-
const manifest = {
|
|
147
|
-
hash: 'blake2b',
|
|
148
|
-
static: null,
|
|
149
|
-
signer: null,
|
|
150
|
-
multipleSigners: null
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (inp.hash && inp.hash !== 'blake2b') throw BAD_ARGUMENT('Only Blake2b hashes are supported')
|
|
154
|
-
|
|
155
|
-
if (inp.static) {
|
|
156
|
-
if (!(b4a.isBuffer(inp.static) && inp.static.byteLength === 32)) throw BAD_ARGUMENT('Invalid static manifest')
|
|
157
|
-
manifest.static = inp.static
|
|
158
|
-
return manifest
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (inp.signer) {
|
|
162
|
-
manifest.signer = parseSigner(inp.signer)
|
|
163
|
-
return manifest
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (inp.multipleSigners) {
|
|
167
|
-
manifest.multipleSigners = parseMultipleSigners(inp.multipleSigners)
|
|
168
|
-
return manifest
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
throw BAD_ARGUMENT('No signer was provided')
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function parseMultipleSigners (m) {
|
|
175
|
-
if (m.signers.length < m.quorum || !(m.quorum > 0)) throw BAD_ARGUMENT('Invalid quorum')
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
allowPatched: !!m.allowPatched,
|
|
179
|
-
quorum: m.quorum,
|
|
180
|
-
signers: m.signers.map(parseSigner)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function parseSigner (signer) {
|
|
185
|
-
validateSigner(signer)
|
|
186
|
-
return {
|
|
187
|
-
signature: 'ed25519',
|
|
188
|
-
namespace: signer.namespace || caps.DEFAULT_NAMESPACE,
|
|
189
|
-
publicKey: signer.publicKey
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function validateSigner (signer) {
|
|
194
|
-
if (!signer || !signer.publicKey) throw BAD_ARGUMENT('Signer missing public key')
|
|
195
|
-
if (signer.signature && signer.signature !== 'ed25519') throw BAD_ARGUMENT('Only Ed25519 signatures are supported')
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function defaultSignerManifest (publicKey) {
|
|
199
|
-
return {
|
|
200
|
-
hash: 'blake2b',
|
|
201
|
-
static: null,
|
|
202
|
-
signer: {
|
|
203
|
-
signature: 'ed25519',
|
|
204
|
-
namespace: caps.DEFAULT_NAMESPACE,
|
|
205
|
-
publicKey
|
|
206
|
-
},
|
|
207
|
-
multipleSigners: null
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function manifestHash (manifest) {
|
|
212
|
-
const state = { start: 0, end: 32, buffer: null }
|
|
213
|
-
m.manifest.preencode(state, manifest)
|
|
214
|
-
state.buffer = b4a.allocUnsafe(state.end)
|
|
215
|
-
c.raw.encode(state, caps.MANIFEST)
|
|
216
|
-
m.manifest.encode(state, manifest)
|
|
217
|
-
return defaultCrypto.hash(state.buffer)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function isCompat (key, manifest) {
|
|
221
|
-
return !!(manifest && manifest.signer && b4a.equals(key, manifest.signer.publicKey))
|
|
222
|
-
}
|