From 3f23a11f57fa029818ceb81af1572c052f0924b2 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Tue, 3 Apr 2018 13:26:21 +0200 Subject: [PATCH 1/3] feat: add flow annotations This adds flow annotations to multihashing --- .babelrc | 34 ++++++++++ .flowconfig | 9 +++ package.json | 36 ++++++++-- src/blake.js | 65 ++++++++++++------ src/index.js | 53 +++++++++------ src/sha3.js | 49 ++++++++------ src/types.js | 10 +++ test/index.spec.js | 161 ++++++++++++++++++++++++++------------------- test/node.js | 4 ++ 9 files changed, 288 insertions(+), 133 deletions(-) create mode 100644 .babelrc create mode 100644 .flowconfig create mode 100644 src/types.js create mode 100644 test/node.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..0a4cc4b --- /dev/null +++ b/.babelrc @@ -0,0 +1,34 @@ +{ + "env": { + "development": { + "sourceMaps": "inline", + "comments": false, + "presets": [ + [ + "env", + { + "targets": { + "node": "current" + } + } + ], + "flow-node" + ] + }, + "umd": { + "comments": false, + "presets": [ + [ + "env", + { + "modules": false, + "targets": { + "browsers": "last 2 versions" + } + } + ], + "flow-node" + ] + } + } +} diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..57c6722 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,9 @@ +[ignore] +.*/node_modules/documentation/* + +[libs] + +[include] + +[options] +suppress_comment= \\(.\\|\n\\)*\\@FlowIgnore diff --git a/package.json b/package.json index e2c7f82..460c9f9 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,10 @@ "description": "multiple hash functions", "main": "src/index.js", "scripts": { - "lint": "aegir lint", - "build": "aegir build", - "test": "aegir test -t node -t browser -t webworker", + "lint": "lint-staged && npm run type-check", + "type-check": "flow check", + "build": "npm run build:node && BABEL_ENV=umd aegir build", + "test": "npm run build:node && aegir test -t node -t browser -t webworker", "test:node": "aegir test -t node", "test:browser": "aegir test -t browser", "test:webworker": "aegir test -t webworker", @@ -14,12 +15,27 @@ "release-minor": "aegir release --type minor -t node -t browser", "release-major": "aegir release --type major -t node -t browser", "coverage": "aegir coverage", - "coverage-publish": "aegir coverage --provider coveralls" + "coverage-publish": "aegir coverage --provider coveralls", + "build:types": "flow-copy-source --verbose src lib", + "build:lib": "babel --out-dir lib src", + "build:node": "npm run build:types && npm run build:lib", + "start": "flow-copy-source --watch --verbose src lib & babel --watch --out-dir lib src" + }, + "lint-staged": { + "*.js": [ + "prettier --no-semi --write", + "git add" + ] }, "pre-commit": [ "lint", "test" ], + "standard": { + "ignore": [ + "dist" + ] + }, "repository": { "type": "git", "url": "git://github.com/multiformats/js-multihashing.git" @@ -33,6 +49,9 @@ "url": "https://github.com/multiformats/js-multihashing/issues" }, "dependencies": { + "babel-cli": "^6.26.0", + "babel-core": "^6.26.0", + "babel-loader": "^7.1.4", "blakejs": "^1.1.0", "js-sha3": "^0.7.0", "multihashes": "~0.4.12", @@ -40,9 +59,16 @@ }, "devDependencies": { "aegir": "^12.3.0", + "babel-preset-flow-node": "^2.0.1", "chai": "^4.1.2", "dirty-chai": "^2.0.1", - "pre-commit": "^1.2.2" + "flow-bin": "^0.69.0", + "flow-copy-source": "^1.3.0", + "lint-staged": "^7.0.2", + "pre-commit": "^1.2.2", + "prettier": "^1.11.1", + "rollup.config.flow": "^1.0.0", + "source-map-support": "^0.5.4" }, "homepage": "https://github.com/multiformats/js-multihashing", "contributors": [ diff --git a/src/blake.js b/src/blake.js index 1f7af54..5796e4a 100644 --- a/src/blake.js +++ b/src/blake.js @@ -1,56 +1,79 @@ -'use strict' +// @flow +"use strict" -const blake = require('blakejs') -const minB = 0xb201 -const minS = 0xb241 +import * as blake from "blakejs" +import type { Hash, HashTable, HashBuilder } from "./types" +import type { Code } from "multihashes/lib/constants" -var blake2b = { +const minB: Code = 0xb201 +const minS: Code = 0xb241 + +type BlakeCtx = { + b: Uint8Array, + h: Uint32Array, + t: number, + c: number, + outlen: number +} +type Blake2Hash = Buffer +type BlakeHasher = { + init(size: number, key: ?number): BlakeCtx, + update(ctx: BlakeCtx, input: Uint8Array): void, + digest(ctx: BlakeCtx): Uint8Array +} + +const blake2b: BlakeHasher = { init: blake.blake2bInit, update: blake.blake2bUpdate, digest: blake.blake2bFinal } -var blake2s = { +blake2b.init(1, 1) + +const blake2s: BlakeHasher = { init: blake.blake2sInit, update: blake.blake2sUpdate, digest: blake.blake2sFinal } -class B2Hash { - constructor (size, hashFunc) { +class B2Hash implements Hash { + ctx: BlakeCtx | null + hf: BlakeHasher + + constructor(size, hashFunc) { this.hf = hashFunc this.ctx = this.hf.init(size, null) } - update (buf) { + update(buf: Buffer): Hash { if (this.ctx === null) { - throw new Error('blake2 context is null. (already called digest?)') + throw new Error("blake2 context is null. (already called digest?)") } this.hf.update(this.ctx, buf) return this } - digest () { + digest(): Blake2Hash { const ctx = this.ctx this.ctx = null + if (ctx === null) { + throw Error("blake2 context is null. (already called digest?)") + } return Buffer.from(this.hf.digest(ctx)) } } -function addFuncs (table) { - function mkFunc (size, hashFunc) { - return () => new B2Hash(size, hashFunc) +export const addFuncs = (table: HashTable) => { + const mkFunc = (size: number, hashFunc: BlakeHasher): HashBuilder => { + return (): Hash => new B2Hash(size, hashFunc) } - var i + // I don't like using any here but the only way I could get the types to work here. + let i for (i = 0; i < 64; i++) { - table[minB + i] = mkFunc(i + 1, blake2b) + table[(minB + i: any)] = mkFunc(i + 1, blake2b) } for (i = 0; i < 32; i++) { - table[minS + i] = mkFunc(i + 1, blake2s) + table[(minS + i: any)] = mkFunc(i + 1, blake2s) } } - -module.exports = { - addFuncs: addFuncs -} diff --git a/src/index.js b/src/index.js index 1624e61..1baa2c3 100644 --- a/src/index.js +++ b/src/index.js @@ -1,23 +1,34 @@ -'use strict' +// @flow +"use strict" -const multihash = require('multihashes') -const blake = require('./blake') -const sha3 = require('./sha3') -const crypto = require('webcrypto') +import * as multihash from "multihashes" +import type { Multihash } from "multihashes" +import type { Name, Code } from "multihashes/lib/constants" +import type { HashTable, Hash } from "./types" +import * as blake from "./blake" +import * as sha3 from "./sha3" +import * as crypto from "webcrypto" -const mh = module.exports = Multihashing +const mh = (module.exports = Multihashing) mh.Buffer = Buffer // for browser things -function Multihashing (buf, func, length) { +function Multihashing( + buf: Buffer, + func: Name | Code, + length: number +): Multihash { return multihash.encode(mh.digest(buf, func, length), func, length) } // expose multihash itself, to avoid silly double requires. mh.multihash = multihash -mh.digest = function (buf, func, length) { - let digest = mh.createHash(func).update(buf).digest() +mh.digest = function(buf: Buffer, func: Name | Code, length: ?number): Buffer { + let digest = mh + .createHash(func) + .update(buf) + .digest() if (length) { digest = digest.slice(0, length) @@ -26,38 +37,38 @@ mh.digest = function (buf, func, length) { return digest } -mh.createHash = function (func, length) { +mh.createHash = function(func: Name | Code): Hash { func = multihash.coerceCode(func) if (!mh.functions[func]) { - throw new Error('multihash function ' + func + ' not yet supported') + throw new Error("multihash function " + func + " not yet supported") } return mh.functions[func]() } -mh.verify = function (hash, buf) { +mh.verify = function verify(hash: Multihash, buf: Buffer): boolean { const decoded = multihash.decode(hash) const encoded = mh(buf, decoded.name, decoded.length) return encoded.equals(hash) } mh.functions = { - 0x11: gsha1, - 0x12: gsha2256, - 0x13: gsha2512 + [0x11]: gsha1, + [0x12]: gsha2256, + [0x13]: gsha2512 } blake.addFuncs(mh.functions) sha3.addFuncs(mh.functions) -function gsha1 () { - return crypto.createHash('sha1') +function gsha1(): Hash { + return crypto.createHash("sha1") } -function gsha2256 () { - return crypto.createHash('sha256') +function gsha2256(): Hash { + return crypto.createHash("sha256") } -function gsha2512 () { - return crypto.createHash('sha512') +function gsha2512(): Hash { + return crypto.createHash("sha512") } diff --git a/src/sha3.js b/src/sha3.js index b7a9695..7b81b16 100644 --- a/src/sha3.js +++ b/src/sha3.js @@ -1,6 +1,8 @@ -'use strict' +// @flow +"use strict" -const sha3 = require('js-sha3') +import * as sha3 from "js-sha3" +import type { Hash, HashTable } from "./types" const functions = [ [0x14, sha3.sha3_512], @@ -9,44 +11,53 @@ const functions = [ [0x17, sha3.sha3_224], [0x18, sha3.shake128, 256], [0x19, sha3.shake256, 512], - [0x1A, sha3.keccak224], - [0x1B, sha3.keccak256], - [0x1C, sha3.keccak384], - [0x1D, sha3.keccak512] + [0x1a, sha3.keccak224], + [0x1b, sha3.keccak256], + [0x1c, sha3.keccak384], + [0x1d, sha3.keccak512] ] -class Hasher { - constructor (hashFunc, arg) { +type HexString = string +type Sha3Hash = Buffer +type ShaHasher = (input: string | Buffer, length?: number) => HexString + +class ShaHash implements Hash { + hf: ShaHasher + input: Buffer | null + arg: number + + constructor(hashFunc, arg?: number) { this.hf = hashFunc - this.arg = arg + if (arg) { + this.arg = arg + } this.input = null } - update (buf) { + update(buf: Buffer): Hash { this.input = buf return this } - digest () { + digest(): Sha3Hash { + if (!this.input) { + throw Error("Missing an input to hash") + } const input = this.input const arg = this.arg - return Buffer.from(this.hf(input, arg), 'hex') + return Buffer.from(this.hf(input, arg), "hex") } } -function addFuncs (table) { +export const addFuncs = (table: HashTable) => { for (const info of functions) { const code = info[0] const fn = info[1] if (info.length === 3) { - table[code] = () => new Hasher(fn, info[2]) + table[code] = () => new ShaHash(fn, info[2]) } else { - table[code] = () => new Hasher(fn) + table[code] = () => new ShaHash(fn) } } } - -module.exports = { - addFuncs: addFuncs -} diff --git a/src/types.js b/src/types.js new file mode 100644 index 0000000..e4ea8d0 --- /dev/null +++ b/src/types.js @@ -0,0 +1,10 @@ +// @flow +import type { Code } from "multihashes/lib/constants" + +export interface Hash { + update(buf: Buffer): Hash; + digest(): Buffer; +} + +export type HashBuilder = () => Hash +export type HashTable = { [Code]: HashBuilder } diff --git a/test/index.spec.js b/test/index.spec.js index ef59261..b8bb154 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,92 +1,119 @@ /* eslint-env mocha */ -'use strict' +"use strict" -const chai = require('chai') -const dirtyChai = require('dirty-chai') +const chai = require("chai") +const dirtyChai = require("dirty-chai") chai.use(dirtyChai) const expect = chai.expect -const multihashing = require('../src') +const multihashing = require("../lib") const tests = { - sha1: [ - ['beep boop', '11147c8357577f51d4f0a8d393aa1aaafb28863d9421'] - ], - 'sha2-256': [ - ['beep boop', '122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c'] - ], - 'sha2-512': [ - ['beep boop', '134014f301f31be243f34c5668937883771fa381002f1aaa5f31b3f78e500b66ff2f4f8ea5e3c9f5a61bd073e2452c480484b02e030fb239315a2577f7ae156af177'] - ], - 'blake2b-512': [ - ['beep boop', 'c0e402400eac6255ba822373a0948122b8d295008419a8ab27842ee0d70eca39855621463c03ec75ac3610aacfdff89fa989d8d61fc00450148f289eb5b12ad1a954f659'] - ], - 'blake2b-160': [ - ['beep boop', '94e40214fe303247293e54e0a7ea48f9408ca68b36b08442'] - ], - 'blake2s-256': [ - ['beep boop', 'e0e402204542eaca484e4311def8af74b546edd7fceb49eeb3cdcfd8a4a72ed0dc81d4c0'] - ], - 'blake2s-40': [ - ['beep boop', 'c5e402059ada01bb57'] - ], - 'sha3-512': [ - ['beep bop', '144038122bf54c0e1eeff013e9b8c735af7c08ff8a7bb2b55b5abe9d97f9653e19f388cd9719ffb4ab8ccb9330a1fd27929b0a9ee6d7b8b9884c6f787f11088219bc'] - ], - 'sha3-384': [ - ['beep bop', '15302f0456d702d4cafa23c091f8da2dc878b1536fd592c47c2d239f5de67f0a306f36e0197dbbf1c5409292aa92e326b16e'] - ], - 'sha3-256': [ - ['beep bop', '16204de761fac0b163270f59056e1c5d1038348fcb960c03610bde24565473600dfe'] - ], - 'sha3-224': [ - ['beep bop', '171cda7cce25c2f6248dc88a2fdfca56bb97bf39b100089cacfdf68b7b50'] - ], - 'shake-128': [ - ['beep boop', '18205fe422311f770743c2e0d86bcca092111cbce85487212829739c3c3723776e5a'] - ], - 'shake-256': [ - ['beep boop', '194059feb5565e4f924baef74708649fed376d63948a862322ed763ecf093b63b38b0955908c099c63dda73ee469c31b1456cec95e325bd868d0ce0c0135f5a54411'] - ], - 'keccak-224': [ - ['beep bop', '1a1c45f2663794752c0a2292985b476a6aec407cfd78ad6f14f56d7060d9'] - ], - 'keccak-256': [ - ['beep bop', '1b209e7c2fee63c4065cbaa989bd2655a288f877aa788484fb0640d125417796b5e9'] - ], - 'keccak-384': [ - ['beep bop', '1c305a1da4b6e329884e88b66d82961d6518d9cec66eae6ff6900344a30a742a044b6eb584ab6e8a1c609e04f2f235f5cab3'] - ], - 'keccak-512': [ - ['beep bop', '1d403c22f68c98a6c8ea9fa7819721fba90f905d3c29390d4a94fefc4f8348ed04829a7521b44af4aeea707b32fe63e28322666ae26a59feb3493fafa11873383f6c'] + sha1: [["beep boop", "11147c8357577f51d4f0a8d393aa1aaafb28863d9421"]], + "sha2-256": [ + [ + "beep boop", + "122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c" + ] + ], + "sha2-512": [ + [ + "beep boop", + "134014f301f31be243f34c5668937883771fa381002f1aaa5f31b3f78e500b66ff2f4f8ea5e3c9f5a61bd073e2452c480484b02e030fb239315a2577f7ae156af177" + ] + ], + "blake2b-512": [ + [ + "beep boop", + "c0e402400eac6255ba822373a0948122b8d295008419a8ab27842ee0d70eca39855621463c03ec75ac3610aacfdff89fa989d8d61fc00450148f289eb5b12ad1a954f659" + ] + ], + "blake2b-160": [ + ["beep boop", "94e40214fe303247293e54e0a7ea48f9408ca68b36b08442"] + ], + "blake2s-256": [ + [ + "beep boop", + "e0e402204542eaca484e4311def8af74b546edd7fceb49eeb3cdcfd8a4a72ed0dc81d4c0" + ] + ], + "blake2s-40": [["beep boop", "c5e402059ada01bb57"]], + "sha3-512": [ + [ + "beep bop", + "144038122bf54c0e1eeff013e9b8c735af7c08ff8a7bb2b55b5abe9d97f9653e19f388cd9719ffb4ab8ccb9330a1fd27929b0a9ee6d7b8b9884c6f787f11088219bc" + ] + ], + "sha3-384": [ + [ + "beep bop", + "15302f0456d702d4cafa23c091f8da2dc878b1536fd592c47c2d239f5de67f0a306f36e0197dbbf1c5409292aa92e326b16e" + ] + ], + "sha3-256": [ + [ + "beep bop", + "16204de761fac0b163270f59056e1c5d1038348fcb960c03610bde24565473600dfe" + ] + ], + "sha3-224": [ + ["beep bop", "171cda7cce25c2f6248dc88a2fdfca56bb97bf39b100089cacfdf68b7b50"] + ], + "shake-128": [ + [ + "beep boop", + "18205fe422311f770743c2e0d86bcca092111cbce85487212829739c3c3723776e5a" + ] + ], + "shake-256": [ + [ + "beep boop", + "194059feb5565e4f924baef74708649fed376d63948a862322ed763ecf093b63b38b0955908c099c63dda73ee469c31b1456cec95e325bd868d0ce0c0135f5a54411" + ] + ], + "keccak-224": [ + ["beep bop", "1a1c45f2663794752c0a2292985b476a6aec407cfd78ad6f14f56d7060d9"] + ], + "keccak-256": [ + [ + "beep bop", + "1b209e7c2fee63c4065cbaa989bd2655a288f877aa788484fb0640d125417796b5e9" + ] + ], + "keccak-384": [ + [ + "beep bop", + "1c305a1da4b6e329884e88b66d82961d6518d9cec66eae6ff6900344a30a742a044b6eb584ab6e8a1c609e04f2f235f5cab3" + ] + ], + "keccak-512": [ + [ + "beep bop", + "1d403c22f68c98a6c8ea9fa7819721fba90f905d3c29390d4a94fefc4f8348ed04829a7521b44af4aeea707b32fe63e28322666ae26a59feb3493fafa11873383f6c" + ] ] } -describe('multihashing', () => { +describe("multihashing", () => { for (const algo in tests) { it(algo, () => { for (const test of tests[algo]) { const input = Buffer.from(test[0]) - const output = Buffer.from(test[1], 'hex') + const output = Buffer.from(test[1], "hex") expect(multihashing(input, algo)).to.be.eql(output) expect(multihashing.verify(output, input)).to.be.eql(true) } }) } - it('cuts the length', () => { - const buf = Buffer.from('beep boop') - - expect( - multihashing(buf, 'sha2-256', 10) - ).to.be.eql( - Buffer.from('120a90ea688e275d58056732', 'hex') + it("cuts the length", () => { + const buf = Buffer.from("beep boop") + expect(multihashing(buf, "sha2-256", 10)).to.be.eql( + Buffer.from("120a90ea688e275d58056732", "hex") ) }) - it('throws on non implemented func', () => { - expect( - () => multihashing(Buffer.from('beep boop'), 'sha3') - ).to.throw( + it("throws on non implemented func", () => { + expect(() => multihashing(Buffer.from("beep boop"), "sha3")).to.throw( /Unrecognized hash function named:/ ) }) diff --git a/test/node.js b/test/node.js new file mode 100644 index 0000000..0998241 --- /dev/null +++ b/test/node.js @@ -0,0 +1,4 @@ +// TODO: Instead mocha should be passed additional arg +// `--require source-map-support/register` but as things stand now there is +// no way to do it without changes to aegir so we do this instead for now. +require("source-map-support/register") From fe4c5539989ddda58231df94237fb68572a6bb0a Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Thu, 5 Apr 2018 17:01:33 +0200 Subject: [PATCH 2/3] improvements on the types based on review --- src/blake.js | 12 ++++++------ src/index.js | 3 ++- src/sha3.js | 12 +++++++----- src/types.js | 17 ++++++++++++++--- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/blake.js b/src/blake.js index 5796e4a..deff167 100644 --- a/src/blake.js +++ b/src/blake.js @@ -1,8 +1,6 @@ // @flow -"use strict" - import * as blake from "blakejs" -import type { Hash, HashTable, HashBuilder } from "./types" +import type { Hash, HashUpdate, HashTable, HashBuilder } from "./types" import type { Code } from "multihashes/lib/constants" const minB: Code = 0xb201 @@ -28,8 +26,6 @@ const blake2b: BlakeHasher = { digest: blake.blake2bFinal } -blake2b.init(1, 1) - const blake2s: BlakeHasher = { init: blake.blake2sInit, update: blake.blake2sUpdate, @@ -45,6 +41,10 @@ class B2Hash implements Hash { this.ctx = this.hf.init(size, null) } + static new(size, hashFunc): HashUpdate { + return new B2Hash(size, hashFunc) + } + update(buf: Buffer): Hash { if (this.ctx === null) { throw new Error("blake2 context is null. (already called digest?)") @@ -65,7 +65,7 @@ class B2Hash implements Hash { export const addFuncs = (table: HashTable) => { const mkFunc = (size: number, hashFunc: BlakeHasher): HashBuilder => { - return (): Hash => new B2Hash(size, hashFunc) + return (): HashUpdate => B2Hash.new(size, hashFunc) } // I don't like using any here but the only way I could get the types to work here. diff --git a/src/index.js b/src/index.js index 1baa2c3..b10db90 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,8 @@ import * as blake from "./blake" import * as sha3 from "./sha3" import * as crypto from "webcrypto" -const mh = (module.exports = Multihashing) +const mh = Multihashing +export default mh mh.Buffer = Buffer // for browser things diff --git a/src/sha3.js b/src/sha3.js index 7b81b16..0772d2f 100644 --- a/src/sha3.js +++ b/src/sha3.js @@ -1,8 +1,6 @@ // @flow -"use strict" - import * as sha3 from "js-sha3" -import type { Hash, HashTable } from "./types" +import type { Hash, HashTable, HashUpdate } from "./types" const functions = [ [0x14, sha3.sha3_512], @@ -34,6 +32,10 @@ class ShaHash implements Hash { this.input = null } + static new(hashFunc, arg?: number): HashUpdate { + return new ShaHash(hashFunc, arg) + } + update(buf: Buffer): Hash { this.input = buf return this @@ -55,9 +57,9 @@ export const addFuncs = (table: HashTable) => { const fn = info[1] if (info.length === 3) { - table[code] = () => new ShaHash(fn, info[2]) + table[code] = () => ShaHash.new(fn, info[2]) } else { - table[code] = () => new ShaHash(fn) + table[code] = () => ShaHash.new(fn) } } } diff --git a/src/types.js b/src/types.js index e4ea8d0..9dcd4cb 100644 --- a/src/types.js +++ b/src/types.js @@ -1,10 +1,21 @@ // @flow import type { Code } from "multihashes/lib/constants" -export interface Hash { - update(buf: Buffer): Hash; +// We break up the Hash Class into Hash and HashUpdate +// this is a really nice use of types to avoid the user +// calling digest on the hash class before doing an update +// and adding an input. This works by only returning an interface +// that supports update. Once update is called a full hash interface with +// the digest function exposed is available. +// This will only work for a code also using flow. + +export interface Hash extends HashUpdate { digest(): Buffer; } -export type HashBuilder = () => Hash +export interface HashUpdate { + update(buf: Buffer): Hash; +} + +export type HashBuilder = () => HashUpdate export type HashTable = { [Code]: HashBuilder } From e6f7f0e8ec3677f7fa28e62be7a050de71f8148c Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Fri, 6 Apr 2018 10:11:40 +0200 Subject: [PATCH 3/3] remove prettier and use standardjs for linting --- package.json | 11 +---- src/blake.js | 18 ++++---- src/index.js | 43 +++++++++--------- src/sha3.js | 16 +++---- src/types.js | 12 +++-- test/index.spec.js | 111 ++++++++++++++++++++++----------------------- test/node.js | 2 +- 7 files changed, 104 insertions(+), 109 deletions(-) diff --git a/package.json b/package.json index 460c9f9..11ed80f 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "multiple hash functions", "main": "src/index.js", "scripts": { - "lint": "lint-staged && npm run type-check", + "lint": "npm run type-check && aegir lint", "type-check": "flow check", "build": "npm run build:node && BABEL_ENV=umd aegir build", "test": "npm run build:node && aegir test -t node -t browser -t webworker", @@ -21,12 +21,6 @@ "build:node": "npm run build:types && npm run build:lib", "start": "flow-copy-source --watch --verbose src lib & babel --watch --out-dir lib src" }, - "lint-staged": { - "*.js": [ - "prettier --no-semi --write", - "git add" - ] - }, "pre-commit": [ "lint", "test" @@ -58,7 +52,7 @@ "webcrypto": "~0.1.1" }, "devDependencies": { - "aegir": "^12.3.0", + "aegir": "git+https://github.com/ipfs/aegir.git#flow", "babel-preset-flow-node": "^2.0.1", "chai": "^4.1.2", "dirty-chai": "^2.0.1", @@ -66,7 +60,6 @@ "flow-copy-source": "^1.3.0", "lint-staged": "^7.0.2", "pre-commit": "^1.2.2", - "prettier": "^1.11.1", "rollup.config.flow": "^1.0.0", "source-map-support": "^0.5.4" }, diff --git a/src/blake.js b/src/blake.js index deff167..55603de 100644 --- a/src/blake.js +++ b/src/blake.js @@ -1,7 +1,7 @@ // @flow -import * as blake from "blakejs" -import type { Hash, HashUpdate, HashTable, HashBuilder } from "./types" -import type { Code } from "multihashes/lib/constants" +import * as blake from 'blakejs' +import type { Hash, HashUpdate, HashTable, HashBuilder } from './types' +import type { Code } from 'multihashes/lib/constants' const minB: Code = 0xb201 const minS: Code = 0xb241 @@ -36,28 +36,28 @@ class B2Hash implements Hash { ctx: BlakeCtx | null hf: BlakeHasher - constructor(size, hashFunc) { + constructor (size, hashFunc) { this.hf = hashFunc this.ctx = this.hf.init(size, null) } - static new(size, hashFunc): HashUpdate { + static new (size, hashFunc): HashUpdate { return new B2Hash(size, hashFunc) } - update(buf: Buffer): Hash { + update (buf: Buffer): Hash { if (this.ctx === null) { - throw new Error("blake2 context is null. (already called digest?)") + throw new Error('blake2 context is null. (already called digest?)') } this.hf.update(this.ctx, buf) return this } - digest(): Blake2Hash { + digest (): Blake2Hash { const ctx = this.ctx this.ctx = null if (ctx === null) { - throw Error("blake2 context is null. (already called digest?)") + throw Error('blake2 context is null. (already called digest?)') } return Buffer.from(this.hf.digest(ctx)) } diff --git a/src/index.js b/src/index.js index b10db90..5b564d8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,20 +1,19 @@ // @flow -"use strict" -import * as multihash from "multihashes" -import type { Multihash } from "multihashes" -import type { Name, Code } from "multihashes/lib/constants" -import type { HashTable, Hash } from "./types" -import * as blake from "./blake" -import * as sha3 from "./sha3" -import * as crypto from "webcrypto" +import * as multihash from 'multihashes' +import type { Multihash } from 'multihashes' +import type { Name, Code } from 'multihashes/lib/constants' +import type { HashUpdate, HashTable } from './types' +import * as blake from './blake' +import * as sha3 from './sha3' +import * as crypto from 'webcrypto' const mh = Multihashing export default mh mh.Buffer = Buffer // for browser things -function Multihashing( +function Multihashing ( buf: Buffer, func: Name | Code, length: number @@ -25,7 +24,7 @@ function Multihashing( // expose multihash itself, to avoid silly double requires. mh.multihash = multihash -mh.digest = function(buf: Buffer, func: Name | Code, length: ?number): Buffer { +mh.digest = function (buf: Buffer, func: Name | Code, length: ?number): Buffer { let digest = mh .createHash(func) .update(buf) @@ -38,38 +37,40 @@ mh.digest = function(buf: Buffer, func: Name | Code, length: ?number): Buffer { return digest } -mh.createHash = function(func: Name | Code): Hash { +mh.createHash = function (func: Name | Code): HashUpdate { func = multihash.coerceCode(func) if (!mh.functions[func]) { - throw new Error("multihash function " + func + " not yet supported") + throw new Error('multihash function ' + func + ' not yet supported') } return mh.functions[func]() } -mh.verify = function verify(hash: Multihash, buf: Buffer): boolean { +mh.verify = function verify (hash: Multihash, buf: Buffer): boolean { const decoded = multihash.decode(hash) const encoded = mh(buf, decoded.name, decoded.length) return encoded.equals(hash) } -mh.functions = { +/* eslint-disable no-useless-computed-key */ +mh.functions = ({ [0x11]: gsha1, [0x12]: gsha2256, [0x13]: gsha2512 -} +}: HashTable) +/* eslint-enable no-useless-computed-key */ blake.addFuncs(mh.functions) sha3.addFuncs(mh.functions) -function gsha1(): Hash { - return crypto.createHash("sha1") +function gsha1 (): HashUpdate { + return crypto.createHash('sha1') } -function gsha2256(): Hash { - return crypto.createHash("sha256") +function gsha2256 (): HashUpdate { + return crypto.createHash('sha256') } -function gsha2512(): Hash { - return crypto.createHash("sha512") +function gsha2512 (): HashUpdate { + return crypto.createHash('sha512') } diff --git a/src/sha3.js b/src/sha3.js index 0772d2f..2d673cb 100644 --- a/src/sha3.js +++ b/src/sha3.js @@ -1,6 +1,6 @@ // @flow -import * as sha3 from "js-sha3" -import type { Hash, HashTable, HashUpdate } from "./types" +import * as sha3 from 'js-sha3' +import type { Hash, HashTable, HashUpdate } from './types' const functions = [ [0x14, sha3.sha3_512], @@ -24,7 +24,7 @@ class ShaHash implements Hash { input: Buffer | null arg: number - constructor(hashFunc, arg?: number) { + constructor (hashFunc, arg?: number) { this.hf = hashFunc if (arg) { this.arg = arg @@ -32,22 +32,22 @@ class ShaHash implements Hash { this.input = null } - static new(hashFunc, arg?: number): HashUpdate { + static new (hashFunc, arg?: number): HashUpdate { return new ShaHash(hashFunc, arg) } - update(buf: Buffer): Hash { + update (buf: Buffer): Hash { this.input = buf return this } - digest(): Sha3Hash { + digest (): Sha3Hash { if (!this.input) { - throw Error("Missing an input to hash") + throw Error('Missing an input to hash') } const input = this.input const arg = this.arg - return Buffer.from(this.hf(input, arg), "hex") + return Buffer.from(this.hf(input, arg), 'hex') } } diff --git a/src/types.js b/src/types.js index 9dcd4cb..973bd99 100644 --- a/src/types.js +++ b/src/types.js @@ -1,5 +1,5 @@ // @flow -import type { Code } from "multihashes/lib/constants" +import type { Code } from 'multihashes/lib/constants' // We break up the Hash Class into Hash and HashUpdate // this is a really nice use of types to avoid the user @@ -9,13 +9,15 @@ import type { Code } from "multihashes/lib/constants" // the digest function exposed is available. // This will only work for a code also using flow. -export interface Hash extends HashUpdate { - digest(): Buffer; -} - +/* eslint-disable no-use-before-define */ export interface HashUpdate { update(buf: Buffer): Hash; } +export interface Hash extends HashUpdate { + digest(): Buffer; +} +/* eslint-enable no-use-before-define */ + export type HashBuilder = () => HashUpdate export type HashTable = { [Code]: HashBuilder } diff --git a/test/index.spec.js b/test/index.spec.js index b8bb154..5737474 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,119 +1,118 @@ /* eslint-env mocha */ -"use strict" -const chai = require("chai") -const dirtyChai = require("dirty-chai") +const chai = require('chai') +const dirtyChai = require('dirty-chai') chai.use(dirtyChai) const expect = chai.expect -const multihashing = require("../lib") +const multihashing = require('../lib') const tests = { - sha1: [["beep boop", "11147c8357577f51d4f0a8d393aa1aaafb28863d9421"]], - "sha2-256": [ + sha1: [['beep boop', '11147c8357577f51d4f0a8d393aa1aaafb28863d9421']], + 'sha2-256': [ [ - "beep boop", - "122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c" + 'beep boop', + '122090ea688e275d580567325032492b597bc77221c62493e76330b85ddda191ef7c' ] ], - "sha2-512": [ + 'sha2-512': [ [ - "beep boop", - "134014f301f31be243f34c5668937883771fa381002f1aaa5f31b3f78e500b66ff2f4f8ea5e3c9f5a61bd073e2452c480484b02e030fb239315a2577f7ae156af177" + 'beep boop', + '134014f301f31be243f34c5668937883771fa381002f1aaa5f31b3f78e500b66ff2f4f8ea5e3c9f5a61bd073e2452c480484b02e030fb239315a2577f7ae156af177' ] ], - "blake2b-512": [ + 'blake2b-512': [ [ - "beep boop", - "c0e402400eac6255ba822373a0948122b8d295008419a8ab27842ee0d70eca39855621463c03ec75ac3610aacfdff89fa989d8d61fc00450148f289eb5b12ad1a954f659" + 'beep boop', + 'c0e402400eac6255ba822373a0948122b8d295008419a8ab27842ee0d70eca39855621463c03ec75ac3610aacfdff89fa989d8d61fc00450148f289eb5b12ad1a954f659' ] ], - "blake2b-160": [ - ["beep boop", "94e40214fe303247293e54e0a7ea48f9408ca68b36b08442"] + 'blake2b-160': [ + ['beep boop', '94e40214fe303247293e54e0a7ea48f9408ca68b36b08442'] ], - "blake2s-256": [ + 'blake2s-256': [ [ - "beep boop", - "e0e402204542eaca484e4311def8af74b546edd7fceb49eeb3cdcfd8a4a72ed0dc81d4c0" + 'beep boop', + 'e0e402204542eaca484e4311def8af74b546edd7fceb49eeb3cdcfd8a4a72ed0dc81d4c0' ] ], - "blake2s-40": [["beep boop", "c5e402059ada01bb57"]], - "sha3-512": [ + 'blake2s-40': [['beep boop', 'c5e402059ada01bb57']], + 'sha3-512': [ [ - "beep bop", - "144038122bf54c0e1eeff013e9b8c735af7c08ff8a7bb2b55b5abe9d97f9653e19f388cd9719ffb4ab8ccb9330a1fd27929b0a9ee6d7b8b9884c6f787f11088219bc" + 'beep bop', + '144038122bf54c0e1eeff013e9b8c735af7c08ff8a7bb2b55b5abe9d97f9653e19f388cd9719ffb4ab8ccb9330a1fd27929b0a9ee6d7b8b9884c6f787f11088219bc' ] ], - "sha3-384": [ + 'sha3-384': [ [ - "beep bop", - "15302f0456d702d4cafa23c091f8da2dc878b1536fd592c47c2d239f5de67f0a306f36e0197dbbf1c5409292aa92e326b16e" + 'beep bop', + '15302f0456d702d4cafa23c091f8da2dc878b1536fd592c47c2d239f5de67f0a306f36e0197dbbf1c5409292aa92e326b16e' ] ], - "sha3-256": [ + 'sha3-256': [ [ - "beep bop", - "16204de761fac0b163270f59056e1c5d1038348fcb960c03610bde24565473600dfe" + 'beep bop', + '16204de761fac0b163270f59056e1c5d1038348fcb960c03610bde24565473600dfe' ] ], - "sha3-224": [ - ["beep bop", "171cda7cce25c2f6248dc88a2fdfca56bb97bf39b100089cacfdf68b7b50"] + 'sha3-224': [ + ['beep bop', '171cda7cce25c2f6248dc88a2fdfca56bb97bf39b100089cacfdf68b7b50'] ], - "shake-128": [ + 'shake-128': [ [ - "beep boop", - "18205fe422311f770743c2e0d86bcca092111cbce85487212829739c3c3723776e5a" + 'beep boop', + '18205fe422311f770743c2e0d86bcca092111cbce85487212829739c3c3723776e5a' ] ], - "shake-256": [ + 'shake-256': [ [ - "beep boop", - "194059feb5565e4f924baef74708649fed376d63948a862322ed763ecf093b63b38b0955908c099c63dda73ee469c31b1456cec95e325bd868d0ce0c0135f5a54411" + 'beep boop', + '194059feb5565e4f924baef74708649fed376d63948a862322ed763ecf093b63b38b0955908c099c63dda73ee469c31b1456cec95e325bd868d0ce0c0135f5a54411' ] ], - "keccak-224": [ - ["beep bop", "1a1c45f2663794752c0a2292985b476a6aec407cfd78ad6f14f56d7060d9"] + 'keccak-224': [ + ['beep bop', '1a1c45f2663794752c0a2292985b476a6aec407cfd78ad6f14f56d7060d9'] ], - "keccak-256": [ + 'keccak-256': [ [ - "beep bop", - "1b209e7c2fee63c4065cbaa989bd2655a288f877aa788484fb0640d125417796b5e9" + 'beep bop', + '1b209e7c2fee63c4065cbaa989bd2655a288f877aa788484fb0640d125417796b5e9' ] ], - "keccak-384": [ + 'keccak-384': [ [ - "beep bop", - "1c305a1da4b6e329884e88b66d82961d6518d9cec66eae6ff6900344a30a742a044b6eb584ab6e8a1c609e04f2f235f5cab3" + 'beep bop', + '1c305a1da4b6e329884e88b66d82961d6518d9cec66eae6ff6900344a30a742a044b6eb584ab6e8a1c609e04f2f235f5cab3' ] ], - "keccak-512": [ + 'keccak-512': [ [ - "beep bop", - "1d403c22f68c98a6c8ea9fa7819721fba90f905d3c29390d4a94fefc4f8348ed04829a7521b44af4aeea707b32fe63e28322666ae26a59feb3493fafa11873383f6c" + 'beep bop', + '1d403c22f68c98a6c8ea9fa7819721fba90f905d3c29390d4a94fefc4f8348ed04829a7521b44af4aeea707b32fe63e28322666ae26a59feb3493fafa11873383f6c' ] ] } -describe("multihashing", () => { +describe('multihashing', () => { for (const algo in tests) { it(algo, () => { for (const test of tests[algo]) { const input = Buffer.from(test[0]) - const output = Buffer.from(test[1], "hex") + const output = Buffer.from(test[1], 'hex') expect(multihashing(input, algo)).to.be.eql(output) expect(multihashing.verify(output, input)).to.be.eql(true) } }) } - it("cuts the length", () => { - const buf = Buffer.from("beep boop") - expect(multihashing(buf, "sha2-256", 10)).to.be.eql( - Buffer.from("120a90ea688e275d58056732", "hex") + it('cuts the length', () => { + const buf = Buffer.from('beep boop') + expect(multihashing(buf, 'sha2-256', 10)).to.be.eql( + Buffer.from('120a90ea688e275d58056732', 'hex') ) }) - it("throws on non implemented func", () => { - expect(() => multihashing(Buffer.from("beep boop"), "sha3")).to.throw( + it('throws on non implemented func', () => { + expect(() => multihashing(Buffer.from('beep boop'), 'sha3')).to.throw( /Unrecognized hash function named:/ ) }) diff --git a/test/node.js b/test/node.js index 0998241..f58bab2 100644 --- a/test/node.js +++ b/test/node.js @@ -1,4 +1,4 @@ // TODO: Instead mocha should be passed additional arg // `--require source-map-support/register` but as things stand now there is // no way to do it without changes to aegir so we do this instead for now. -require("source-map-support/register") +require('source-map-support/register')