fix: add buffer and update deps (#25)

* fix: add buffer and update deps

update secp256k1 dep and fix code
use multibase to encode b58
avoid un-necessary circular dependency no libp2p-crypto
use  only sha256 from multihashing-async

* Update src/crypto.js

Co-Authored-By: Jacob Heun <jacobheun@gmail.com>

* chore: remove commitlint from CI

Co-authored-by: Jacob Heun <jacobheun@gmail.com>
This commit is contained in:
Hugo Dias 2020-03-17 10:59:23 +00:00 committed by GitHub
parent ae109d46f7
commit 35f196ea4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 36 deletions

1
.gitignore vendored
View File

@ -32,6 +32,7 @@ build
node_modules node_modules
dist dist
docs
package-lock.json package-lock.json
yarn.lock yarn.lock
.vscode .vscode

View File

@ -10,6 +10,7 @@ stages:
node_js: node_js:
- '10' - '10'
- '12'
os: os:
- linux - linux
@ -23,7 +24,6 @@ jobs:
include: include:
- stage: check - stage: check
script: script:
- npx aegir commitlint --travis
- npx aegir dep-check - npx aegir dep-check
- npm run lint - npm run lint

View File

@ -4,9 +4,6 @@
"description": "Support for secp256k1 keys in libp2p-crypto", "description": "Support for secp256k1 keys in libp2p-crypto",
"leadMaintainer": "Friedel Ziegelmayer <dignifiedquire@gmail.com>", "leadMaintainer": "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
"main": "src/index.js", "main": "src/index.js",
"browser": {
"secp256k1": "secp256k1/js"
},
"scripts": { "scripts": {
"lint": "aegir lint", "lint": "aegir lint",
"build": "aegir build", "build": "aegir build",
@ -27,18 +24,19 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bs58": "^4.0.1", "buffer": "^5.5.0",
"multihashing-async": "^0.8.0", "is-typedarray": "^1.0.0",
"nodeify": "^1.0.1", "multibase": "^0.6.0",
"safe-buffer": "^5.1.2", "multihashing-async": "^0.8.1",
"secp256k1": "^3.6.2" "secp256k1": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"aegir": "^21.0.2", "aegir": "^21.0.2",
"benchmark": "^2.1.4", "benchmark": "^2.1.4",
"chai": "^4.2.0", "chai": "^4.2.0",
"dirty-chai": "^2.0.1", "dirty-chai": "^2.0.1",
"libp2p-crypto": "~0.17.2" "libp2p-crypto": "~0.17.2",
"protons": "^1.1.0"
}, },
"engines": { "engines": {
"node": ">=6.0.0", "node": ">=6.0.0",

View File

@ -1,10 +1,26 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
var isTypedArray = require('is-typedarray').strict
const secp256k1 = require('secp256k1') const secp256k1 = require('secp256k1')
const multihashing = require('multihashing-async') const sha = require('multihashing-async/src/sha')
const HASH_ALGORITHM = 'sha2-256' const HASH_ALGORITHM = 'sha2-256'
function typedArrayTobuffer (arr) {
if (isTypedArray(arr)) {
// To avoid a copy, use the typed array's underlying ArrayBuffer to back new Buffer
var buf = Buffer.from(arr.buffer)
if (arr.byteLength !== arr.buffer.byteLength) {
// Respect the "view", i.e. byteOffset and byteLength, without doing a copy
buf = buf.slice(arr.byteOffset, arr.byteOffset + arr.byteLength)
}
return buf
} else {
// Pass through all other types to `Buffer.from`
return Buffer.from(arr)
}
}
module.exports = (randomBytes) => { module.exports = (randomBytes) => {
const privateKeyLength = 32 const privateKeyLength = 32
@ -17,26 +33,26 @@ module.exports = (randomBytes) => {
} }
async function hashAndSign (key, msg) { async function hashAndSign (key, msg) {
const digest = await multihashing.digest(msg, HASH_ALGORITHM) const digest = await sha.digest(msg, HASH_ALGORITHM)
const sig = secp256k1.sign(digest, key) const sig = secp256k1.ecdsaSign(digest, key)
return secp256k1.signatureExport(sig.signature) return typedArrayTobuffer(secp256k1.signatureExport(sig.signature))
} }
async function hashAndVerify (key, sig, msg) { async function hashAndVerify (key, sig, msg) {
const digest = await multihashing.digest(msg, HASH_ALGORITHM) const digest = await sha.digest(msg, HASH_ALGORITHM)
sig = secp256k1.signatureImport(sig) sig = typedArrayTobuffer(secp256k1.signatureImport(sig))
return secp256k1.verify(digest, sig, key) return secp256k1.ecdsaVerify(sig, digest, key)
} }
function compressPublicKey (key) { function compressPublicKey (key) {
if (!secp256k1.publicKeyVerify(key)) { if (!secp256k1.publicKeyVerify(key)) {
throw new Error('Invalid public key') throw new Error('Invalid public key')
} }
return secp256k1.publicKeyConvert(key, true) return typedArrayTobuffer(secp256k1.publicKeyConvert(key, true))
} }
function decompressPublicKey (key) { function decompressPublicKey (key) {
return secp256k1.publicKeyConvert(key, false) return typedArrayTobuffer(secp256k1.publicKeyConvert(key, false))
} }
function validatePrivateKey (key) { function validatePrivateKey (key) {
@ -53,7 +69,7 @@ module.exports = (randomBytes) => {
function computePublicKey (privateKey) { function computePublicKey (privateKey) {
validatePrivateKey(privateKey) validatePrivateKey(privateKey)
return secp256k1.publicKeyCreate(privateKey) return typedArrayTobuffer(secp256k1.publicKeyCreate(privateKey))
} }
return { return {

View File

@ -1,7 +1,7 @@
'use strict' 'use strict'
const bs58 = require('bs58') const multibase = require('multibase')
const multihashing = require('multihashing-async') const sha = require('multihashing-async/src/sha')
module.exports = (keysProtobuf, randomBytes, crypto) => { module.exports = (keysProtobuf, randomBytes, crypto) => {
crypto = crypto || require('./crypto')(randomBytes) crypto = crypto || require('./crypto')(randomBytes)
@ -32,7 +32,7 @@ module.exports = (keysProtobuf, randomBytes, crypto) => {
} }
hash () { hash () {
return multihashing(this.bytes, 'sha2-256') return sha.multihashing(this.bytes, 'sha2-256')
} }
} }
@ -68,7 +68,7 @@ module.exports = (keysProtobuf, randomBytes, crypto) => {
} }
hash () { hash () {
return multihashing(this.bytes, 'sha2-256') return sha.multihashing(this.bytes, 'sha2-256')
} }
/** /**
@ -83,8 +83,7 @@ module.exports = (keysProtobuf, randomBytes, crypto) => {
*/ */
async id () { async id () {
const hash = await this.public.hash() const hash = await this.public.hash()
return multibase.encode('base58btc', hash).toString().slice(1)
return bs58.encode(hash)
} }
} }

View File

@ -1,6 +1,6 @@
'use strict' 'use strict'
const Buffer = require('safe-buffer').Buffer const { Buffer } = require('buffer')
// The keypair and signature below were generated in a gore repl session (https://github.com/motemen/gore) // The keypair and signature below were generated in a gore repl session (https://github.com/motemen/gore)
// using the secp256k1 fork of go-libp2p-crypto by github user @vyzo // using the secp256k1 fork of go-libp2p-crypto by github user @vyzo

View File

@ -1,14 +1,14 @@
/* eslint-env mocha */ /* eslint-env mocha */
'use strict' 'use strict'
const { Buffer } = require('buffer')
const chai = require('chai') const chai = require('chai')
const dirtyChai = require('dirty-chai') const dirtyChai = require('dirty-chai')
const expect = chai.expect const expect = chai.expect
chai.use(dirtyChai) chai.use(dirtyChai)
const protobuf = require('protons')
const libp2pCrypto = require('libp2p-crypto') const keysPBM = protobuf(require('libp2p-crypto/src/keys/keys.proto'))
const keysPBM = libp2pCrypto.keys.keysPBM const randomBytes = require('libp2p-crypto/src/random-bytes')
const randomBytes = libp2pCrypto.randomBytes
const crypto = require('../src/crypto')(randomBytes) const crypto = require('../src/crypto')(randomBytes)
describe('secp256k1 keys', () => { describe('secp256k1 keys', () => {
@ -136,7 +136,7 @@ describe('handles generation of invalid key', () => {
try { try {
await secp256k1.generateKeyPair() await secp256k1.generateKeyPair()
} catch (err) { } catch (err) {
return expect(err.message).to.equal('Invalid private key') return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
} }
throw new Error('Expected error to be thrown') throw new Error('Expected error to be thrown')
}) })
@ -182,7 +182,7 @@ describe('crypto functions', () => {
try { try {
await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello')) await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
} catch (err) { } catch (err) {
return expect(err.message).to.equal('private key length is invalid') return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
} }
throw new Error('Expected error to be thrown') throw new Error('Expected error to be thrown')
}) })
@ -202,7 +202,7 @@ describe('crypto functions', () => {
try { try {
await crypto.hashAndVerify(pubKey, Buffer.from('invalid-sig'), Buffer.from('hello')) await crypto.hashAndVerify(pubKey, Buffer.from('invalid-sig'), Buffer.from('hello'))
} catch (err) { } catch (err) {
return expect(err.message).to.equal('couldn\'t parse DER signature') return expect(err.message).to.equal('Signature could not be parsed')
} }
throw new Error('Expected error to be thrown') throw new Error('Expected error to be thrown')
}) })
@ -211,7 +211,7 @@ describe('crypto functions', () => {
try { try {
await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello')) await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
} catch (err) { } catch (err) {
return expect(err.message).to.equal('private key length is invalid') return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
} }
throw new Error('Expected error to be thrown') throw new Error('Expected error to be thrown')
}) })