moolb-js

Bloom filter for javascript with pluggable hasher backend
git clone git://git.defalsify.org/moolb-js.git
Log | Files | Refs | README

commit 72d515a95954b92ae106aec40b676188fe57d1b0
parent 38a7419e3cdb59b1a9475bca9e3b03c09eca5c4a
Author: nolash <dev@holbrook.no>
Date:   Sat, 31 Oct 2020 12:25:53 +0100

Add automatic adapters for nodejs and web crypto backends for hashing

Diffstat:
Mmoolb/moolb.js | 66+++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mtests/test_moolb.js | 8++++----
2 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/moolb/moolb.js b/moolb/moolb.js @@ -2,26 +2,54 @@ let crypto = undefined; (function() { if (typeof module !== 'undefined' && typeof exports !== 'undefined') { - crypto = require('crypto'); + let nodeCrypto = require('crypto'); + function hashWrapper(nodeCrypto, alg) { + this.alg = alg; + this.crypto = nodeCrypto.createHash(alg); + } + hashWrapper.prototype.update = function(d) { + this.crypto.update(d); + } + hashWrapper.prototype.digest = async function() { + z = this.crypto.digest(this.data); + return new Uint8Array(z); + } + + function cryptoWrapper(nodeCrypto) { + this.crypto = nodeCrypto + } + cryptoWrapper.prototype.createHash = function(alg) { + return new hashWrapper(this.crypto, alg); + } module.exports = { Bloom: Bloom, fromBytes: fromBytes, }; + crypto = new cryptoWrapper(nodeCrypto); } else { - function cryptoWrapper(webCrypto) { + function hashWrapper(webCrypto, alg) { + this.alg = alg; this.crypto = webCrypto; + this.data = undefined; } - cryptoWrapper.prototype.createHash = function(b, s) { - d = new Uint8Array(b.byteLength + s.byteLength); - let i = 0; - for (; i < b.byteLength; i++) { - d[i] = b[i]; + hashWrapper.prototype.update = function(d) { + if (this.data != undefined) { + throw "cannot append"; } - for (let j = 0; j < s.byteLength; j++) { - d[i+j] = s[j]; - } - return this.crypto.subtle.digest(d); + this.data = d; + } + hashWrapper.prototype.digest = async function() { + z = await this.crypto.subtle.digest('SHA-256', this.data); + return new Uint8Array(z); } + + function cryptoWrapper(webCrypto) { + this.crypto = webCrypto + } + cryptoWrapper.prototype.createHash = function(alg) { + return new hashWrapper(this.crypto, alg); + } + crypto = new cryptoWrapper(window.crypto); window.Bloom = Bloom; window.bloomFromBytes = fromBytes; @@ -57,7 +85,7 @@ function Bloom(bits, rounds, hasher) { // add entry to bloom filter // \param value to add -Bloom.prototype.add = function(v) { +Bloom.prototype.add = async function(v) { let a = new ArrayBuffer(v.byteLength + 4); let iw = new DataView(a); for (let i = 0; i < v.byteLength; i++) { @@ -66,8 +94,7 @@ Bloom.prototype.add = function(v) { console.log(iw, v); for (var i = 0; i < this.rounds; i++) { iw.setInt32(v.byteLength, i); - console.log(iw); - let result = this.hasher(iw); + let result = await this.hasher(iw); let resultHex = Array.prototype.map.call(new Uint8Array(result), x => ('00' + x.toString(16)).slice(-2)).join(''); let resultInt = parseInt(BigInt('0x'+resultHex) % BigInt(this.bits), 10); let bytepos = parseInt(resultInt / 8, 10); @@ -80,7 +107,7 @@ Bloom.prototype.add = function(v) { // checks if the block number has been added to the bloom filter // \param value to check for // \return false if not found in filter -Bloom.prototype.check = function(v) { +Bloom.prototype.check = async function(v) { let a = new ArrayBuffer(v.byteLength + 4); let iw = new DataView(a); for (let i = 0; i < v.byteLength; i++) { @@ -88,7 +115,8 @@ Bloom.prototype.check = function(v) { } for (let i = 0; i < this.rounds; i++) { iw.setInt32(v.byteLength, i); - let result = this.hasher(iw); + let result = await this.hasher(iw); + //console.log('result', result); let resultHex = Array.prototype.map.call(new Uint8Array(result), x => ('00' + x.toString(16)).slice(-2)).join(''); let resultInt = parseInt(BigInt('0x'+resultHex) % BigInt(this.bits), 10); let bytepos = parseInt(resultInt / 8, 10); @@ -117,11 +145,11 @@ Bloom.prototype.bytes = function() { // \param data to insert in filter // \param salt, typically a sequence number // \return Uint8Array digest -function hashBloomDefault(data, salt) { +async function hashBloomDefault(data, salt) { let h = crypto.createHash('sha256'); h.update(data); - return Uint8Array.from(h.digest()); - //return h.digest(); + z = await h.digest(); + return Uint8Array.from(z); } function fromBytes(bytes, rounds, hasher) { diff --git a/tests/test_moolb.js b/tests/test_moolb.js @@ -2,17 +2,17 @@ let moolb = require('../moolb/moolb'); let assert = require('assert'); describe('check', () => { - it('builtin', () => { + it('builtin', async () => { let ref = b = new moolb.Bloom(8192 * 8, 3); let enc = new TextEncoder(); let v = enc.encode('1024'); - b.add(v); - let r = b.check(v); + await b.add(v); + let r = await b.check(v); assert(r); v = enc.encode('1023'); - r = b.check(v); + r = await b.check(v); assert(!r) }); });