Skip to content
This repository has been archived by the owner on Aug 24, 2021. It is now read-only.

Commit

Permalink
fix: replace node buffers with uint8arrays (#78)
Browse files Browse the repository at this point in the history
Removes node `Buffer`s in favour of `Uint8Array`s.

BREAKING CHANGE

- Where node `Buffer`s were used, now `Uint8Array`s are
  • Loading branch information
achingbrain authored Aug 3, 2020
1 parent 10c82bc commit eb612f3
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 111 deletions.
65 changes: 29 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
# js-multihashing-async
# js-multihashing-async <!-- omit in toc -->

[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs)
[![Coverage Status](https://coveralls.io/repos/github/multiformats/js-multihashing-async/badge.svg?branch=master)](https://coveralls.io/github/multiformats/js-multihashing-async?branch=master)
[![Travis CI](https://flat.badgen.net/travis/ipfs/js-multihashing-async)](https://travis-ci.com/ipfs/js-multihashing-async)
[![Dependency Status](https://david-dm.org/multiformats/js-multihashing-async.svg?style=flat-square)](https://david-dm.org/multiformats/js-multihashing-async)
[![Dependency Status](https://david-dm.org/multiformats/js-multihashing-async.svg?style=flat-square)](https://david-dm.org/multiformats/js-multihashing-async)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
[![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)

> Use all the functions in [multihash](https://github.com/multiformats/multihash).
## Lead Maintainer
## Lead Maintainer <!-- omit in toc -->

[Hugo Dias](https://github.com/hugomrdias)

### Notice
> This module is moving to async/await starting from 0.7.0.
### Notice <!-- omit in toc -->
> This module is moving to async/await starting from 0.7.0.
> The last minor version to support callbacks is 0.6.0, any backports will merged to the branch `callbacks` and released under `>0.6.0 <0.7.0`.
#### Wait, why, how is this different from Node `crypto`?
#### Wait, why, how is this different from Node `crypto`? <!-- omit in toc -->

This module just makes working with multihashes a bit nicer.
[js-multihash](//github.com/multiformats/js-multihash) is only for
Expand All @@ -29,21 +29,18 @@ It currently uses `crypto` and [`sha3`](https://github.com/phusion/node-sha3) in
In the browser [`webcrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
and [`browserify-sha3`](https://github.com/wanderer/browserify-sha3) are used.

## Table of Contents

* [Table of Contents](#table-of-contents)
* [Install](#install)
+ [In Node.js through npm](#in-nodejs-through-npm)
+ [Use in a browser with browserify, webpack or any other bundler](#use-in-a-browser-with-browserify-webpack-or-any-other-bundler)
+ [Use in a browser Using a script tag](#use-in-a-browser-using-a-script-tag)
- [Gotchas](#gotchas)
* [Usage](#usage)
* [Examples](#examples)
+ [Multihash output](#multihash-output)
* [API](#api)
* [Maintainers](#maintainers)
* [Contribute](#contribute)
* [License](#license)
## Table of Contents <!-- omit in toc -->

- [Install](#install)
- [In Node.js through npm](#in-nodejs-through-npm)
- [Use in a browser with browserify, webpack or any other bundler](#use-in-a-browser-with-browserify-webpack-or-any-other-bundler)
- [Use in a browser Using a script tag](#use-in-a-browser-using-a-script-tag)
- [Usage](#usage)
- [Examples](#examples)
- [Multihash output](#multihash-output)
- [API](#api)
- [Contribute](#contribute)
- [License](#license)

## Install

Expand Down Expand Up @@ -78,24 +75,20 @@ available in the global namespace.
<script src="https://unpkg.com/multihashing-async/dist/index.js"></script>
```

#### Gotchas

You will need to use Node.js `Buffer` API compatible, if you are running inside the browser, you can access it by `multihashing.Buffer` or you can install Feross's [Buffer](https://github.com/feross/buffer).

## Usage

```js
const multihashing = require('multihashing-async')
const buf = Buffer.from('beep boop')
const bytes = new TextEncoder().encode('beep boop')

const mh = await multihashing(buf, 'sha1')
const mh = await multihashing(bytes, 'sha1')

// Use `.digest(...)` if you want only the hash digest (drops the prefix indicating the hash type).
const digest = await multihashing.digest(buf, 'sha1')
const digest = await multihashing.digest(bytes, 'sha1')

// Use `.createHash(...)` for the raw hash functions
const hash = multihashing.createHash('sha1')
const digest = await hash(buf)
const digest = await hash(bytes)
```

## Examples
Expand All @@ -104,19 +97,19 @@ const digest = await hash(buf)

```js
const multihashing = require('multihashing-async')
const buf = Buffer.from('beep boop')
const bytes = new TextEncoder().encode('beep boop')

const mh = await multihashing(buf, 'sha1')
const mh = await multihashing(bytes, 'sha1')
console.log(mh)
// => <Buffer 11 14 7c 83 57 57 7f 51 d4 f0 a8 d3 93 aa 1a aa fb 28 86 3d 94 21>
// => <Uint8Array 11 14 7c 83 57 57 7f 51 d4 f0 a8 d3 93 aa 1a aa fb 28 86 3d 94 21>

const mh = await multihashing(buf, 'sha2-256')
const mh = await multihashing(bytes, 'sha2-256')
console.log(mh)
// => <Buffer 12 20 90 ea 68 8e 27 5d 58 05 67 32 50 32 49 2b 59 7b c7 72 21 c6 24 93 e7 63 30 b8 5d dd a1 91 ef 7c>
// => <Uint8Array 12 20 90 ea 68 8e 27 5d 58 05 67 32 50 32 49 2b 59 7b c7 72 21 c6 24 93 e7 63 30 b8 5d dd a1 91 ef 7c>

const mh = await multihashing(buf, 'sha2-512')
const mh = await multihashing(bytes, 'sha2-512')
console.log(mh)
// => <Buffer 13 40 14 f3 01 f3 1b e2 43 f3 4c 56 68 93 78 83 77 1f a3 81 00 2f 1a aa 5f 31 b3 f7 8e 50 0b 66 ff 2f 4f 8e a5 e3 c9 f5 a6 1b d0 73 e2 45 2c 48 04 84 b0 ...>
// => <Uint8Array 13 40 14 f3 01 f3 1b e2 43 f3 4c 56 68 93 78 83 77 1f a3 81 00 2f 1a aa 5f 31 b3 f7 8e 50 0b 66 ff 2f 4f 8e a5 e3 c9 f5 a6 1b d0 73 e2 45 2c 48 04 84 b0 ...>
```

## API
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const algs = [

algs.forEach((alg) => {
suite.add(alg, async function (d) {
const buf = Buffer.alloc(10 * 1024)
const buf = new Uint8Array(10 * 1024)
buf.fill(Math.ceil(Math.random() * 100))
const res = await multihashing(buf, alg)
list.push(res)
Expand Down
14 changes: 7 additions & 7 deletions example.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const multihashing = require('multihashing-async')
const buf = Buffer.from('beep boop')
const bytes = new TextEncoder().encode('beep boop')

function print (err, mh) {
if (err) {
Expand All @@ -10,11 +10,11 @@ function print (err, mh) {
// eslint-disable-next-line
console.log(mh)
}
multihashing(buf, 'sha1', print)
// => <Buffer 11 14 7c 83 57 57 7f 51 d4 f0 a8 d3 93 aa 1a aa fb 28 86 3d 94 21>
multihashing(bytes, 'sha1', print)
// => <Uint8Array 11 14 7c 83 57 57 7f 51 d4 f0 a8 d3 93 aa 1a aa fb 28 86 3d 94 21>

multihashing(buf, 'sha2-256', print)
// => <Buffer 12 20 90 ea 68 8e 27 5d 58 05 67 32 50 32 49 2b 59 7b c7 72 21 c6 24 93 e7 63 30 b8 5d dd a1 91 ef 7c>
multihashing(bytes, 'sha2-256', print)
// => <Uint8Array 12 20 90 ea 68 8e 27 5d 58 05 67 32 50 32 49 2b 59 7b c7 72 21 c6 24 93 e7 63 30 b8 5d dd a1 91 ef 7c>

multihashing(buf, 'sha2-512', print)
// => <Buffer 13 40 14 f3 01 f3 1b e2 43 f3 4c 56 68 93 78 83 77 1f a3 81 00 2f 1a aa 5f 31 b3 f7 8e 50 0b 66 ff 2f 4f 8e a5 e3 c9 f5 a6 1b d0 73 e2 45 2c 48 04 84 b0 ...>
multihashing(bytes, 'sha2-512', print)
// => <Uint8Array 13 40 14 f3 01 f3 1b e2 43 f3 4c 56 68 93 78 83 77 1f a3 81 00 2f 1a aa 5f 31 b3 f7 8e 50 0b 66 ff 2f 4f 8e a5 e3 c9 f5 a6 1b d0 73 e2 45 2c 48 04 84 b0 ...>
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,15 @@
},
"dependencies": {
"blakejs": "^1.1.0",
"buffer": "^5.4.3",
"err-code": "^2.0.0",
"js-sha3": "^0.8.0",
"multihashes": "^1.0.1",
"murmurhash3js-revisited": "^3.0.0"
"multihashes": "^2.0.0",
"murmurhash3js-revisited": "^3.0.0",
"uint8arrays": "^1.0.0"
},
"devDependencies": {
"aegir": "^25.0.0",
"benchmark": "^2.1.4",
"chai": "^4.1.2",
"dirty-chai": "^2.0.1",
"sinon": "^9.0.2"
},
"engines": {
Expand Down
3 changes: 1 addition & 2 deletions src/blake.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict'

const { Buffer } = require('buffer')
const blake = require('blakejs')

const minB = 0xb201
Expand All @@ -25,7 +24,7 @@ const blake2s = {
const makeB2Hash = (size, hf) => async (data) => {
const ctx = hf.init(size, null)
hf.update(ctx, data)
return Buffer.from(hf.digest(ctx))
return hf.digest(ctx)
}

module.exports = (table) => {
Expand Down
26 changes: 13 additions & 13 deletions src/crypto.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict'

const { Buffer } = require('buffer')
const sha3 = require('js-sha3')
const mur = require('murmurhash3js-revisited')
const { factory: sha } = require('./sha')
const { fromNumberTo32BitBuf } = require('./utils')
const uint8ArrayFromString = require('uint8arrays/from-string')

// Note that although this function doesn't do any asynchronous work, we mark
// the function as async because it must return a Promise to match the API
Expand All @@ -13,27 +13,27 @@ const { fromNumberTo32BitBuf } = require('./utils')
const hash = (algorithm) => async (data) => {
switch (algorithm) {
case 'sha3-224':
return Buffer.from(sha3.sha3_224.arrayBuffer(data))
return new Uint8Array(sha3.sha3_224.arrayBuffer(data))
case 'sha3-256':
return Buffer.from(sha3.sha3_256.arrayBuffer(data))
return new Uint8Array(sha3.sha3_256.arrayBuffer(data))
case 'sha3-384':
return Buffer.from(sha3.sha3_384.arrayBuffer(data))
return new Uint8Array(sha3.sha3_384.arrayBuffer(data))
case 'sha3-512':
return Buffer.from(sha3.sha3_512.arrayBuffer(data))
return new Uint8Array(sha3.sha3_512.arrayBuffer(data))
case 'shake-128':
return Buffer.from(sha3.shake128.create(128).update(data).arrayBuffer())
return new Uint8Array(sha3.shake128.create(128).update(data).arrayBuffer())
case 'shake-256':
return Buffer.from(sha3.shake256.create(256).update(data).arrayBuffer())
return new Uint8Array(sha3.shake256.create(256).update(data).arrayBuffer())
case 'keccak-224':
return Buffer.from(sha3.keccak224.arrayBuffer(data))
return new Uint8Array(sha3.keccak224.arrayBuffer(data))
case 'keccak-256':
return Buffer.from(sha3.keccak256.arrayBuffer(data))
return new Uint8Array(sha3.keccak256.arrayBuffer(data))
case 'keccak-384':
return Buffer.from(sha3.keccak384.arrayBuffer(data))
return new Uint8Array(sha3.keccak384.arrayBuffer(data))
case 'keccak-512':
return Buffer.from(sha3.keccak512.arrayBuffer(data))
return new Uint8Array(sha3.keccak512.arrayBuffer(data))
case 'murmur3-128':
return Buffer.from(mur.x64.hash128(data), 'hex')
return uint8ArrayFromString(mur.x64.hash128(data), 'base16')
case 'murmur3-32':
return fromNumberTo32BitBuf(mur.x86.hash32(data))

Expand All @@ -42,7 +42,7 @@ const hash = (algorithm) => async (data) => {
}
}

const identity = data => Buffer.from(data)
const identity = data => data

module.exports = {
identity,
Expand Down
19 changes: 6 additions & 13 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
'use strict'

const { Buffer } = require('buffer')
const errcode = require('err-code')
const multihash = require('multihashes')
const crypto = require('./crypto')
const equals = require('uint8arrays/equals')

/**
* Hash the given `buf` using the algorithm specified by `alg`.
* @param {Buffer} buf - The value to hash.
* @param {Uint8Array} buf - The value to hash.
* @param {number|string} alg - The algorithm to use eg 'sha1'
* @param {number} [length] - Optionally trim the result to this length.
* @returns {Promise<Buffer>}
* @returns {Promise<Uint8Array>}
*/
async function Multihashing (buf, alg, length) {
const digest = await Multihashing.digest(buf, alg, length)
return multihash.encode(digest, alg, length)
}

/**
* The `buffer` module for easy use in the browser.
*
* @type {Buffer}
*/
Multihashing.Buffer = Buffer // for browser things

/**
* Expose multihash itself, to avoid silly double requires.
*/
Multihashing.multihash = multihash

/**
* @param {Buffer} buf - The value to hash.
* @param {Uint8Array} buf - The value to hash.
* @param {number|string} alg - The algorithm to use eg 'sha1'
* @param {number} [length] - Optionally trim the result to this length.
* @returns {Promise<Buffer>}
* @returns {Promise<Uint8Array>}
*/
Multihashing.digest = async (buf, alg, length) => {
const hash = Multihashing.createHash(alg)
Expand Down Expand Up @@ -108,7 +101,7 @@ crypto.addBlake(Multihashing.functions)
Multihashing.validate = async (buf, hash) => {
const newHash = await Multihashing(buf, multihash.decode(hash).name)

return Buffer.compare(hash, newHash) === 0
return equals(hash, newHash)
}

module.exports = Multihashing
9 changes: 4 additions & 5 deletions src/sha.browser.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable require-await */
'use strict'

const { Buffer } = require('buffer')
const multihash = require('multihashes')

const crypto = self.crypto || self.msCrypto
Expand All @@ -14,14 +13,14 @@ const digest = async (data, alg) => {
}
switch (alg) {
case 'sha1':
return Buffer.from(await crypto.subtle.digest({ name: 'SHA-1' }, data))
return new Uint8Array(await crypto.subtle.digest({ name: 'SHA-1' }, data))
case 'sha2-256':
return Buffer.from(await crypto.subtle.digest({ name: 'SHA-256' }, data))
return new Uint8Array(await crypto.subtle.digest({ name: 'SHA-256' }, data))
case 'sha2-512':
return Buffer.from(await crypto.subtle.digest({ name: 'SHA-512' }, data))
return new Uint8Array(await crypto.subtle.digest({ name: 'SHA-512' }, data))
case 'dbl-sha2-256': {
const d = await crypto.subtle.digest({ name: 'SHA-256' }, data)
return Buffer.from(await crypto.subtle.digest({ name: 'SHA-256' }, d))
return new Uint8Array(await crypto.subtle.digest({ name: 'SHA-256' }, d))
}
default:
throw new Error(`${alg} is not a supported algorithm`)
Expand Down
6 changes: 2 additions & 4 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
'use strict'

const { Buffer } = require('buffer')

const fromNumberTo32BitBuf = (number) => {
const bytes = new Array(4)
const bytes = new Uint8Array(4)

for (let i = 0; i < 4; i++) {
bytes[i] = number & 0xff
number = number >> 8
}

return Buffer.from(bytes)
return bytes
}

module.exports = {
Expand Down
Loading

0 comments on commit eb612f3

Please sign in to comment.