hypercore 10.0.0-alpha.6 → 10.0.0-alpha.7
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/README.md +10 -1
- package/index.js +80 -21
- package/lib/block-encryption.js +67 -0
- package/lib/core.js +3 -1
- package/lib/merkle-tree.js +20 -13
- package/package.json +4 -3
- package/test/encryption.js +85 -0
package/README.md
CHANGED
|
@@ -63,7 +63,8 @@ Note that `tree`, `data`, and `bitfield` are normally heavily sparse files.
|
|
|
63
63
|
createIfMissing: true, // create a new Hypercore key pair if none was present in storage
|
|
64
64
|
overwrite: false, // overwrite any old Hypercore that might already exist
|
|
65
65
|
valueEncoding: 'json' | 'utf-8' | 'binary', // defaults to binary
|
|
66
|
-
keyPair: kp // optionally pass the public key and secret key as a key pair
|
|
66
|
+
keyPair: kp, // optionally pass the public key and secret key as a key pair
|
|
67
|
+
encryptionKey: k // optionally pass an encryption key to enable block encryption
|
|
67
68
|
}
|
|
68
69
|
```
|
|
69
70
|
|
|
@@ -202,6 +203,10 @@ In contrast to `core.key` this key does not allow you to verify the data but can
|
|
|
202
203
|
|
|
203
204
|
Populated after `ready` has been emitted. Will be `null` before the event.
|
|
204
205
|
|
|
206
|
+
#### `core.encryptionKey`
|
|
207
|
+
|
|
208
|
+
Buffer containing the optional block encryption key of this core. Will be `null` unless block encryption is enabled.
|
|
209
|
+
|
|
205
210
|
#### `core.length`
|
|
206
211
|
|
|
207
212
|
How many blocks of data are available on this core?
|
|
@@ -220,6 +225,10 @@ What is the current fork id of this core?
|
|
|
220
225
|
|
|
221
226
|
Populated after `ready` has been emitted. Will be `0` before the event.
|
|
222
227
|
|
|
228
|
+
#### `core.padding`
|
|
229
|
+
|
|
230
|
+
How much padding is applied to each block of this core? Will be `0` unless block encryption is enabled.
|
|
231
|
+
|
|
223
232
|
#### `const stream = core.replicate(isInitiatorOrReplicationStream)`
|
|
224
233
|
|
|
225
234
|
Create a replication stream. You should pipe this to another Hypercore instance.
|
package/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const fsctl = requireMaybe('fsctl') || { lock: noop, sparse: noop }
|
|
|
12
12
|
const Replicator = require('./lib/replicator')
|
|
13
13
|
const Extensions = require('./lib/extensions')
|
|
14
14
|
const Core = require('./lib/core')
|
|
15
|
+
const BlockEncryption = require('./lib/block-encryption')
|
|
15
16
|
|
|
16
17
|
const promises = Symbol.for('hypercore.promises')
|
|
17
18
|
const inspect = Symbol.for('nodejs.util.inspect.custom')
|
|
@@ -49,6 +50,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
49
50
|
this.replicator = null
|
|
50
51
|
this.extensions = opts.extensions || new Extensions()
|
|
51
52
|
this.cache = opts.cache === true ? new Xache({ maxSize: 65536, maxAge: 0 }) : (opts.cache || null)
|
|
53
|
+
this.encryption = opts.encryption || null
|
|
52
54
|
|
|
53
55
|
this.valueEncoding = null
|
|
54
56
|
this.key = key || null
|
|
@@ -64,6 +66,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
64
66
|
this.closing = null
|
|
65
67
|
this.opening = opts._opening || this._open(key, storage, opts)
|
|
66
68
|
this.opening.catch(noop)
|
|
69
|
+
|
|
70
|
+
this._preappend = this.encryption && preappend.bind(this)
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
[inspect] (depth, opts) {
|
|
@@ -119,6 +123,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
119
123
|
...opts,
|
|
120
124
|
sign: opts.sign || (keyPair && keyPair.secretKey && Core.createSigner(this.crypto, keyPair)) || this.sign,
|
|
121
125
|
valueEncoding: this.valueEncoding,
|
|
126
|
+
encryption: this.encryption,
|
|
122
127
|
extensions: this.extensions,
|
|
123
128
|
_opening: this.opening,
|
|
124
129
|
_sessions: this.sessions
|
|
@@ -207,7 +212,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
207
212
|
}
|
|
208
213
|
|
|
209
214
|
get byteLength () {
|
|
210
|
-
return this.core === null ? 0 : this.core.tree.byteLength
|
|
215
|
+
return this.core === null ? 0 : this.core.tree.byteLength - (this.core.tree.length * this.padding)
|
|
211
216
|
}
|
|
212
217
|
|
|
213
218
|
get fork () {
|
|
@@ -218,6 +223,14 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
218
223
|
return this.replicator === null ? [] : this.replicator.peers
|
|
219
224
|
}
|
|
220
225
|
|
|
226
|
+
get encryptionKey () {
|
|
227
|
+
return this.encryption && this.encryption.key
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
get padding () {
|
|
231
|
+
return this.encryption === null ? 0 : this.encryption.padding
|
|
232
|
+
}
|
|
233
|
+
|
|
221
234
|
ready () {
|
|
222
235
|
return this.opening
|
|
223
236
|
}
|
|
@@ -271,6 +284,11 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
271
284
|
this.key = this.core.header.signer.publicKey
|
|
272
285
|
this.writable = !!this.sign
|
|
273
286
|
|
|
287
|
+
if (!this.encryption && opts.encryptionKey) {
|
|
288
|
+
this.encryption = new BlockEncryption(opts.encryptionKey, this.key)
|
|
289
|
+
this._preappend = preappend.bind(this)
|
|
290
|
+
}
|
|
291
|
+
|
|
274
292
|
this.extensions.attach(this.replicator)
|
|
275
293
|
this.opened = true
|
|
276
294
|
|
|
@@ -305,6 +323,12 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
305
323
|
}
|
|
306
324
|
|
|
307
325
|
if (value) {
|
|
326
|
+
if (this.encryption) {
|
|
327
|
+
this.encryption.decrypt(bitfield.start, value)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
value = value.subarray(this.padding)
|
|
331
|
+
|
|
308
332
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
309
333
|
this.sessions[i].emit('download', bitfield.start, value, from)
|
|
310
334
|
}
|
|
@@ -343,7 +367,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
343
367
|
async seek (bytes) {
|
|
344
368
|
if (this.opened === false) await this.opening
|
|
345
369
|
|
|
346
|
-
const s = this.core.tree.seek(bytes)
|
|
370
|
+
const s = this.core.tree.seek(bytes, this.padding)
|
|
347
371
|
|
|
348
372
|
return (await s.update()) || this.replicator.requestSeek(s)
|
|
349
373
|
}
|
|
@@ -367,10 +391,17 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
367
391
|
async _get (index, opts) {
|
|
368
392
|
const encoding = (opts && opts.valueEncoding && c.from(codecs(opts.valueEncoding))) || this.valueEncoding
|
|
369
393
|
|
|
370
|
-
|
|
371
|
-
|
|
394
|
+
let block
|
|
395
|
+
|
|
396
|
+
if (this.core.bitfield.get(index)) {
|
|
397
|
+
block = await this.core.blocks.get(index)
|
|
398
|
+
} else {
|
|
399
|
+
if (opts && opts.onwait) opts.onwait(index)
|
|
400
|
+
block = await this.replicator.requestBlock(index)
|
|
401
|
+
}
|
|
372
402
|
|
|
373
|
-
|
|
403
|
+
if (this.encryption) this.encryption.decrypt(index, block)
|
|
404
|
+
return this._decode(encoding, block)
|
|
374
405
|
}
|
|
375
406
|
|
|
376
407
|
download (range) {
|
|
@@ -427,22 +458,17 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
427
458
|
if (this.opened === false) await this.opening
|
|
428
459
|
if (this.writable === false) throw new Error('Core is not writable')
|
|
429
460
|
|
|
430
|
-
|
|
431
|
-
const buffers = new Array(blks.length)
|
|
432
|
-
|
|
433
|
-
for (let i = 0; i < blks.length; i++) {
|
|
434
|
-
const blk = blks[i]
|
|
461
|
+
blocks = Array.isArray(blocks) ? blocks : [blocks]
|
|
435
462
|
|
|
436
|
-
|
|
437
|
-
? blk
|
|
438
|
-
: this.valueEncoding
|
|
439
|
-
? c.encode(this.valueEncoding, blk)
|
|
440
|
-
: Buffer.from(blk)
|
|
463
|
+
const buffers = new Array(blocks.length)
|
|
441
464
|
|
|
442
|
-
|
|
465
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
466
|
+
buffers[i] = this._encode(this.valueEncoding, blocks[i])
|
|
443
467
|
}
|
|
444
468
|
|
|
445
|
-
return await this.core.append(buffers, this.sign
|
|
469
|
+
return await this.core.append(buffers, this.sign, {
|
|
470
|
+
preappend: this._preappend
|
|
471
|
+
})
|
|
446
472
|
}
|
|
447
473
|
|
|
448
474
|
registerExtension (name, handlers) {
|
|
@@ -453,14 +479,38 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
453
479
|
onextensionupdate () {
|
|
454
480
|
if (this.replicator !== null) this.replicator.broadcastOptions()
|
|
455
481
|
}
|
|
456
|
-
}
|
|
457
482
|
|
|
458
|
-
|
|
483
|
+
_encode (enc, val) {
|
|
484
|
+
const state = { start: this.padding, end: this.padding, buffer: null }
|
|
485
|
+
|
|
486
|
+
if (Buffer.isBuffer(val)) {
|
|
487
|
+
if (state.start === 0) return val
|
|
488
|
+
state.end += val.byteLength
|
|
489
|
+
} else if (enc) {
|
|
490
|
+
enc.preencode(state, val)
|
|
491
|
+
} else {
|
|
492
|
+
val = Buffer.from(val)
|
|
493
|
+
if (state.start === 0) return val
|
|
494
|
+
state.end += val.byteLength
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
state.buffer = Buffer.allocUnsafe(state.end)
|
|
498
|
+
|
|
499
|
+
if (enc) enc.encode(state, val)
|
|
500
|
+
else state.buffer.set(val, state.start)
|
|
501
|
+
|
|
502
|
+
return state.buffer
|
|
503
|
+
}
|
|
459
504
|
|
|
460
|
-
|
|
461
|
-
|
|
505
|
+
_decode (enc, block) {
|
|
506
|
+
block = block.subarray(this.padding)
|
|
507
|
+
if (enc) return c.decode(enc, block)
|
|
508
|
+
return block
|
|
509
|
+
}
|
|
462
510
|
}
|
|
463
511
|
|
|
512
|
+
function noop () {}
|
|
513
|
+
|
|
464
514
|
function isStream (s) {
|
|
465
515
|
return typeof s === 'object' && s && typeof s.pipe === 'function'
|
|
466
516
|
}
|
|
@@ -489,3 +539,12 @@ function min (arr) {
|
|
|
489
539
|
function max (arr) {
|
|
490
540
|
return reduce(arr, (a, b) => Math.max(a, b), -Infinity)
|
|
491
541
|
}
|
|
542
|
+
|
|
543
|
+
function preappend (blocks) {
|
|
544
|
+
const offset = this.core.tree.length
|
|
545
|
+
const fork = this.core.tree.fork
|
|
546
|
+
|
|
547
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
548
|
+
this.encryption.encrypt(offset + i, blocks[i], fork)
|
|
549
|
+
}
|
|
550
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const sodium = require('sodium-universal')
|
|
2
|
+
const c = require('compact-encoding')
|
|
3
|
+
|
|
4
|
+
const nonce = Buffer.alloc(sodium.crypto_stream_NONCEBYTES)
|
|
5
|
+
|
|
6
|
+
module.exports = class BlockEncryption {
|
|
7
|
+
constructor (encryptionKey, hypercoreKey) {
|
|
8
|
+
const subKeys = Buffer.alloc(2 * sodium.crypto_stream_KEYBYTES)
|
|
9
|
+
|
|
10
|
+
this.key = encryptionKey
|
|
11
|
+
this.blockKey = subKeys.subarray(0, sodium.crypto_stream_KEYBYTES)
|
|
12
|
+
this.blindingKey = subKeys.subarray(sodium.crypto_stream_KEYBYTES)
|
|
13
|
+
this.padding = 8
|
|
14
|
+
|
|
15
|
+
sodium.crypto_generichash(this.blockKey, encryptionKey, hypercoreKey)
|
|
16
|
+
sodium.crypto_generichash(this.blindingKey, this.blockKey)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
encrypt (index, block, fork) {
|
|
20
|
+
const padding = block.subarray(0, this.padding)
|
|
21
|
+
block = block.subarray(this.padding)
|
|
22
|
+
|
|
23
|
+
c.uint64.encode({ start: 0, end: 8, buffer: padding }, fork)
|
|
24
|
+
c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
|
|
25
|
+
|
|
26
|
+
// Zero out any previous padding.
|
|
27
|
+
nonce.fill(0, 8, 8 + padding.byteLength)
|
|
28
|
+
|
|
29
|
+
// Blind the fork ID, possibly risking reusing the nonce on a reorg of the
|
|
30
|
+
// Hypercore. This is fine as the blinding is best-effort and the latest
|
|
31
|
+
// fork ID shared on replication anyway.
|
|
32
|
+
sodium.crypto_stream_xor(
|
|
33
|
+
padding,
|
|
34
|
+
padding,
|
|
35
|
+
nonce,
|
|
36
|
+
this.blindingKey
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
nonce.set(padding, 8)
|
|
40
|
+
|
|
41
|
+
// The combination of a (blinded) fork ID and a block index is unique for a
|
|
42
|
+
// given Hypercore and is therefore a valid nonce for encrypting the block.
|
|
43
|
+
sodium.crypto_stream_xor(
|
|
44
|
+
block,
|
|
45
|
+
block,
|
|
46
|
+
nonce,
|
|
47
|
+
this.blockKey
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
decrypt (index, block) {
|
|
52
|
+
const padding = block.subarray(0, this.padding)
|
|
53
|
+
block = block.subarray(this.padding)
|
|
54
|
+
|
|
55
|
+
c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
|
|
56
|
+
|
|
57
|
+
nonce.set(padding, 8)
|
|
58
|
+
|
|
59
|
+
// Decrypt the block using the blinded fork ID.
|
|
60
|
+
sodium.crypto_stream_xor(
|
|
61
|
+
block,
|
|
62
|
+
block,
|
|
63
|
+
nonce,
|
|
64
|
+
this.blockKey
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
}
|
package/lib/core.js
CHANGED
|
@@ -214,10 +214,12 @@ module.exports = class Core {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
async append (values, sign = this.defaultSign) {
|
|
217
|
+
async append (values, sign = this.defaultSign, hooks = {}) {
|
|
218
218
|
await this._mutex.lock()
|
|
219
219
|
|
|
220
220
|
try {
|
|
221
|
+
if (hooks.preappend) await hooks.preappend(values)
|
|
222
|
+
|
|
221
223
|
if (!values.length) return this.tree.length
|
|
222
224
|
|
|
223
225
|
const batch = this.tree.batch()
|
package/lib/merkle-tree.js
CHANGED
|
@@ -272,11 +272,15 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
class ByteSeeker {
|
|
275
|
-
constructor (tree, bytes) {
|
|
275
|
+
constructor (tree, bytes, padding = 0) {
|
|
276
276
|
this.tree = tree
|
|
277
277
|
this.bytes = bytes
|
|
278
|
-
this.
|
|
279
|
-
|
|
278
|
+
this.padding = padding
|
|
279
|
+
|
|
280
|
+
const size = tree.byteLength - (tree.length * padding)
|
|
281
|
+
|
|
282
|
+
this.start = bytes >= size ? tree.length : 0
|
|
283
|
+
this.end = bytes < size ? tree.length : 0
|
|
280
284
|
}
|
|
281
285
|
|
|
282
286
|
nodes () {
|
|
@@ -287,12 +291,12 @@ class ByteSeeker {
|
|
|
287
291
|
if (!bytes) return [0, 0]
|
|
288
292
|
|
|
289
293
|
for (const node of this.tree.roots) { // all async ticks happen once we find the root so safe
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
294
|
+
let size = node.size
|
|
295
|
+
if (this.padding > 0) size -= this.padding * flat.countLeaves(node.index)
|
|
293
296
|
|
|
294
|
-
if (bytes
|
|
295
|
-
|
|
297
|
+
if (bytes === size) return [flat.rightSpan(node.index) + 2, 0]
|
|
298
|
+
if (bytes > size) {
|
|
299
|
+
bytes -= size
|
|
296
300
|
continue
|
|
297
301
|
}
|
|
298
302
|
|
|
@@ -301,9 +305,12 @@ class ByteSeeker {
|
|
|
301
305
|
while ((ite.index & 1) !== 0) {
|
|
302
306
|
const l = await this.tree.get(ite.leftChild(), false)
|
|
303
307
|
if (l) {
|
|
304
|
-
|
|
305
|
-
if (
|
|
306
|
-
|
|
308
|
+
let size = l.size
|
|
309
|
+
if (this.padding > 0) size -= this.padding * ite.countLeaves()
|
|
310
|
+
|
|
311
|
+
if (size === bytes) return [ite.rightSpan() + 2, 0]
|
|
312
|
+
if (size > bytes) continue
|
|
313
|
+
bytes -= size
|
|
307
314
|
ite.sibling()
|
|
308
315
|
} else {
|
|
309
316
|
ite.parent()
|
|
@@ -355,8 +362,8 @@ module.exports = class MerkleTree {
|
|
|
355
362
|
return new MerkleTreeBatch(this)
|
|
356
363
|
}
|
|
357
364
|
|
|
358
|
-
seek (bytes) {
|
|
359
|
-
return new ByteSeeker(this, bytes)
|
|
365
|
+
seek (bytes, padding) {
|
|
366
|
+
return new ByteSeeker(this, bytes, padding)
|
|
360
367
|
}
|
|
361
368
|
|
|
362
369
|
hash () {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "10.0.0-alpha.
|
|
3
|
+
"version": "10.0.0-alpha.7",
|
|
4
4
|
"description": "Hypercore 10",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,14 +31,15 @@
|
|
|
31
31
|
"@hyperswarm/secret-stream": "^5.0.0",
|
|
32
32
|
"big-sparse-array": "^1.0.2",
|
|
33
33
|
"codecs": "^2.2.0",
|
|
34
|
-
"compact-encoding": "^2.
|
|
34
|
+
"compact-encoding": "^2.5.0",
|
|
35
35
|
"crc32-universal": "^1.0.1",
|
|
36
|
-
"flat-tree": "^1.
|
|
36
|
+
"flat-tree": "^1.9.0",
|
|
37
37
|
"hypercore-crypto": "^2.1.1",
|
|
38
38
|
"is-options": "^1.0.1",
|
|
39
39
|
"random-access-file": "^2.1.4",
|
|
40
40
|
"random-array-iterator": "^1.0.0",
|
|
41
41
|
"safety-catch": "^1.0.1",
|
|
42
|
+
"sodium-universal": "^3.0.4",
|
|
42
43
|
"uint64le": "^1.0.0",
|
|
43
44
|
"xache": "^1.0.0"
|
|
44
45
|
},
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const test = require('brittle')
|
|
2
|
+
const { create, replicate } = require('./helpers')
|
|
3
|
+
|
|
4
|
+
const encryptionKey = Buffer.alloc(32, 'hello world')
|
|
5
|
+
|
|
6
|
+
test('encrypted append and get', async function (t) {
|
|
7
|
+
const a = await create({ encryptionKey })
|
|
8
|
+
|
|
9
|
+
t.alike(a.encryptionKey, encryptionKey)
|
|
10
|
+
|
|
11
|
+
await a.append(['hello'])
|
|
12
|
+
|
|
13
|
+
t.is(a.byteLength, 5)
|
|
14
|
+
t.is(a.core.tree.byteLength, 5 + a.padding)
|
|
15
|
+
|
|
16
|
+
const unencrypted = await a.get(0)
|
|
17
|
+
const encrypted = await a.core.blocks.get(0)
|
|
18
|
+
|
|
19
|
+
t.alike(unencrypted, Buffer.from('hello'))
|
|
20
|
+
t.unlike(unencrypted, encrypted)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('encrypted seek', async function (t) {
|
|
24
|
+
const a = await create({ encryptionKey })
|
|
25
|
+
|
|
26
|
+
await a.append(['hello', 'world', '!'])
|
|
27
|
+
|
|
28
|
+
t.alike(await a.seek(0), [0, 0])
|
|
29
|
+
t.alike(await a.seek(4), [0, 4])
|
|
30
|
+
t.alike(await a.seek(5), [1, 0])
|
|
31
|
+
t.alike(await a.seek(6), [1, 1])
|
|
32
|
+
t.alike(await a.seek(6), [1, 1])
|
|
33
|
+
t.alike(await a.seek(9), [1, 4])
|
|
34
|
+
t.alike(await a.seek(10), [2, 0])
|
|
35
|
+
t.alike(await a.seek(11), [3, 0])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('encrypted replication', async function (t) {
|
|
39
|
+
const a = await create({ encryptionKey })
|
|
40
|
+
|
|
41
|
+
await a.append(['a', 'b', 'c', 'd', 'e'])
|
|
42
|
+
|
|
43
|
+
t.test('with encryption key', async function (t) {
|
|
44
|
+
t.plan(10)
|
|
45
|
+
|
|
46
|
+
const b = await create(a.key, { encryptionKey })
|
|
47
|
+
|
|
48
|
+
b.on('download', (i, block) => {
|
|
49
|
+
t.alike(block, Buffer.from([i + /* a */ 0x61]))
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
replicate(a, b, t)
|
|
53
|
+
|
|
54
|
+
const r = b.download({ start: 0, end: a.length })
|
|
55
|
+
await r.downloaded()
|
|
56
|
+
|
|
57
|
+
for (let i = 0; i < 5; i++) {
|
|
58
|
+
t.alike(await b.get(i), await a.get(i))
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
t.test('without encryption key', async function (t) {
|
|
63
|
+
const b = await create(a.key)
|
|
64
|
+
|
|
65
|
+
replicate(a, b, t)
|
|
66
|
+
|
|
67
|
+
const r = b.download({ start: 0, end: a.length })
|
|
68
|
+
await r.downloaded()
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < 5; i++) {
|
|
71
|
+
t.unlike(await b.get(i), await a.get(i))
|
|
72
|
+
t.alike(await b.get(i), await a.core.blocks.get(i))
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('encrypted sessions', async function (t) {
|
|
78
|
+
const a = await create({ encryptionKey })
|
|
79
|
+
|
|
80
|
+
await a.append(['hello'])
|
|
81
|
+
|
|
82
|
+
const session = a.session()
|
|
83
|
+
|
|
84
|
+
t.alike(await session.get(0), Buffer.from('hello'))
|
|
85
|
+
})
|