mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-03-15 09:41:03 +00:00
chore: integrate libp2p-crypto-secp256k1
This commit is contained in:
parent
456a365378
commit
3272688489
@ -33,20 +33,22 @@
|
|||||||
"IPFS",
|
"IPFS",
|
||||||
"libp2p",
|
"libp2p",
|
||||||
"crypto",
|
"crypto",
|
||||||
"rsa"
|
"rsa",
|
||||||
|
"secp256k1"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "^5.5.0",
|
"buffer": "^5.5.0",
|
||||||
"err-code": "^2.0.0",
|
"err-code": "^2.0.0",
|
||||||
|
"is-typedarray": "^1.0.0",
|
||||||
"iso-random-stream": "^1.1.0",
|
"iso-random-stream": "^1.1.0",
|
||||||
"keypair": "^1.0.1",
|
"keypair": "^1.0.1",
|
||||||
"libp2p-crypto-secp256k1": "^0.4.2",
|
|
||||||
"multibase": "^0.7.0",
|
"multibase": "^0.7.0",
|
||||||
"multihashing-async": "^0.8.1",
|
"multihashing-async": "^0.8.1",
|
||||||
"node-forge": "~0.9.1",
|
"node-forge": "~0.9.1",
|
||||||
"pem-jwk": "^2.0.0",
|
"pem-jwk": "^2.0.0",
|
||||||
"protons": "^1.0.1",
|
"protons": "^1.0.1",
|
||||||
|
"secp256k1": "^4.0.0",
|
||||||
"ursa-optional": "~0.10.1"
|
"ursa-optional": "~0.10.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
38
secp256k1/.gitignore
vendored
38
secp256k1/.gitignore
vendored
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,134 +0,0 @@
|
|||||||
<a name="0.4.3"></a>
|
|
||||||
## [0.4.3](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.4.2...v0.4.3) (2020-03-25)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.4.2"></a>
|
|
||||||
## [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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.4.1"></a>
|
|
||||||
## [0.4.1](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.4.0...v0.4.1) (2020-01-06)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.4.0"></a>
|
|
||||||
# [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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.3.1"></a>
|
|
||||||
## [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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.3.0"></a>
|
|
||||||
# [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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.2.3"></a>
|
|
||||||
## [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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.2.2"></a>
|
|
||||||
## [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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.2.1"></a>
|
|
||||||
## [0.2.1](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.2.0...v0.2.1) (2017-07-22)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.2.0"></a>
|
|
||||||
# [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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.1.4"></a>
|
|
||||||
## [0.1.4](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.3...v0.1.4) (2017-02-12)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.1.3"></a>
|
|
||||||
## [0.1.3](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.2...v0.1.3) (2017-02-11)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.1.2"></a>
|
|
||||||
## [0.1.2](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.1...v0.1.2) (2017-02-09)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.1.1"></a>
|
|
||||||
## [0.1.1](https://github.com/libp2p/js-libp2p-crypto-secp256k1/compare/v0.1.0...v0.1.1) (2017-02-09)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.1.0"></a>
|
|
||||||
# [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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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.
|
|
@ -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<Secp256k1PrivateKey>`
|
|
||||||
|
|
||||||
### `unmarshalSecp256k1PublicKey(bytes)`
|
|
||||||
- `bytes: Buffer`
|
|
||||||
|
|
||||||
Converts a serialized secp256k1 public key into an instance of `Secp256k1PublicKey` and returns it
|
|
||||||
|
|
||||||
### `unmarshalSecp256k1PrivateKey(bytes)`
|
|
||||||
- `bytes: Buffer`
|
|
||||||
|
|
||||||
Returns `Promise<Secp256k1PrivateKey>`
|
|
||||||
|
|
||||||
Converts a serialized secp256k1 private key into an instance of `Secp256k1PrivateKey`.
|
|
||||||
|
|
||||||
### `Secp256k1PublicKey`
|
|
||||||
|
|
||||||
#### `.verify(data, sig)`
|
|
||||||
- `data: Buffer`
|
|
||||||
- `sig: Buffer`
|
|
||||||
|
|
||||||
Returns `Promise<Boolean>`
|
|
||||||
|
|
||||||
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<Buffer>`
|
|
||||||
|
|
||||||
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)
|
|
@ -1,66 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "libp2p-crypto-secp256k1",
|
|
||||||
"version": "0.4.3",
|
|
||||||
"description": "Support for secp256k1 keys in libp2p-crypto",
|
|
||||||
"leadMaintainer": "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
|
||||||
"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 <daviddias.p@gmail.com>",
|
|
||||||
"Jacob Heun <jacobheun@gmail.com>",
|
|
||||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
|
||||||
"Hugo Dias <hugomrdias@gmail.com>",
|
|
||||||
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
|
||||||
"Yusef Napora <yusef@napora.org>",
|
|
||||||
"Alan Shaw <alan.shaw@protocol.ai>",
|
|
||||||
"Alberto Elias <hi@albertoelias.me>",
|
|
||||||
"Alex Potsides <alex@achingbrain.net>",
|
|
||||||
"Arve Knudsen <arve.knudsen@gmail.com>",
|
|
||||||
"Vasco Santos <vasco.santos@ua.pt>"
|
|
||||||
]
|
|
||||||
}
|
|
@ -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)
|
|
||||||
})
|
|
||||||
})
|
|
@ -13,7 +13,7 @@ exports = module.exports
|
|||||||
const supportedKeys = {
|
const supportedKeys = {
|
||||||
rsa: require('./rsa-class'),
|
rsa: require('./rsa-class'),
|
||||||
ed25519: require('./ed25519-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
|
exports.supportedKeys = supportedKeys
|
||||||
|
@ -4,7 +4,7 @@ const multibase = require('multibase')
|
|||||||
const sha = require('multihashing-async/src/sha')
|
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('./secp256k1')(randomBytes)
|
||||||
|
|
||||||
class Secp256k1PublicKey {
|
class Secp256k1PublicKey {
|
||||||
constructor (key) {
|
constructor (key) {
|
@ -1,81 +1,267 @@
|
|||||||
/* 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 sinon = require('sinon')
|
|
||||||
|
|
||||||
const fixtures = require('../fixtures/secp256k1')
|
|
||||||
const crypto = require('../../src')
|
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', () => {
|
describe('secp256k1 keys', () => {
|
||||||
before(() => {
|
let key
|
||||||
const empty = null
|
|
||||||
sinon.replace(crypto.keys.supportedKeys, 'secp256k1', empty)
|
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 () => {
|
it('generates a valid key', async () => {
|
||||||
const key = await crypto.keys.generateKeyPair('secp256k1', 256)
|
expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
|
||||||
expect(key).to.exist()
|
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 () => {
|
it('optionally accepts a `bits` argument when generating a key', async () => {
|
||||||
const key = await crypto.keys.generateKeyPair('secp256k1', 256)
|
const _key = await secp256k1.generateKeyPair(256)
|
||||||
expect(key).to.exist()
|
expect(_key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey)
|
||||||
|
})
|
||||||
|
|
||||||
const keyMarshal = crypto.keys.marshalPrivateKey(key)
|
it('signs', async () => {
|
||||||
const key2 = await crypto.keys.unmarshalPrivateKey(keyMarshal)
|
const text = randomBytes(512)
|
||||||
const keyMarshal2 = crypto.keys.marshalPrivateKey(key2)
|
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)
|
expect(keyMarshal).to.eql(keyMarshal2)
|
||||||
|
|
||||||
const pk = key.public
|
const pk = key.public
|
||||||
const pkMarshal = crypto.keys.marshalPublicKey(pk)
|
const pkMarshal = pk.marshal()
|
||||||
const pk2 = crypto.keys.unmarshalPublicKey(pkMarshal)
|
const pk2 = secp256k1.unmarshalSecp256k1PublicKey(pkMarshal)
|
||||||
const pkMarshal2 = crypto.keys.marshalPublicKey(pk2)
|
const pkMarshal2 = pk2.marshal()
|
||||||
|
|
||||||
expect(pkMarshal).to.eql(pkMarshal2)
|
expect(pkMarshal).to.eql(pkMarshal2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('unmarshals a secp256k1 private key', async () => {
|
it('key id', async () => {
|
||||||
const key = await crypto.keys.unmarshalPrivateKey(fixtures.pbmPrivateKey)
|
const id = await key.id()
|
||||||
expect(key).to.exist()
|
expect(id).to.exist()
|
||||||
|
expect(id).to.be.a('string')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('unmarshals a secp256k1 public key', () => {
|
describe('key equals', () => {
|
||||||
const key = crypto.keys.unmarshalPublicKey(fixtures.pbmPublicKey)
|
it('equals itself', () => {
|
||||||
expect(key).to.exist()
|
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)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user