hypercore-xsalsa20-onwrite-hook
Version:
A write hook to decrypt data using a XSalsa20 cipher into a hypercore storage when replicating from peers
60 lines (50 loc) • 1.47 kB
JavaScript
const xsalsa20 = require('xsalsa20-encoding')
const varint = require('varint')
const crypto = require('hypercore-crypto')
const assert = require('assert')
/**
* The size in bytes of the nonce attached to an
* enciphered buffer returned from the xsalsa20
* encoding.
* @public
* @const
*/
const NONCE_BYTES = 24
/**
* Creates a `onwrite()` hook for a Hypercore feed that uses the
* xsalsa20 cipher to encipher or decipher blocks in a Hypercore feed.
* Nonces are computed from the Hypercore feed's public key and block index.
* @param {String|Buffer} key
* @return {Function}
*/
function createHook(key, opts) {
// istanbul ignore next
if ('string' === typeof key) {
key = Buffer.from(key, 'hex')
}
assert(Buffer.isBuffer(key), '`key` is not a buffer.')
return onwrite
function onwrite(index, data, peer, done) {
const block = Buffer.from(varint.encode(index))
const nonce = Buffer.allocUnsafe(24)
// nonce = hash(key || block)
crypto.data(Buffer.concat([this.key, block])).copy(nonce)
// if not replicating from a peer, encipher plaintext,
// otherwise decipher ciphertext with computed nonce
if (!peer) {
xsalsa20(key, { nonce: () => nonce })
.encode(data)
.slice(NONCE_BYTES)
.copy(data)
} else {
xsalsa20(key)
.decode(Buffer.concat([nonce, data]))
.copy(data)
}
done(null)
}
}
/**
* Module exports.
*/
module.exports = createHook