diff --git a/package.json b/package.json
index 484bed6..143070f 100644
--- a/package.json
+++ b/package.json
@@ -33,20 +33,22 @@
"IPFS",
"libp2p",
"crypto",
- "rsa"
+ "rsa",
+ "secp256k1"
],
"license": "MIT",
"dependencies": {
"buffer": "^5.5.0",
"err-code": "^2.0.0",
+ "is-typedarray": "^1.0.0",
"iso-random-stream": "^1.1.0",
"keypair": "^1.0.1",
- "libp2p-crypto-secp256k1": "^0.4.2",
"multibase": "^0.7.0",
"multihashing-async": "^0.8.1",
"node-forge": "~0.9.1",
"pem-jwk": "^2.0.0",
"protons": "^1.0.1",
+ "secp256k1": "^4.0.0",
"ursa-optional": "~0.10.1"
},
"devDependencies": {
diff --git a/secp256k1/.gitignore b/secp256k1/.gitignore
deleted file mode 100644
index f99b5ca..0000000
--- a/secp256k1/.gitignore
+++ /dev/null
@@ -1,38 +0,0 @@
-**/node_modules/
-**/*.log
-test/repo-tests*
-
-# Logs
-logs
-*.log
-
-coverage
-
-# Runtime data
-pids
-*.pid
-*.seed
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# node-waf configuration
-.lock-wscript
-
-build
-
-# Dependency directory
-# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
-node_modules
-
-dist
-docs
-package-lock.json
-yarn.lock
-.vscode
diff --git a/secp256k1/.npmignore b/secp256k1/.npmignore
deleted file mode 100644
index 59335fd..0000000
--- a/secp256k1/.npmignore
+++ /dev/null
@@ -1,34 +0,0 @@
-**/node_modules/
-**/*.log
-test/repo-tests*
-
-# Logs
-logs
-*.log
-
-coverage
-
-# Runtime data
-pids
-*.pid
-*.seed
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# node-waf configuration
-.lock-wscript
-
-build
-
-# Dependency directory
-# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
-node_modules
-
-test
diff --git a/secp256k1/.travis.yml b/secp256k1/.travis.yml
deleted file mode 100644
index cb1d170..0000000
--- a/secp256k1/.travis.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-
-language: node_js
-
-cache: npm
-
-stages:
- - check
- - test
- - cov
-
-node_js:
- - '10'
- - '12'
-
-os:
- - linux
- - osx
- - windows
-
-script: npx nyc -s npm run test:node -- --bail
-after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov
-
-jobs:
- include:
- - stage: check
- script:
- - npx aegir dep-check
- - npm run lint
-
- - stage: test
- name: chrome
- addons:
- chrome: stable
- script:
- - npx aegir test -t browser
-
- - stage: test
- name: firefox
- addons:
- firefox: latest
- script:
- - npx aegir test -t browser -- --browsers FirefoxHeadless
-
-notifications:
- email: false
\ No newline at end of file
diff --git a/secp256k1/CHANGELOG.md b/secp256k1/CHANGELOG.md
deleted file mode 100644
index 4dd03a4..0000000
--- a/secp256k1/CHANGELOG.md
+++ /dev/null
@@ -1,134 +0,0 @@
-
-## [0.4.3](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.4.2...v0.4.3) (2020-03-25)
-
-
-
-
-## [0.4.2](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.4.1...v0.4.2) (2020-03-17)
-
-
-### Bug Fixes
-
-* add buffer and update deps ([#25](https://github.com/libp2p/js-libp2p-crypto-secp256k1/issues/25)) ([35f196e](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/35f196e))
-
-
-
-
-## [0.4.1](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.4.0...v0.4.1) (2020-01-06)
-
-
-
-
-# [0.4.0](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.3.1...v0.4.0) (2019-07-10)
-
-
-### Features
-
-* use async await ([#18](https://github.com/libp2p/js-libp2p-crypto-secp256k1/issues/18)) ([1974eb9](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/1974eb9))
-
-
-### BREAKING CHANGES
-
-* Callback support has been dropped in favor of async/await.
-
-* feat: use async/await
-
-This PR changes this module to remove callbacks and use async/await. The API is unchanged aside from the obvious removal of the `callback` parameter.
-
-refs https://github.com/ipfs/js-ipfs/issues/1670
-
-* fix: use latest multihashing-async as it is all promises now
-
-
-
-
-## [0.3.1](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.2.2...v0.3.1) (2019-07-10)
-
-
-### Bug Fixes
-
-* update deps and repo setup ([cfdcbe0](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/cfdcbe0))
-* **unmarshal:** provide only one arg to callback ([#17](https://github.com/libp2p/js-libp2p-crypto-secp256k1/issues/17)) ([3bb8451](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/3bb8451))
-
-
-### Features
-
-* add `id()` method to Secp256k1PrivateKey ([f4dbd62](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/f4dbd62))
-
-
-
-
-# [0.3.0](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.2.3...v0.3.0) (2019-02-20)
-
-
-### Features
-
-* add `id()` method to Secp256k1PrivateKey ([f4dbd62](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/f4dbd62))
-
-
-
-
-## [0.2.3](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.2.2...v0.2.3) (2019-01-08)
-
-
-### Bug Fixes
-
-* update deps and repo setup ([cfdcbe0](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/cfdcbe0))
-
-
-
-
-## [0.2.2](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.2.1...v0.2.2) (2017-07-22)
-
-
-### Bug Fixes
-
-* circular circular dep -> DI ([0dcf1a6](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/0dcf1a6))
-
-
-
-
-## [0.2.1](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.2.0...v0.2.1) (2017-07-22)
-
-
-
-
-# [0.2.0](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.4...v0.2.0) (2017-07-22)
-
-
-### Features
-
-* next libp2p-crypto ([#4](https://github.com/libp2p/js-libp2p-crypto-secp256k1/issues/4)) ([4ee48a7](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/4ee48a7))
-
-
-
-
-## [0.1.4](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.3...v0.1.4) (2017-02-12)
-
-
-
-
-## [0.1.3](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.2...v0.1.3) (2017-02-11)
-
-
-
-
-## [0.1.2](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.1...v0.1.2) (2017-02-09)
-
-
-
-
-## [0.1.1](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.0...v0.1.1) (2017-02-09)
-
-
-
-
-# [0.1.0](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/4c36aeb...v0.1.0) (2017-02-09)
-
-
-### Features
-
-* initial implementation ([4c36aeb](https://github.com/libp2p/js-libp2p-crypto-secp256k1/commit/4c36aeb))
-
-
-
diff --git a/secp256k1/LICENSE b/secp256k1/LICENSE
deleted file mode 100644
index bbfffbf..0000000
--- a/secp256k1/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017 libp2p
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/secp256k1/README.md b/secp256k1/README.md
deleted file mode 100644
index 7063200..0000000
--- a/secp256k1/README.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# js-libp2p-crypto-secp256k1
-
-[](http://protocol.ai)
-[](http://libp2p.io/)
-[](http://webchat.freenode.net/?channels=%23libp2p)
-[](https://discuss.libp2p.io)
-[](https://codecov.io/gh/libp2p/js-libp2p-crypto-secp256k1)
-[](https://travis-ci.com/libp2p/js-libp2p-crypto-secp256k1)
-[](https://david-dm.org/libp2p/js-libp2p-crypto-secp256k1)
-[](https://github.com/feross/standard)
-
-
-
-> Support for secp256k1 keys in js-libp2p-crypto
-
-This repo contains a [js-libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto)-compatible
-implementation of cryptographic signature generation and verification using the
-[secp256k1 elliptic curve](https://en.bitcoin.it/wiki/Secp256k1) popularized by Bitcoin and other
-crypto currencies.
-
-## Lead Captain
-
-[Friedel Ziegelmayer](https://github.com/dignifiedquire/)
-
-## Table of Contents
-
-- [Install](#install)
-- [Usage](#usage)
- - [Example](#example)
-- [API](#api)
- - [`generateKeyPair([bits])`](#generatekeypairbits)
- - [`unmarshalSecp256k1PublicKey(bytes)`](#unmarshalsecp256k1publickeybytes)
- - [`unmarshalSecp256k1PrivateKey(bytes)`](#unmarshalsecp256k1privatekeybytes)
- - [`Secp256k1PublicKey`](#secp256k1publickey)
- - [`.verify(data, sig)`](#verifydata-sig)
- - [`Secp256k1PrivateKey`](#secp256k1privatekey)
- - [`.public`](#public)
- - [`.sign(data)`](#signdata)
-- [Contribute](#contribute)
-- [License](#license)
-
-## Install
-
-```sh
-npm install --save libp2p-crypto-secp256k1
-```
-
-## Usage
-
-This module is designed to work with [js-libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto).
-Installing `libp2p-crypto-secp256k1` will automatically add support for the `'secp256k1'` key type, which
-can be used as an argument to the [libp2p-crypto API functions](https://github.com/libp2p/js-libp2p-crypto#api)
-`generateKeyPair`, `unmarshalPublicKey`, and `marshalPrivateKey`. The keys returned from those functions will be
-instances of the `Secp256k1PublicKey` or `Secp256k1PrivateKey` classes provided by this module.
-
-### Example
-
-```js
-const crypto = require('libp2p-crypto')
-const msg = Buffer.from('Hello World')
-
-const key = await crypto.generateKeyPair('secp256k1', 256)
-// assuming no error, key will be an instance of Secp256k1PrivateKey
-// the public key is available as key.public
-const sig = await key.sign(msg)
-
-const valid = await key.public.verify(msg, sig)
-assert(valid, 'Something went horribly wrong')
-```
-
-## API
-
-The functions below are the public API of this module.
-For usage within `libp2p-crypto`, see the [`libp2p-crypto` API documentation](https://github.com/libp2p/js-libp2p-crypto#api).
-
-### `generateKeyPair([bits])`
-- `bits: Number` - Optional, included for compatibility with js-libp2p-crypto. Ignored if present; private keys will always be 256 bits.
-
-Returns `Promise`
-
-### `unmarshalSecp256k1PublicKey(bytes)`
-- `bytes: Buffer`
-
-Converts a serialized secp256k1 public key into an instance of `Secp256k1PublicKey` and returns it
-
-### `unmarshalSecp256k1PrivateKey(bytes)`
-- `bytes: Buffer`
-
-Returns `Promise`
-
-Converts a serialized secp256k1 private key into an instance of `Secp256k1PrivateKey`.
-
-### `Secp256k1PublicKey`
-
-#### `.verify(data, sig)`
-- `data: Buffer`
-- `sig: Buffer`
-
-Returns `Promise`
-
-Calculates the SHA-256 hash of `data`, and verifies the DER-encoded signature in `sig`.
-
-### `Secp256k1PrivateKey`
-
-#### `.public`
-
-Accessor for the `Secp256k1PublicKey` associated with this private key.
-
-#### `.sign(data)`
-- `data: Buffer`
-
-Returns `Promise`
-
-Calculates the SHA-256 hash of `data` and signs it, resolves with the DER-encoded signature.
-
-## Contribute
-
-Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto-secp256k1/issues)!
-
-This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
-
-[](https://github.com/ipfs/community/blob/master/contributing.md)
-
-## License
-
-[MIT](LICENSE)
diff --git a/secp256k1/package.json b/secp256k1/package.json
deleted file mode 100644
index 0a41bd6..0000000
--- a/secp256k1/package.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "name": "libp2p-crypto-secp256k1",
- "version": "0.4.3",
- "description": "Support for secp256k1 keys in libp2p-crypto",
- "leadMaintainer": "Friedel Ziegelmayer ",
- "main": "src/index.js",
- "scripts": {
- "lint": "aegir lint",
- "build": "aegir build",
- "test": "aegir test -t node -t browser",
- "test:node": "aegir test -t node",
- "test:browser": "aegir test -t browser",
- "release": "aegir release",
- "release-minor": "aegir release --type minor",
- "release-major": "aegir release --type major",
- "coverage": "aegir coverage",
- "coverage-publish": "aegir coverage publish"
- },
- "keywords": [
- "IPFS",
- "libp2p",
- "crypto",
- "secp256k1"
- ],
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "is-typedarray": "^1.0.0",
- "multibase": "^0.7.0",
- "multihashing-async": "^0.8.1",
- "secp256k1": "^4.0.0"
- },
- "devDependencies": {
- "aegir": "^21.0.2",
- "benchmark": "^2.1.4",
- "chai": "^4.2.0",
- "dirty-chai": "^2.0.1",
- "libp2p-crypto": "~0.17.2",
- "protons": "^1.1.0"
- },
- "engines": {
- "node": ">=6.0.0",
- "npm": ">=3.0.0"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/libp2p/js-libp2p-crypto-secp256k1.git"
- },
- "bugs": {
- "url": "https://github.com/libp2p/js-libp2p-crypto-secp256k1/issues"
- },
- "homepage": "https://github.com/libp2p/js-libp2p-crypto-secp256k1",
- "contributors": [
- "David Dias ",
- "Jacob Heun ",
- "Friedel Ziegelmayer ",
- "Hugo Dias ",
- "ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ ",
- "Yusef Napora ",
- "Alan Shaw ",
- "Alberto Elias ",
- "Alex Potsides ",
- "Arve Knudsen ",
- "Vasco Santos "
- ]
-}
diff --git a/secp256k1/test/secp256k1.spec.js b/secp256k1/test/secp256k1.spec.js
deleted file mode 100644
index 0863ca4..0000000
--- a/secp256k1/test/secp256k1.spec.js
+++ /dev/null
@@ -1,268 +0,0 @@
-/* eslint-env mocha */
-'use strict'
-
-const { Buffer } = require('buffer')
-const chai = require('chai')
-const dirtyChai = require('dirty-chai')
-const expect = chai.expect
-chai.use(dirtyChai)
-const protobuf = require('protons')
-const keysPBM = protobuf(require('libp2p-crypto/src/keys/keys.proto'))
-const randomBytes = require('libp2p-crypto/src/random-bytes')
-const crypto = require('../src/crypto')(randomBytes)
-
-describe('secp256k1 keys', () => {
- let key
- const secp256k1 = require('../src')(keysPBM, randomBytes)
-
- before(async () => {
- key = await secp256k1.generateKeyPair()
- })
-
- it('generates a valid key', async () => {
- expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
- expect(key.public).to.be.an.instanceof(secp256k1.Secp256k1PublicKey)
-
- const digest = await key.hash()
- expect(digest).to.have.length(34)
-
- const publicDigest = await key.public.hash()
- expect(publicDigest).to.have.length(34)
- })
-
- it('optionally accepts a `bits` argument when generating a key', async () => {
- const _key = await secp256k1.generateKeyPair(256)
- expect(_key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
- })
-
- it('signs', async () => {
- const text = randomBytes(512)
- const sig = await key.sign(text)
- const res = await key.public.verify(text, sig)
- expect(res).to.equal(true)
- })
-
- it('encoding', async () => {
- const keyMarshal = key.marshal()
- const key2 = await secp256k1.unmarshalSecp256k1PrivateKey(keyMarshal)
- const keyMarshal2 = key2.marshal()
-
- expect(keyMarshal).to.eql(keyMarshal2)
-
- const pk = key.public
- const pkMarshal = pk.marshal()
- const pk2 = secp256k1.unmarshalSecp256k1PublicKey(pkMarshal)
- const pkMarshal2 = pk2.marshal()
-
- expect(pkMarshal).to.eql(pkMarshal2)
- })
-
- it('key id', async () => {
- const id = await key.id()
- expect(id).to.exist()
- expect(id).to.be.a('string')
- })
-
- describe('key equals', () => {
- it('equals itself', () => {
- expect(key.equals(key)).to.eql(true)
-
- expect(key.public.equals(key.public)).to.eql(true)
- })
-
- it('not equals other key', async () => {
- const key2 = await secp256k1.generateKeyPair(256)
- expect(key.equals(key2)).to.eql(false)
- expect(key2.equals(key)).to.eql(false)
- expect(key.public.equals(key2.public)).to.eql(false)
- expect(key2.public.equals(key.public)).to.eql(false)
- })
- })
-
- it('sign and verify', async () => {
- const data = Buffer.from('hello world')
- const sig = await key.sign(data)
- const valid = await key.public.verify(data, sig)
- expect(valid).to.eql(true)
- })
-
- it('fails to verify for different data', async () => {
- const data = Buffer.from('hello world')
- const sig = await key.sign(data)
- const valid = await key.public.verify(Buffer.from('hello'), sig)
- expect(valid).to.eql(false)
- })
-})
-
-describe('key generation error', () => {
- let generateKey
- let secp256k1
-
- before(() => {
- generateKey = crypto.generateKey
- crypto.generateKey = () => { throw new Error('Error generating key') }
- secp256k1 = require('../src')(keysPBM, randomBytes, crypto)
- })
-
- after(() => {
- crypto.generateKey = generateKey
- })
-
- it('returns an error if key generation fails', async () => {
- try {
- await secp256k1.generateKeyPair()
- } catch (err) {
- return expect(err.message).to.equal('Error generating key')
- }
- throw new Error('Expected error to be thrown')
- })
-})
-
-describe('handles generation of invalid key', () => {
- let generateKey
- let secp256k1
-
- before(() => {
- generateKey = crypto.generateKey
- crypto.generateKey = () => Buffer.from('not a real key')
- secp256k1 = require('../src')(keysPBM, randomBytes, crypto)
- })
-
- after(() => {
- crypto.generateKey = generateKey
- })
-
- it('returns an error if key generator returns an invalid key', async () => {
- try {
- await secp256k1.generateKeyPair()
- } catch (err) {
- return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
- }
- throw new Error('Expected error to be thrown')
- })
-})
-
-describe('crypto functions', () => {
- let privKey
- let pubKey
-
- before(async () => {
- privKey = await crypto.generateKey()
- pubKey = crypto.computePublicKey(privKey)
- })
-
- it('generates valid keys', () => {
- expect(() => {
- crypto.validatePrivateKey(privKey)
- crypto.validatePublicKey(pubKey)
- }).to.not.throw()
- })
-
- it('does not validate an invalid key', () => {
- expect(() => crypto.validatePublicKey(Buffer.from('42'))).to.throw()
- expect(() => crypto.validatePrivateKey(Buffer.from('42'))).to.throw()
- })
-
- it('validates a correct signature', async () => {
- const sig = await crypto.hashAndSign(privKey, Buffer.from('hello'))
- const valid = await crypto.hashAndVerify(pubKey, sig, Buffer.from('hello'))
- expect(valid).to.equal(true)
- })
-
- it('errors if given a null buffer to sign', async () => {
- try {
- await crypto.hashAndSign(privKey, null)
- } catch (err) {
- return // expected
- }
- throw new Error('Expected error to be thrown')
- })
-
- it('errors when signing with an invalid key', async () => {
- try {
- await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
- } catch (err) {
- return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
- }
- throw new Error('Expected error to be thrown')
- })
-
- it('errors if given a null buffer to validate', async () => {
- const sig = await crypto.hashAndSign(privKey, Buffer.from('hello'))
-
- try {
- await crypto.hashAndVerify(privKey, sig, null)
- } catch (err) {
- return // expected
- }
- throw new Error('Expected error to be thrown')
- })
-
- it('errors when validating a message with an invalid signature', async () => {
- try {
- await crypto.hashAndVerify(pubKey, Buffer.from('invalid-sig'), Buffer.from('hello'))
- } catch (err) {
- return expect(err.message).to.equal('Signature could not be parsed')
- }
- throw new Error('Expected error to be thrown')
- })
-
- it('errors when signing with an invalid key', async () => {
- try {
- await crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
- } catch (err) {
- return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
- }
- throw new Error('Expected error to be thrown')
- })
-
- it('throws when compressing an invalid public key', () => {
- expect(() => crypto.compressPublicKey(Buffer.from('42'))).to.throw()
- })
-
- it('throws when decompressing an invalid public key', () => {
- expect(() => crypto.decompressPublicKey(Buffer.from('42'))).to.throw()
- })
-
- it('compresses/decompresses a valid public key', () => {
- const decompressed = crypto.decompressPublicKey(pubKey)
- expect(decompressed).to.exist()
- expect(decompressed.length).to.be.eql(65)
- const recompressed = crypto.compressPublicKey(decompressed)
- expect(recompressed).to.eql(pubKey)
- })
-})
-
-describe('go interop', () => {
- const secp256k1 = require('../src')(keysPBM, randomBytes)
- const fixtures = require('./fixtures/go-interop')
-
- it('loads a private key marshaled by go-libp2p-crypto', async () => {
- // we need to first extract the key data from the protobuf, which is
- // normally handled by js-libp2p-crypto
- const decoded = keysPBM.PrivateKey.decode(fixtures.privateKey)
- expect(decoded.Type).to.eql(keysPBM.KeyType.Secp256k1)
-
- const key = await secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data)
- expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
- expect(key.bytes).to.eql(fixtures.privateKey)
- })
-
- it('loads a public key marshaled by go-libp2p-crypto', () => {
- const decoded = keysPBM.PublicKey.decode(fixtures.publicKey)
- expect(decoded.Type).to.be.eql(keysPBM.KeyType.Secp256k1)
-
- const key = secp256k1.unmarshalSecp256k1PublicKey(decoded.Data)
- expect(key).to.be.an.instanceof(secp256k1.Secp256k1PublicKey)
- expect(key.bytes).to.eql(fixtures.publicKey)
- })
-
- it('generates the same signature as go-libp2p-crypto', async () => {
- const decoded = keysPBM.PrivateKey.decode(fixtures.privateKey)
- expect(decoded.Type).to.eql(keysPBM.KeyType.Secp256k1)
-
- const key = await secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data)
- const sig = await key.sign(fixtures.message)
- expect(sig).to.eql(fixtures.signature)
- })
-})
diff --git a/src/keys/index.js b/src/keys/index.js
index a05d8cc..ad92cd1 100644
--- a/src/keys/index.js
+++ b/src/keys/index.js
@@ -13,7 +13,7 @@ exports = module.exports
const supportedKeys = {
rsa: require('./rsa-class'),
ed25519: require('./ed25519-class'),
- secp256k1: require('libp2p-crypto-secp256k1')(keysPBM, require('../random-bytes'))
+ secp256k1: require('./secp256k1-class')(keysPBM, require('../random-bytes'))
}
exports.supportedKeys = supportedKeys
diff --git a/secp256k1/src/index.js b/src/keys/secp256k1-class.js
similarity index 97%
rename from secp256k1/src/index.js
rename to src/keys/secp256k1-class.js
index 13ebfe8..e8c5390 100644
--- a/secp256k1/src/index.js
+++ b/src/keys/secp256k1-class.js
@@ -4,7 +4,7 @@ const multibase = require('multibase')
const sha = require('multihashing-async/src/sha')
module.exports = (keysProtobuf, randomBytes, crypto) => {
- crypto = crypto || require('./crypto')(randomBytes)
+ crypto = crypto || require('./secp256k1')(randomBytes)
class Secp256k1PublicKey {
constructor (key) {
diff --git a/secp256k1/src/crypto.js b/src/keys/secp256k1.js
similarity index 100%
rename from secp256k1/src/crypto.js
rename to src/keys/secp256k1.js
diff --git a/secp256k1/test/fixtures/go-interop.js b/test/fixtures/go-key-secp256k1.js
similarity index 100%
rename from secp256k1/test/fixtures/go-interop.js
rename to test/fixtures/go-key-secp256k1.js
diff --git a/test/keys/secp256k1.spec.js b/test/keys/secp256k1.spec.js
index 2f17613..da245ab 100644
--- a/test/keys/secp256k1.spec.js
+++ b/test/keys/secp256k1.spec.js
@@ -1,81 +1,267 @@
/* eslint-env mocha */
'use strict'
+const { Buffer } = require('buffer')
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
-const sinon = require('sinon')
-
-const fixtures = require('../fixtures/secp256k1')
const crypto = require('../../src')
+const secp256k1 = crypto.keys.supportedKeys.secp256k1
+const keysPBM = crypto.keys.keysPBM
+const randomBytes = crypto.randomBytes
+const secp256k1Crypto = require('../../src/keys/secp256k1')(randomBytes)
-describe('without libp2p-crypto-secp256k1 module present', () => {
- before(() => {
- const empty = null
- sinon.replace(crypto.keys.supportedKeys, 'secp256k1', empty)
+describe('secp256k1 keys', () => {
+ let key
+
+ before(async () => {
+ key = await secp256k1.generateKeyPair()
})
- after(() => {
- sinon.restore()
- })
-
- it('fails to generate a secp256k1 key', async () => {
- try {
- await crypto.keys.generateKeyPair('secp256k1', 256)
- } catch (err) {
- return // expected
- }
- throw new Error('Expected error to be thrown')
- })
-
- it('fails to unmarshal a secp256k1 private key', async () => {
- try {
- await crypto.keys.unmarshalPrivateKey(fixtures.pbmPrivateKey)
- } catch (err) {
- return // expected
- }
- throw new Error('Expected error to be thrown')
- })
-
- it('fails to unmarshal a secp256k1 public key', () => {
- expect(() => {
- crypto.keys.unmarshalPublicKey(fixtures.pbmPublicKey)
- }).to.throw(Error)
- })
-})
-
-describe('with libp2p-crypto-secp256k1 module present', () => {
it('generates a valid key', async () => {
- const key = await crypto.keys.generateKeyPair('secp256k1', 256)
- expect(key).to.exist()
+ expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
+ expect(key.public).to.be.an.instanceof(secp256k1.Secp256k1PublicKey)
+
+ const digest = await key.hash()
+ expect(digest).to.have.length(34)
+
+ const publicDigest = await key.public.hash()
+ expect(publicDigest).to.have.length(34)
})
- it('protobuf encoding', async () => {
- const key = await crypto.keys.generateKeyPair('secp256k1', 256)
- expect(key).to.exist()
+ it('optionally accepts a `bits` argument when generating a key', async () => {
+ const _key = await secp256k1.generateKeyPair(256)
+ expect(_key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
+ })
- const keyMarshal = crypto.keys.marshalPrivateKey(key)
- const key2 = await crypto.keys.unmarshalPrivateKey(keyMarshal)
- const keyMarshal2 = crypto.keys.marshalPrivateKey(key2)
+ it('signs', async () => {
+ const text = randomBytes(512)
+ const sig = await key.sign(text)
+ const res = await key.public.verify(text, sig)
+ expect(res).to.equal(true)
+ })
+
+ it('encoding', async () => {
+ const keyMarshal = key.marshal()
+ const key2 = await secp256k1.unmarshalSecp256k1PrivateKey(keyMarshal)
+ const keyMarshal2 = key2.marshal()
expect(keyMarshal).to.eql(keyMarshal2)
const pk = key.public
- const pkMarshal = crypto.keys.marshalPublicKey(pk)
- const pk2 = crypto.keys.unmarshalPublicKey(pkMarshal)
- const pkMarshal2 = crypto.keys.marshalPublicKey(pk2)
+ const pkMarshal = pk.marshal()
+ const pk2 = secp256k1.unmarshalSecp256k1PublicKey(pkMarshal)
+ const pkMarshal2 = pk2.marshal()
expect(pkMarshal).to.eql(pkMarshal2)
})
- it('unmarshals a secp256k1 private key', async () => {
- const key = await crypto.keys.unmarshalPrivateKey(fixtures.pbmPrivateKey)
- expect(key).to.exist()
+ it('key id', async () => {
+ const id = await key.id()
+ expect(id).to.exist()
+ expect(id).to.be.a('string')
})
- it('unmarshals a secp256k1 public key', () => {
- const key = crypto.keys.unmarshalPublicKey(fixtures.pbmPublicKey)
- expect(key).to.exist()
+ describe('key equals', () => {
+ it('equals itself', () => {
+ expect(key.equals(key)).to.eql(true)
+
+ expect(key.public.equals(key.public)).to.eql(true)
+ })
+
+ it('not equals other key', async () => {
+ const key2 = await secp256k1.generateKeyPair(256)
+ expect(key.equals(key2)).to.eql(false)
+ expect(key2.equals(key)).to.eql(false)
+ expect(key.public.equals(key2.public)).to.eql(false)
+ expect(key2.public.equals(key.public)).to.eql(false)
+ })
+ })
+
+ it('sign and verify', async () => {
+ const data = Buffer.from('hello world')
+ const sig = await key.sign(data)
+ const valid = await key.public.verify(data, sig)
+ expect(valid).to.eql(true)
+ })
+
+ it('fails to verify for different data', async () => {
+ const data = Buffer.from('hello world')
+ const sig = await key.sign(data)
+ const valid = await key.public.verify(Buffer.from('hello'), sig)
+ expect(valid).to.eql(false)
+ })
+})
+
+describe('key generation error', () => {
+ let generateKey
+ let secp256k1
+
+ before(() => {
+ generateKey = secp256k1Crypto.generateKey
+ secp256k1 = require('../../src/keys/secp256k1-class')(keysPBM, randomBytes, secp256k1Crypto)
+ secp256k1Crypto.generateKey = () => { throw new Error('Error generating key') }
+ })
+
+ after(() => {
+ secp256k1Crypto.generateKey = generateKey
+ })
+
+ it('returns an error if key generation fails', async () => {
+ try {
+ await secp256k1.generateKeyPair()
+ } catch (err) {
+ return expect(err.message).to.equal('Error generating key')
+ }
+ throw new Error('Expected error to be thrown')
+ })
+})
+
+describe('handles generation of invalid key', () => {
+ let generateKey
+ let secp256k1
+
+ before(() => {
+ generateKey = secp256k1Crypto.generateKey
+ secp256k1 = require('../../src/keys/secp256k1-class')(keysPBM, randomBytes, secp256k1Crypto)
+ secp256k1Crypto.generateKey = () => Buffer.from('not a real key')
+ })
+
+ after(() => {
+ secp256k1Crypto.generateKey = generateKey
+ })
+
+ it('returns an error if key generator returns an invalid key', async () => {
+ try {
+ await secp256k1.generateKeyPair()
+ } catch (err) {
+ return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
+ }
+ throw new Error('Expected error to be thrown')
+ })
+})
+
+describe('crypto functions', () => {
+ let privKey
+ let pubKey
+
+ before(async () => {
+ privKey = await secp256k1Crypto.generateKey()
+ pubKey = secp256k1Crypto.computePublicKey(privKey)
+ })
+
+ it('generates valid keys', () => {
+ expect(() => {
+ secp256k1Crypto.validatePrivateKey(privKey)
+ secp256k1Crypto.validatePublicKey(pubKey)
+ }).to.not.throw()
+ })
+
+ it('does not validate an invalid key', () => {
+ expect(() => secp256k1Crypto.validatePublicKey(Buffer.from('42'))).to.throw()
+ expect(() => secp256k1Crypto.validatePrivateKey(Buffer.from('42'))).to.throw()
+ })
+
+ it('validates a correct signature', async () => {
+ const sig = await secp256k1Crypto.hashAndSign(privKey, Buffer.from('hello'))
+ const valid = await secp256k1Crypto.hashAndVerify(pubKey, sig, Buffer.from('hello'))
+ expect(valid).to.equal(true)
+ })
+
+ it('errors if given a null buffer to sign', async () => {
+ try {
+ await secp256k1Crypto.hashAndSign(privKey, null)
+ } catch (err) {
+ return // expected
+ }
+ throw new Error('Expected error to be thrown')
+ })
+
+ it('errors when signing with an invalid key', async () => {
+ try {
+ await secp256k1Crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
+ } catch (err) {
+ return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
+ }
+ throw new Error('Expected error to be thrown')
+ })
+
+ it('errors if given a null buffer to validate', async () => {
+ const sig = await secp256k1Crypto.hashAndSign(privKey, Buffer.from('hello'))
+
+ try {
+ await secp256k1Crypto.hashAndVerify(privKey, sig, null)
+ } catch (err) {
+ return // expected
+ }
+ throw new Error('Expected error to be thrown')
+ })
+
+ it('errors when validating a message with an invalid signature', async () => {
+ try {
+ await secp256k1Crypto.hashAndVerify(pubKey, Buffer.from('invalid-sig'), Buffer.from('hello'))
+ } catch (err) {
+ return expect(err.message).to.equal('Signature could not be parsed')
+ }
+ throw new Error('Expected error to be thrown')
+ })
+
+ it('errors when signing with an invalid key', async () => {
+ try {
+ await secp256k1Crypto.hashAndSign(Buffer.from('42'), Buffer.from('Hello'))
+ } catch (err) {
+ return expect(err.message).to.equal('Expected private key to be an Uint8Array with length 32')
+ }
+ throw new Error('Expected error to be thrown')
+ })
+
+ it('throws when compressing an invalid public key', () => {
+ expect(() => secp256k1Crypto.compressPublicKey(Buffer.from('42'))).to.throw()
+ })
+
+ it('throws when decompressing an invalid public key', () => {
+ expect(() => secp256k1Crypto.decompressPublicKey(Buffer.from('42'))).to.throw()
+ })
+
+ it('compresses/decompresses a valid public key', () => {
+ const decompressed = secp256k1Crypto.decompressPublicKey(pubKey)
+ expect(decompressed).to.exist()
+ expect(decompressed.length).to.be.eql(65)
+ const recompressed = secp256k1Crypto.compressPublicKey(decompressed)
+ expect(recompressed).to.eql(pubKey)
+ })
+})
+
+describe('go interop', () => {
+ const fixtures = require('../fixtures/go-key-secp256k1')
+
+ it('loads a private key marshaled by go-libp2p-crypto', async () => {
+ // we need to first extract the key data from the protobuf, which is
+ // normally handled by js-libp2p-crypto
+ const decoded = keysPBM.PrivateKey.decode(fixtures.privateKey)
+ expect(decoded.Type).to.eql(keysPBM.KeyType.Secp256k1)
+
+ const key = await secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data)
+ expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
+ expect(key.bytes).to.eql(fixtures.privateKey)
+ })
+
+ it('loads a public key marshaled by go-libp2p-crypto', () => {
+ const decoded = keysPBM.PublicKey.decode(fixtures.publicKey)
+ expect(decoded.Type).to.be.eql(keysPBM.KeyType.Secp256k1)
+
+ const key = secp256k1.unmarshalSecp256k1PublicKey(decoded.Data)
+ expect(key).to.be.an.instanceof(secp256k1.Secp256k1PublicKey)
+ expect(key.bytes).to.eql(fixtures.publicKey)
+ })
+
+ it('generates the same signature as go-libp2p-crypto', async () => {
+ const decoded = keysPBM.PrivateKey.decode(fixtures.privateKey)
+ expect(decoded.Type).to.eql(keysPBM.KeyType.Secp256k1)
+
+ const key = await secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data)
+ const sig = await key.sign(fixtures.message)
+ expect(sig).to.eql(fixtures.signature)
})
})