Compare commits

..

No commits in common. "master" and "v0.17.4" have entirely different histories.

38 changed files with 428 additions and 1344 deletions

View File

@ -1,113 +1,3 @@
<a name="0.19.2"></a>
## [0.19.2](https://github.com/libp2p/js-libp2p-crypto/compare/v0.19.1...v0.19.2) (2021-03-17)
### Bug Fixes
* ed25519 PeerID generation ([#186](https://github.com/libp2p/js-libp2p-crypto/issues/186)) ([1c16dd3](https://github.com/libp2p/js-libp2p-crypto/commit/1c16dd3)), closes [ipfs/js-ipfs#3591](https://github.com/ipfs/js-ipfs/issues/3591) [libp2p/js-libp2p-crypto#185](https://github.com/libp2p/js-libp2p-crypto/issues/185)
<a name="0.19.1"></a>
## [0.19.1](https://github.com/libp2p/js-libp2p-crypto/compare/v0.19.0...v0.19.1) (2021-03-15)
### Bug Fixes
* ed25519 key ID generation ([bc33769](https://github.com/libp2p/js-libp2p-crypto/commit/bc33769))
<a name="0.19.0"></a>
# [0.19.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.18.0...v0.19.0) (2021-01-15)
<a name="0.18.0"></a>
# [0.18.0](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.9...v0.18.0) (2020-08-07)
### Bug Fixes
* remove rendundant public key ([#181](https://github.com/libp2p/js-libp2p-crypto/issues/181)) ([afcffc8](https://github.com/libp2p/js-libp2p-crypto/commit/afcffc8))
* replace node buffers with uint8arrays ([#180](https://github.com/libp2p/js-libp2p-crypto/issues/180)) ([a0f387a](https://github.com/libp2p/js-libp2p-crypto/commit/a0f387a))
### BREAKING CHANGES
* The private ed25519 key will no longer include the redundant public key
* chore: fix lint
* - Where node Buffers were returned, now Uint8Arrays are
* chore: remove commented code
<a name="0.17.9"></a>
## [0.17.9](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.8...v0.17.9) (2020-08-05)
### Features
* add exporting/importing of non rsa keys in libp2p-key format ([#179](https://github.com/libp2p/js-libp2p-crypto/issues/179)) ([7273739](https://github.com/libp2p/js-libp2p-crypto/commit/7273739))
<a name="0.17.8"></a>
## [0.17.8](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.7...v0.17.8) (2020-07-20)
### Bug Fixes
* go ed25519 interop ([2f18a07](https://github.com/libp2p/js-libp2p-crypto/commit/2f18a07))
<a name="0.17.7"></a>
## [0.17.7](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.6...v0.17.7) (2020-06-09)
<a name="0.17.6"></a>
## [0.17.6](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.5...v0.17.6) (2020-04-07)
### Bug Fixes
* add buffer and update deps ([#25](https://github.com/libp2p/js-libp2p-crypto/issues/25)) ([35f196e](https://github.com/libp2p/js-libp2p-crypto/commit/35f196e))
* **unmarshal:** provide only one arg to callback ([#17](https://github.com/libp2p/js-libp2p-crypto/issues/17)) ([3bb8451](https://github.com/libp2p/js-libp2p-crypto/commit/3bb8451))
* circular circular dep -> DI ([0dcf1a6](https://github.com/libp2p/js-libp2p-crypto/commit/0dcf1a6))
* update deps and repo setup ([cfdcbe0](https://github.com/libp2p/js-libp2p-crypto/commit/cfdcbe0))
### Features
* add `id()` method to Secp256k1PrivateKey ([f4dbd62](https://github.com/libp2p/js-libp2p-crypto/commit/f4dbd62))
* initial implementation ([4c36aeb](https://github.com/libp2p/js-libp2p-crypto/commit/4c36aeb))
* next libp2p-crypto ([#4](https://github.com/libp2p/js-libp2p-crypto/issues/4)) ([4ee48a7](https://github.com/libp2p/js-libp2p-crypto/commit/4ee48a7))
* use async await ([#18](https://github.com/libp2p/js-libp2p-crypto/issues/18)) ([1974eb9](https://github.com/libp2p/js-libp2p-crypto/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.17.5"></a>
## [0.17.5](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.4...v0.17.5) (2020-03-24)
<a name="0.17.4"></a> <a name="0.17.4"></a>
## [0.17.4](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.3...v0.17.4) (2020-03-23) ## [0.17.4](https://github.com/libp2p/js-libp2p-crypto/compare/v0.17.3...v0.17.4) (2020-03-23)

122
README.md
View File

@ -20,12 +20,10 @@ This repo contains the JavaScript implementation of the crypto primitives needed
## Table of Contents ## Table of Contents
- [js-libp2p-crypto](#js-libp2p-crypto) - [js-libp2p-crypto](#js-libp2p-crypto)
- [Lead Maintainer](#lead-maintainer) - [Lead Maintainer](#Lead-Maintainer)
- [Table of Contents](#table-of-contents) - [Table of Contents](#Table-of-Contents)
- [Install](#install) - [Install](#Install)
- [Usage](#usage) - [API](#API)
- [Web Crypto API](#web-crypto-api)
- [API](#api)
- [`crypto.aes`](#cryptoaes) - [`crypto.aes`](#cryptoaes)
- [`crypto.aes.create(key, iv)`](#cryptoaescreatekey-iv) - [`crypto.aes.create(key, iv)`](#cryptoaescreatekey-iv)
- [`decrypt(data)`](#decryptdata) - [`decrypt(data)`](#decryptdata)
@ -34,19 +32,18 @@ This repo contains the JavaScript implementation of the crypto primitives needed
- [`crypto.hmac.create(hash, secret)`](#cryptohmaccreatehash-secret) - [`crypto.hmac.create(hash, secret)`](#cryptohmaccreatehash-secret)
- [`digest(data)`](#digestdata) - [`digest(data)`](#digestdata)
- [`crypto.keys`](#cryptokeys) - [`crypto.keys`](#cryptokeys)
- [`crypto.keys.generateKeyPair(type, bits)`](#cryptokeysgeneratekeypairtype-bits) - [`crypto.keys.generateKeyPair(type, bits)`](#cryptokeysgenerateKeyPairtype-bits)
- [`crypto.keys.generateEphemeralKeyPair(curve)`](#cryptokeysgenerateephemeralkeypaircurve) - [`crypto.keys.generateEphemeralKeyPair(curve)`](#cryptokeysgenerateEphemeralKeyPaircurve)
- [`crypto.keys.keyStretcher(cipherType, hashType, secret)`](#cryptokeyskeystretcherciphertype-hashtype-secret) - [`crypto.keys.keyStretcher(cipherType, hashType, secret)`](#cryptokeyskeyStretchercipherType-hashType-secret)
- [`crypto.keys.marshalPublicKey(key, [type])`](#cryptokeysmarshalpublickeykey-type) - [`crypto.keys.marshalPublicKey(key, [type])`](#cryptokeysmarshalPublicKeykey-type)
- [`crypto.keys.unmarshalPublicKey(buf)`](#cryptokeysunmarshalpublickeybuf) - [`crypto.keys.unmarshalPublicKey(buf)`](#cryptokeysunmarshalPublicKeybuf)
- [`crypto.keys.marshalPrivateKey(key, [type])`](#cryptokeysmarshalprivatekeykey-type) - [`crypto.keys.marshalPrivateKey(key, [type])`](#cryptokeysmarshalPrivateKeykey-type)
- [`crypto.keys.unmarshalPrivateKey(buf)`](#cryptokeysunmarshalprivatekeybuf) - [`crypto.keys.unmarshalPrivateKey(buf)`](#cryptokeysunmarshalPrivateKeybuf)
- [`crypto.keys.import(encryptedKey, password)`](#cryptokeysimportencryptedkey-password) - [`crypto.keys.import(pem, password)`](#cryptokeysimportpem-password)
- [`privateKey.export(password, format)`](#privatekeyexportpassword-format) - [`crypto.randomBytes(number)`](#cryptorandomBytesnumber)
- [`crypto.randomBytes(number)`](#cryptorandombytesnumber) - [`crypto.pbkdf2(password, salt, iterations, keySize, hash)`](#cryptopbkdf2password-salt-iterations-keySize-hash)
- [`crypto.pbkdf2(password, salt, iterations, keySize, hash)`](#cryptopbkdf2password-salt-iterations-keysize-hash) - [Contribute](#Contribute)
- [Contribute](#contribute) - [License](#License)
- [License](#license)
## Install ## Install
@ -85,22 +82,22 @@ This uses `CTR` mode.
#### `crypto.aes.create(key, iv)` #### `crypto.aes.create(key, iv)`
- `key: Uint8Array` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used. - `key: Buffer` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used.
- `iv: Uint8Array` Must have length `16`. - `iv: Buffer` Must have length `16`.
Returns `Promise<{decrypt<Function>, encrypt<Function>}>` Returns `Promise<{decrypt<Function>, encrypt<Function>}>`
##### `decrypt(data)` ##### `decrypt(data)`
- `data: Uint8Array` - `data: Buffer`
Returns `Promise<Uint8Array>` Returns `Promise<Buffer>`
##### `encrypt(data)` ##### `encrypt(data)`
- `data: Uint8Array` - `data: Buffer`
Returns `Promise<Uint8Array>` Returns `Promise<Buffer>`
```js ```js
const crypto = require('libp2p-crypto') const crypto = require('libp2p-crypto')
@ -108,26 +105,26 @@ const crypto = require('libp2p-crypto')
// Setting up Key and IV // Setting up Key and IV
// A 16 bytes array, 128 Bits, AES-128 is chosen // A 16 bytes array, 128 Bits, AES-128 is chosen
const key128 = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) const key128 = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
// A 16 bytes array, 128 Bits, // A 16 bytes array, 128 Bits,
const IV = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) const IV = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
async function main () { async function main () {
const decryptedMessage = 'Hello, world!' const decryptedMessage = 'Hello, world!'
// Encrypting // Encrypting
const cipher = await crypto.aes.create(key128, IV) const cipher = await crypto.aes.create(key128, IV)
const encryptedBuffer = await cipher.encrypt(Uint8Array.from(decryptedMessage)) const encryptedBuffer = await cipher.encrypt(Buffer.from(decryptedMessage))
console.log(encryptedBuffer) console.log(encryptedBuffer)
// prints: <Uint8Array 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c> // prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
// Decrypting // Decrypting
const decipher = await crypto.aes.create(key128, IV) const decipher = await crypto.aes.create(key128, IV)
const decryptedBuffer = await cipher.decrypt(encryptedBuffer) const decryptedBuffer = await cipher.decrypt(encryptedBuffer)
console.log(decryptedBuffer) console.log(decryptedBuffer)
// prints: <Uint8Array 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c> // prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
console.log(decryptedBuffer.toString('utf-8')) console.log(decryptedBuffer.toString('utf-8'))
// prints: Hello, world! // prints: Hello, world!
@ -143,15 +140,15 @@ Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as def
#### `crypto.hmac.create(hash, secret)` #### `crypto.hmac.create(hash, secret)`
- `hash: String` - `hash: String`
- `secret: Uint8Array` - `secret: Buffer`
Returns `Promise<{digest<Function>}>` Returns `Promise<{digest<Function>}>`
##### `digest(data)` ##### `digest(data)`
- `data: Uint8Array` - `data: Buffer`
Returns `Promise<Uint8Array>` Returns `Promise<Buffer>`
Example: Example:
@ -160,8 +157,8 @@ const crypto = require('libp2p-crypto')
async function main () { async function main () {
const hash = 'SHA1' // 'SHA256' || 'SHA512' const hash = 'SHA1' // 'SHA256' || 'SHA512'
const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret')) const hmac = await crypto.hmac.create(hash, Buffer.from('secret'))
const sig = await hmac.digest(uint8ArrayFromString('hello world')) const sig = await hmac.digest(Buffer.from('hello world'))
console.log(sig) console.log(sig)
} }
@ -174,14 +171,16 @@ main()
The [`generateKeyPair`](#generatekeypairtype-bits), [`marshalPublicKey`](#marshalpublickeykey-type), and [`marshalPrivateKey`](#marshalprivatekeykey-type) functions accept a string `type` argument. The [`generateKeyPair`](#generatekeypairtype-bits), [`marshalPublicKey`](#marshalpublickeykey-type), and [`marshalPrivateKey`](#marshalprivatekeykey-type) functions accept a string `type` argument.
Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, although ed25519 and secp256k1 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used. Currently the `'RSA'` and `'ed25519'` types are supported, although ed25519 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used.
Installing the [libp2p-crypto-secp256k1](https://github.com/libp2p/js-libp2p-crypto-secp256k1) module adds support for the `'secp256k1'` type, which supports ECDSA signatures using the secp256k1 elliptic curve popularized by Bitcoin. This module is not installed by default, and should be explicitly depended on if your project requires secp256k1 support.
### `crypto.keys.generateKeyPair(type, bits)` ### `crypto.keys.generateKeyPair(type, bits)`
- `type: String`, see [Supported Key Types](#supported-key-types) above. - `type: String`, see [Supported Key Types](#supported-key-types) above.
- `bits: Number` Minimum of 1024 - `bits: Number` Minimum of 1024
Returns `Promise<{privateKey<Uint8Array>, publicKey<Uint8Array>}>` Returns `Promise<{privateKey<Buffer>, publicKey<Buffer>}>`
Generates a keypair of the given type and bitsize. Generates a keypair of the given type and bitsize.
@ -199,7 +198,7 @@ Resolves to an object of the form:
```js ```js
{ {
key: Uint8Array, key: Buffer,
genSharedKey: Function genSharedKey: Function
} }
``` ```
@ -208,7 +207,7 @@ Resolves to an object of the form:
- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'` - `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'`
- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512` - `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512`
- `secret: Uint8Array` - `secret: Buffer`
Returns `Promise` Returns `Promise`
@ -219,30 +218,30 @@ Resolves to an object of the form:
```js ```js
{ {
k1: { k1: {
iv: Uint8Array, iv: Buffer,
cipherKey: Uint8Array, cipherKey: Buffer,
macKey: Uint8Array macKey: Buffer
}, },
k2: { k2: {
iv: Uint8Array, iv: Buffer,
cipherKey: Uint8Array, cipherKey: Buffer,
macKey: Uint8Array macKey: Buffer
} }
} }
``` ```
### `crypto.keys.marshalPublicKey(key, [type])` ### `crypto.keys.marshalPublicKey(key, [type])`
- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | keys.secp256k1.Secp256k1PublicKey` - `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | require('libp2p-crypto-secp256k1').Secp256k1PublicKey`
- `type: String`, see [Supported Key Types](#supported-key-types) above. Defaults to 'rsa'. - `type: String`, see [Supported Key Types](#supported-key-types) above. Defaults to 'rsa'.
Returns `Uint8Array` Returns `Buffer`
Converts a public key object into a protobuf serialized public key. Converts a public key object into a protobuf serialized public key.
### `crypto.keys.unmarshalPublicKey(buf)` ### `crypto.keys.unmarshalPublicKey(buf)`
- `buf: Uint8Array` - `buf: Buffer`
Returns `RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey` Returns `RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey`
@ -250,46 +249,37 @@ Converts a protobuf serialized public key into its representative object.
### `crypto.keys.marshalPrivateKey(key, [type])` ### `crypto.keys.marshalPrivateKey(key, [type])`
- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | keys.secp256k1.Secp256k1PrivateKey` - `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | require('libp2p-crypto-secp256k1').Secp256k1PrivateKey`
- `type: String`, see [Supported Key Types](#supported-key-types) above. - `type: String`, see [Supported Key Types](#supported-key-types) above.
Returns `Uint8Array` Returns `Buffer`
Converts a private key object into a protobuf serialized private key. Converts a private key object into a protobuf serialized private key.
### `crypto.keys.unmarshalPrivateKey(buf)` ### `crypto.keys.unmarshalPrivateKey(buf)`
- `buf: Uint8Array` - `buf: Buffer`
Returns `Promise<RsaPrivateKey|Ed25519PrivateKey|Secp256k1PrivateKey>` Returns `Promise<RsaPrivateKey|Ed25519PrivateKey|Secp256k1PrivateKey>`
Converts a protobuf serialized private key into its representative object. Converts a protobuf serialized private key into its representative object.
### `crypto.keys.import(encryptedKey, password)` ### `crypto.keys.import(pem, password)`
- `encryptedKey: string` - `pem: string`
- `password: string` - `password: string`
Returns `Promise<PrivateKey>` Returns `Promise<RsaPrivateKey>`
Converts an exported private key into its representative object. Supported formats are 'pem' (RSA only) and 'libp2p-key'. Converts a PEM password protected private key into its representative object.
### `privateKey.export(password, format)`
- `password: string`
- `format: string` the format to export to: 'pem' (rsa only), 'libp2p-key'
Returns `string`
Exports the password protected `PrivateKey`. RSA keys will be exported as password protected PEM by default. Ed25519 and Secp256k1 keys will be exported as password protected AES-GCM base64 encoded strings ('libp2p-key' format).
### `crypto.randomBytes(number)` ### `crypto.randomBytes(number)`
- `number: Number` - `number: Number`
Returns `Uint8Array` Returns `Buffer`
Generates a Uint8Array with length `number` populated by random bytes. Generates a Buffer with length `number` populated by random bytes.
### `crypto.pbkdf2(password, salt, iterations, keySize, hash)` ### `crypto.pbkdf2(password, salt, iterations, keySize, hash)`

View File

@ -1,15 +1,14 @@
{ {
"name": "libp2p-crypto", "name": "libp2p-crypto",
"version": "0.19.2", "version": "0.17.4",
"description": "Crypto primitives for libp2p", "description": "Crypto primitives for libp2p",
"main": "src/index.js", "main": "src/index.js",
"types": "src/index.d.ts", "types": "src/index.d.ts",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>", "leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"browser": { "browser": {
"./src/aes/ciphers.js": "./src/aes/ciphers-browser.js",
"./src/ciphers/aes-gcm.js": "./src/ciphers/aes-gcm.browser.js",
"./src/hmac/index.js": "./src/hmac/index-browser.js", "./src/hmac/index.js": "./src/hmac/index-browser.js",
"./src/keys/ecdh.js": "./src/keys/ecdh-browser.js", "./src/keys/ecdh.js": "./src/keys/ecdh-browser.js",
"./src/aes/ciphers.js": "./src/aes/ciphers-browser.js",
"./src/keys/rsa.js": "./src/keys/rsa-browser.js" "./src/keys/rsa.js": "./src/keys/rsa-browser.js"
}, },
"files": [ "files": [
@ -34,32 +33,29 @@
"IPFS", "IPFS",
"libp2p", "libp2p",
"crypto", "crypto",
"rsa", "rsa"
"secp256k1"
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"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",
"multibase": "^4.0.3", "libp2p-crypto-secp256k1": "^0.4.2",
"multicodec": "^3.0.1", "multibase": "^0.6.0",
"multihashes": "^4.0.2", "multihashing-async": "^0.8.1",
"multihashing-async": "^2.0.1", "node-forge": "~0.9.1",
"node-forge": "^0.10.0",
"pem-jwk": "^2.0.0", "pem-jwk": "^2.0.0",
"protons": "^2.0.0", "protons": "^1.0.1",
"secp256k1": "^4.0.0", "ursa-optional": "~0.10.1"
"uint8arrays": "^2.1.4",
"ursa-optional": "^0.10.1"
}, },
"devDependencies": { "devDependencies": {
"@types/chai": "^4.2.12", "@types/chai": "^4.2.11",
"@types/chai-string": "^1.4.2", "@types/chai-string": "^1.4.2",
"@types/dirty-chai": "^2.0.2", "@types/dirty-chai": "^2.0.2",
"@types/mocha": "^8.0.1", "@types/mocha": "^7.0.1",
"aegir": "^25.0.0", "@types/sinon": "^7.5.1",
"aegir": "^21.0.2",
"benchmark": "^2.1.4", "benchmark": "^2.1.4",
"chai": "^4.2.0", "chai": "^4.2.0",
"chai-string": "^1.5.0", "chai-string": "^1.5.0",
@ -81,26 +77,23 @@
"contributors": [ "contributors": [
"David Dias <daviddias.p@gmail.com>", "David Dias <daviddias.p@gmail.com>",
"Friedel Ziegelmayer <dignifiedquire@gmail.com>", "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
"Jacob Heun <jacobheun@gmail.com>",
"Maciej Krüger <mkg20001@gmail.com>", "Maciej Krüger <mkg20001@gmail.com>",
"Jacob Heun <jacobheun@gmail.com>",
"dryajov <dryajov@gmail.com>", "dryajov <dryajov@gmail.com>",
"Alan Shaw <alan.shaw@protocol.ai>", "Alan Shaw <alan.shaw@protocol.ai>",
"Hugo Dias <hugomrdias@gmail.com>",
"Cayman <caymannava@gmail.com>",
"Yusef Napora <yusef@napora.org>", "Yusef Napora <yusef@napora.org>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
"Arve Knudsen <arve.knudsen@gmail.com>",
"Alex Potsides <alex@achingbrain.net>",
"Vasco Santos <vasco.santos@ua.pt>",
"Alberto Elias <hi@albertoelias.me>",
"Jack Kleeman <jackkleeman@gmail.com>",
"Nadim Kobeissi <nadim@symbolic.software>",
"Richard Littauer <richard.littauer@gmail.com>", "Richard Littauer <richard.littauer@gmail.com>",
"Arve Knudsen <arve.knudsen@gmail.com>",
"Hugo Dias <hugomrdias@gmail.com>",
"Jack Kleeman <jackkleeman@gmail.com>",
"Richard Schneider <makaretu@gmail.com>", "Richard Schneider <makaretu@gmail.com>",
"Vasco Santos <vasco.santos@ua.pt>",
"dirkmc <dirkmdev@gmail.com>", "dirkmc <dirkmdev@gmail.com>",
"nikuda <nikuda@gmail.com>", "nikuda <nikuda@gmail.com>",
"Joao Santos <jrmsantos15@gmail.com>", "ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
"Tom Swindell <t.swindell@rubyx.co.uk>",
"Carson Farmer <carson.farmer@gmail.com>", "Carson Farmer <carson.farmer@gmail.com>",
"Tom Swindell <t.swindell@rubyx.co.uk>" "Alberto Elias <hi@albertoelias.me>",
"Joao Santos <jrmsantos15@gmail.com>"
] ]
} }

View File

@ -1,28 +1,26 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
require('node-forge/lib/aes') require('node-forge/lib/aes')
const forge = require('node-forge/lib/forge') const forge = require('node-forge/lib/forge')
const uint8ArrayToString = require('uint8arrays/to-string')
const uint8ArrayFromString = require('uint8arrays/from-string')
module.exports = { module.exports = {
createCipheriv: (mode, key, iv) => { createCipheriv: (mode, key, iv) => {
const cipher2 = forge.cipher.createCipher('AES-CTR', uint8ArrayToString(key, 'ascii')) const cipher2 = forge.cipher.createCipher('AES-CTR', key.toString('binary'))
cipher2.start({ iv: uint8ArrayToString(iv, 'ascii') }) cipher2.start({ iv: iv.toString('binary') })
return { return {
update: (data) => { update: (data) => {
cipher2.update(forge.util.createBuffer(uint8ArrayToString(data, 'ascii'))) cipher2.update(forge.util.createBuffer(data.toString('binary')))
return uint8ArrayFromString(cipher2.output.getBytes(), 'ascii') return Buffer.from(cipher2.output.getBytes(), 'binary')
} }
} }
}, },
createDecipheriv: (mode, key, iv) => { createDecipheriv: (mode, key, iv) => {
const cipher2 = forge.cipher.createDecipher('AES-CTR', uint8ArrayToString(key, 'ascii')) const cipher2 = forge.cipher.createDecipher('AES-CTR', key.toString('binary'))
cipher2.start({ iv: uint8ArrayToString(iv, 'ascii') }) cipher2.start({ iv: iv.toString('binary') })
return { return {
update: (data) => { update: (data) => {
cipher2.update(forge.util.createBuffer(uint8ArrayToString(data, 'ascii'))) cipher2.update(forge.util.createBuffer(data.toString('binary')))
return uint8ArrayFromString(cipher2.output.getBytes(), 'ascii') return Buffer.from(cipher2.output.getBytes(), 'binary')
} }
} }
} }

View File

@ -1,89 +0,0 @@
'use strict'
const concat = require('uint8arrays/concat')
const fromString = require('uint8arrays/from-string')
const webcrypto = require('../webcrypto')
// Based off of code from https://github.com/luke-park/SecureCompatibleEncryptionExamples
/**
*
* @param {object} [options]
* @param {string} [options.algorithm=AES-GCM]
* @param {Number} [options.nonceLength=12]
* @param {Number} [options.keyLength=16]
* @param {string} [options.digest=sha256]
* @param {Number} [options.saltLength=16]
* @param {Number} [options.iterations=32767]
* @returns {*}
*/
function create ({
algorithm = 'AES-GCM',
nonceLength = 12,
keyLength = 16,
digest = 'SHA-256',
saltLength = 16,
iterations = 32767
} = {}) {
const crypto = webcrypto.get()
keyLength *= 8 // Browser crypto uses bits instead of bytes
/**
* Uses the provided password to derive a pbkdf2 key. The key
* will then be used to encrypt the data.
*
* @param {Uint8Array} data The data to decrypt
* @param {string} password A plain password
* @returns {Promise<Uint8Array>}
*/
async function encrypt (data, password) { // eslint-disable-line require-await
const salt = crypto.getRandomValues(new Uint8Array(saltLength))
const nonce = crypto.getRandomValues(new Uint8Array(nonceLength))
const aesGcm = { name: algorithm, iv: nonce }
// Derive a key using PBKDF2.
const deriveParams = { name: 'PBKDF2', salt, iterations, hash: { name: digest } }
const rawKey = await crypto.subtle.importKey('raw', fromString(password), { name: 'PBKDF2' }, false, ['deriveKey', 'deriveBits'])
const cryptoKey = await crypto.subtle.deriveKey(deriveParams, rawKey, { name: algorithm, length: keyLength }, true, ['encrypt'])
// Encrypt the string.
const ciphertext = await crypto.subtle.encrypt(aesGcm, cryptoKey, data)
return concat([salt, aesGcm.iv, new Uint8Array(ciphertext)])
}
/**
* Uses the provided password to derive a pbkdf2 key. The key
* will then be used to decrypt the data. The options used to create
* this decryption cipher must be the same as those used to create
* the encryption cipher.
*
* @param {Uint8Array} data The data to decrypt
* @param {string} password A plain password
* @returns {Promise<Uint8Array>}
*/
async function decrypt (data, password) {
const salt = data.slice(0, saltLength)
const nonce = data.slice(saltLength, saltLength + nonceLength)
const ciphertext = data.slice(saltLength + nonceLength)
const aesGcm = { name: algorithm, iv: nonce }
// Derive the key using PBKDF2.
const deriveParams = { name: 'PBKDF2', salt, iterations, hash: { name: digest } }
const rawKey = await crypto.subtle.importKey('raw', fromString(password), { name: 'PBKDF2' }, false, ['deriveKey', 'deriveBits'])
const cryptoKey = await crypto.subtle.deriveKey(deriveParams, rawKey, { name: algorithm, length: keyLength }, true, ['decrypt'])
// Decrypt the string.
const plaintext = await crypto.subtle.decrypt(aesGcm, cryptoKey, ciphertext)
return new Uint8Array(plaintext)
}
return {
encrypt,
decrypt
}
}
module.exports = {
create
}

View File

@ -1,130 +0,0 @@
'use strict'
const crypto = require('crypto')
const uint8ArrayConcat = require('uint8arrays/concat')
const uint8ArrayFromString = require('uint8arrays/from-string')
// Based off of code from https://github.com/luke-park/SecureCompatibleEncryptionExamples
/**
*
* @param {object} [options]
* @param {Number} [options.algorithmTagLength=16]
* @param {Number} [options.nonceLength=12]
* @param {Number} [options.keyLength=16]
* @param {string} [options.digest=sha256]
* @param {Number} [options.saltLength=16]
* @param {Number} [options.iterations=32767]
* @returns {*}
*/
function create ({
algorithmTagLength = 16,
nonceLength = 12,
keyLength = 16,
digest = 'sha256',
saltLength = 16,
iterations = 32767
} = {}) {
const algorithm = 'aes-128-gcm'
/**
*
* @private
* @param {Uint8Array} data
* @param {Uint8Array} key
* @returns {Promise<Uint8Array>}
*/
async function encryptWithKey (data, key) { // eslint-disable-line require-await
const nonce = crypto.randomBytes(nonceLength)
// Create the cipher instance.
const cipher = crypto.createCipheriv(algorithm, key, nonce)
// Encrypt and prepend nonce.
const ciphertext = uint8ArrayConcat([cipher.update(data), cipher.final()])
return uint8ArrayConcat([nonce, ciphertext, cipher.getAuthTag()])
}
/**
* Uses the provided password to derive a pbkdf2 key. The key
* will then be used to encrypt the data.
*
* @param {Uint8Array} data The data to decrypt
* @param {string|Uint8Array} password A plain password
* @returns {Promise<Uint8Array>}
*/
async function encrypt (data, password) { // eslint-disable-line require-await
// Generate a 128-bit salt using a CSPRNG.
const salt = crypto.randomBytes(saltLength)
if (typeof password === 'string' || password instanceof String) {
password = uint8ArrayFromString(password)
}
// Derive a key using PBKDF2.
const key = crypto.pbkdf2Sync(password, salt, iterations, keyLength, digest)
// Encrypt and prepend salt.
return uint8ArrayConcat([salt, await encryptWithKey(Uint8Array.from(data), key)])
}
/**
* Decrypts the given cipher text with the provided key. The `key` should
* be a cryptographically safe key and not a plaintext password. To use
* a plaintext password, use `decrypt`. The options used to create
* this decryption cipher must be the same as those used to create
* the encryption cipher.
*
* @private
* @param {Uint8Array} ciphertextAndNonce The data to decrypt
* @param {Uint8Array} key
* @returns {Promise<Uint8Array>}
*/
async function decryptWithKey (ciphertextAndNonce, key) { // eslint-disable-line require-await
// Create Uint8Arrays of nonce, ciphertext and tag.
const nonce = ciphertextAndNonce.slice(0, nonceLength)
const ciphertext = ciphertextAndNonce.slice(nonceLength, ciphertextAndNonce.length - algorithmTagLength)
const tag = ciphertextAndNonce.slice(ciphertext.length + nonceLength)
// Create the cipher instance.
const cipher = crypto.createDecipheriv(algorithm, key, nonce)
// Decrypt and return result.
cipher.setAuthTag(tag)
return uint8ArrayConcat([cipher.update(ciphertext), cipher.final()])
}
/**
* Uses the provided password to derive a pbkdf2 key. The key
* will then be used to decrypt the data. The options used to create
* this decryption cipher must be the same as those used to create
* the encryption cipher.
*
* @param {Uint8Array} data The data to decrypt
* @param {string|Uint8Array} password A plain password
*/
async function decrypt (data, password) { // eslint-disable-line require-await
// Create Uint8Arrays of salt and ciphertextAndNonce.
const salt = data.slice(0, saltLength)
const ciphertextAndNonce = data.slice(saltLength)
if (typeof password === 'string' || password instanceof String) {
password = uint8ArrayFromString(password)
}
// Derive the key using PBKDF2.
const key = crypto.pbkdf2Sync(password, salt, iterations, keyLength, digest)
// Decrypt and return result.
return decryptWithKey(ciphertextAndNonce, key)
}
return {
encrypt,
decrypt
}
}
module.exports = {
create
}

View File

@ -1,5 +1,5 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
const webcrypto = require('../webcrypto') const webcrypto = require('../webcrypto')
const lengths = require('./lengths') const lengths = require('./lengths')
@ -10,8 +10,7 @@ const hashTypes = {
} }
const sign = async (key, data) => { const sign = async (key, data) => {
const buf = await webcrypto.get().subtle.sign({ name: 'HMAC' }, key, data) return Buffer.from(await webcrypto.get().subtle.sign({ name: 'HMAC' }, key, data))
return new Uint8Array(buf, buf.byteOffset, buf.byteLength)
} }
exports.create = async function (hashType, secret) { exports.create = async function (hashType, secret) {

173
src/index.d.ts vendored
View File

@ -1,3 +1,5 @@
/// <reference types="node" />
/** /**
* Supported key types. * Supported key types.
*/ */
@ -29,15 +31,15 @@ export namespace aes {
* AES Cipher in CTR mode. * AES Cipher in CTR mode.
*/ */
interface Cipher { interface Cipher {
encrypt(data: Uint8Array): Promise<Uint8Array>; encrypt(data: Buffer): Promise<Buffer>;
decrypt(data: Uint8Array): Promise<Uint8Array>; decrypt(data: Buffer): Promise<Buffer>;
} }
/** /**
* Create a new AES Cipher. * Create a new AES Cipher.
* @param key The key, if length 16 then AES 128 is used. For length 32, AES 256 is used. * @param key The key, if length 16 then AES 128 is used. For length 32, AES 256 is used.
* @param iv Must have length 16. * @param iv Must have length 16.
*/ */
function create(key: Uint8Array, iv: Uint8Array): Promise<Cipher>; function create(key: Buffer, iv: Buffer): Promise<Cipher>;
} }
/** /**
@ -51,7 +53,7 @@ export namespace hmac {
* HMAC Digest. * HMAC Digest.
*/ */
interface Digest { interface Digest {
digest(data: Uint8Array): Promise<Uint8Array>; digest(data: Buffer): Promise<Buffer>;
length: 20 | 32 | 64 | number; length: 20 | 32 | 64 | number;
} }
/** /**
@ -59,7 +61,7 @@ export namespace hmac {
*/ */
function create( function create(
hash: "SHA1" | "SHA256" | "SHA512" | string, hash: "SHA1" | "SHA256" | "SHA512" | string,
secret: Uint8Array secret: Buffer
): Promise<Digest>; ): Promise<Digest>;
} }
@ -67,11 +69,11 @@ export namespace hmac {
* Generic public key interface. * Generic public key interface.
*/ */
export interface PublicKey { export interface PublicKey {
readonly bytes: Uint8Array; readonly bytes: Buffer;
verify(data: Uint8Array, sig: Uint8Array): Promise<boolean>; verify(data: Buffer, sig: Buffer): Promise<boolean>;
marshal(): Uint8Array; marshal(): Buffer;
equals(key: PublicKey): boolean; equals(key: PublicKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
} }
/** /**
@ -79,11 +81,11 @@ export interface PublicKey {
*/ */
export interface PrivateKey { export interface PrivateKey {
readonly public: PublicKey; readonly public: PublicKey;
readonly bytes: Uint8Array; readonly bytes: Buffer;
sign(data: Uint8Array): Promise<Uint8Array>; sign(data: Buffer): Promise<Buffer>;
marshal(): Uint8Array; marshal(): Buffer;
equals(key: PrivateKey): boolean; equals(key: PrivateKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
/** /**
* Gets the ID of the key. * Gets the ID of the key.
* *
@ -92,17 +94,13 @@ export interface PrivateKey {
* of the PKCS SubjectPublicKeyInfo. * of the PKCS SubjectPublicKeyInfo.
*/ */
id(): Promise<string>; id(): Promise<string>;
/**
* Exports the password protected key in the format specified.
*/
export(password: string, format?: "pkcs-8" | string): Promise<string>;
} }
export interface Keystretcher { export interface Keystretcher {
(res: Uint8Array): Keystretcher; (res: Buffer): Keystretcher;
iv: Uint8Array; iv: Buffer;
cipherKey: Uint8Array; cipherKey: Buffer;
macKey: Uint8Array; macKey: Buffer;
} }
export interface StretchPair { export interface StretchPair {
@ -125,94 +123,101 @@ export namespace keys {
export namespace supportedKeys { export namespace supportedKeys {
namespace rsa { namespace rsa {
class RsaPublicKey implements PublicKey { class RsaPublicKey implements PublicKey {
constructor(key: Uint8Array); constructor(key: Buffer);
readonly bytes: Uint8Array; readonly bytes: Buffer;
verify(data: Uint8Array, sig: Uint8Array): Promise<boolean>; verify(data: Buffer, sig: Buffer): Promise<boolean>;
marshal(): Uint8Array; marshal(): Buffer;
encrypt(bytes: Uint8Array): Uint8Array; encrypt(bytes: Buffer): Buffer;
equals(key: PublicKey): boolean; equals(key: PublicKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
} }
// Type alias for export method
export type KeyInfo = any;
class RsaPrivateKey implements PrivateKey { class RsaPrivateKey implements PrivateKey {
constructor(key: any, publicKey: Uint8Array); constructor(key: any, publicKey: Buffer);
readonly public: RsaPublicKey; readonly public: RsaPublicKey;
readonly bytes: Uint8Array; readonly bytes: Buffer;
genSecret(): Uint8Array; genSecret(): Buffer;
sign(data: Uint8Array): Promise<Uint8Array>; sign(data: Buffer): Promise<Buffer>;
decrypt(bytes: Uint8Array): Uint8Array; decrypt(bytes: Buffer): Buffer;
marshal(): Uint8Array; marshal(): Buffer;
equals(key: PrivateKey): boolean; equals(key: PrivateKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
id(): Promise<string>; id(): Promise<string>;
export(password: string, format?: string): Promise<string>; /**
* Exports the key into a password protected PEM format
*
* @param password The password to read the encrypted PEM
* @param format Defaults to 'pkcs-8'.
*/
export(password: string, format?: "pkcs-8" | string): KeyInfo;
} }
function unmarshalRsaPublicKey(buf: Uint8Array): RsaPublicKey; function unmarshalRsaPublicKey(buf: Buffer): RsaPublicKey;
function unmarshalRsaPrivateKey(buf: Uint8Array): Promise<RsaPrivateKey>; function unmarshalRsaPrivateKey(buf: Buffer): Promise<RsaPrivateKey>;
function generateKeyPair(bits: number): Promise<RsaPrivateKey>; function generateKeyPair(bits: number): Promise<RsaPrivateKey>;
function fromJwk(jwk: Uint8Array): Promise<RsaPrivateKey>; function fromJwk(jwk: Buffer): Promise<RsaPrivateKey>;
} }
namespace ed25519 { namespace ed25519 {
class Ed25519PublicKey implements PublicKey { class Ed25519PublicKey implements PublicKey {
constructor(key: Uint8Array); constructor(key: Buffer);
readonly bytes: Uint8Array; readonly bytes: Buffer;
verify(data: Uint8Array, sig: Uint8Array): Promise<boolean>; verify(data: Buffer, sig: Buffer): Promise<boolean>;
marshal(): Uint8Array; marshal(): Buffer;
encrypt(bytes: Uint8Array): Uint8Array; encrypt(bytes: Buffer): Buffer;
equals(key: PublicKey): boolean; equals(key: PublicKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
} }
class Ed25519PrivateKey implements PrivateKey { class Ed25519PrivateKey implements PrivateKey {
constructor(key: Uint8Array, publicKey: Uint8Array); constructor(key: Buffer, publicKey: Buffer);
readonly public: Ed25519PublicKey; readonly public: Ed25519PublicKey;
readonly bytes: Uint8Array; readonly bytes: Buffer;
sign(data: Uint8Array): Promise<Uint8Array>; sign(data: Buffer): Promise<Buffer>;
marshal(): Uint8Array; marshal(): Buffer;
equals(key: PrivateKey): boolean; equals(key: PrivateKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
id(): Promise<string>; id(): Promise<string>;
export(password: string, format?: string): Promise<string>;
} }
function unmarshalEd25519PrivateKey( function unmarshalEd25519PrivateKey(
buf: Uint8Array buf: Buffer
): Promise<Ed25519PrivateKey>; ): Promise<Ed25519PrivateKey>;
function unmarshalEd25519PublicKey(buf: Uint8Array): Ed25519PublicKey; function unmarshalEd25519PublicKey(buf: Buffer): Ed25519PublicKey;
function generateKeyPair(): Promise<Ed25519PrivateKey>; function generateKeyPair(): Promise<Ed25519PrivateKey>;
function generateKeyPairFromSeed( function generateKeyPairFromSeed(
seed: Uint8Array seed: Buffer
): Promise<Ed25519PrivateKey>; ): Promise<Ed25519PrivateKey>;
} }
namespace secp256k1 { namespace secp256k1 {
class Secp256k1PublicKey implements PublicKey { class Secp256k1PublicKey implements PublicKey {
constructor(key: Uint8Array); constructor(key: Buffer);
readonly bytes: Uint8Array; readonly bytes: Buffer;
verify(data: Uint8Array, sig: Uint8Array): Promise<boolean>; verify(data: Buffer, sig: Buffer): Promise<boolean>;
marshal(): Uint8Array; marshal(): Buffer;
encrypt(bytes: Uint8Array): Uint8Array; encrypt(bytes: Buffer): Buffer;
equals(key: PublicKey): boolean; equals(key: PublicKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
} }
class Secp256k1PrivateKey implements PrivateKey { class Secp256k1PrivateKey implements PrivateKey {
constructor(key: Uint8Array, publicKey: Uint8Array); constructor(key: Uint8Array | Buffer, publicKey: Uint8Array | Buffer);
readonly public: Secp256k1PublicKey; readonly public: Secp256k1PublicKey;
readonly bytes: Uint8Array; readonly bytes: Buffer;
sign(data: Uint8Array): Promise<Uint8Array>; sign(data: Buffer): Promise<Buffer>;
marshal(): Uint8Array; marshal(): Buffer;
equals(key: PrivateKey): boolean; equals(key: PrivateKey): boolean;
hash(): Promise<Uint8Array>; hash(): Promise<Buffer>;
id(): Promise<string>; id(): Promise<string>;
export(password: string, format?: string): Promise<string>;
} }
function unmarshalSecp256k1PrivateKey( function unmarshalSecp256k1PrivateKey(
bytes: Uint8Array bytes: Buffer
): Promise<Secp256k1PrivateKey>; ): Promise<Secp256k1PrivateKey>;
function unmarshalSecp256k1PublicKey(bytes: Uint8Array): Secp256k1PublicKey; function unmarshalSecp256k1PublicKey(bytes: Buffer): Secp256k1PublicKey;
function generateKeyPair(): Promise<Secp256k1PrivateKey>; function generateKeyPair(): Promise<Secp256k1PrivateKey>;
} }
} }
@ -229,14 +234,16 @@ export namespace keys {
bits: number bits: number
): Promise<PrivateKey>; ): Promise<PrivateKey>;
export function generateKeyPair( export function generateKeyPair(
type: "Ed25519" type: "Ed25519",
bits: number
): Promise<keys.supportedKeys.ed25519.Ed25519PrivateKey>; ): Promise<keys.supportedKeys.ed25519.Ed25519PrivateKey>;
export function generateKeyPair( export function generateKeyPair(
type: "RSA", type: "RSA",
bits: number bits: number
): Promise<keys.supportedKeys.rsa.RsaPrivateKey>; ): Promise<keys.supportedKeys.rsa.RsaPrivateKey>;
export function generateKeyPair( export function generateKeyPair(
type: "secp256k1" type: "secp256k1",
bits: number
): Promise<keys.supportedKeys.secp256k1.Secp256k1PrivateKey>; ): Promise<keys.supportedKeys.secp256k1.Secp256k1PrivateKey>;
/** /**
@ -264,8 +271,8 @@ export namespace keys {
export function generateEphemeralKeyPair( export function generateEphemeralKeyPair(
curve: CurveType | string curve: CurveType | string
): Promise<{ ): Promise<{
key: Uint8Array; key: Buffer;
genSharedKey: (theirPub: Uint8Array, forcePrivate?: any) => Promise<Uint8Array>; genSharedKey: (theirPub: Buffer, forcePrivate?: any) => Promise<Buffer>;
}>; }>;
/** /**
@ -277,49 +284,49 @@ export namespace keys {
export function keyStretcher( export function keyStretcher(
cipherType: CipherType | string, cipherType: CipherType | string,
hashType: HashType | string, hashType: HashType | string,
secret: Uint8Array | string secret: Buffer | string
): Promise<StretchPair>; ): Promise<StretchPair>;
/** /**
* Converts a protobuf serialized public key into its representative object. * Converts a protobuf serialized public key into its representative object.
* @param buf The protobuf serialized public key. * @param buf The protobuf serialized public key.
*/ */
export function unmarshalPublicKey(buf: Uint8Array): PublicKey; export function unmarshalPublicKey(buf: Buffer): PublicKey;
/** /**
* Converts a public key object into a protobuf serialized public key. * Converts a public key object into a protobuf serialized public key.
* @param key An RSA, Ed25519, or Secp256k1 public key object. * @param key An RSA, Ed25519, or Secp256k1 public key object.
* @param type One of the supported key types. * @param type One of the supported key types.
*/ */
export function marshalPublicKey(key: PublicKey, type?: KeyType | string): Uint8Array; export function marshalPublicKey(key: PublicKey, type?: KeyType | string): Buffer;
/** /**
* Converts a protobuf serialized private key into its representative object. * Converts a protobuf serialized private key into its representative object.
* @param buf The protobuf serialized private key. * @param buf The protobuf serialized private key.
*/ */
export function unmarshalPrivateKey(buf: Uint8Array): Promise<PrivateKey>; export function unmarshalPrivateKey(buf: Buffer): Promise<PrivateKey>;
/** /**
* Converts a private key object into a protobuf serialized private key. * Converts a private key object into a protobuf serialized private key.
* @param key An RSA, Ed25519, or Secp256k1 private key object. * @param key An RSA, Ed25519, or Secp256k1 private key object.
* @param type One of the supported key types. * @param type One of the supported key types.
*/ */
export function marshalPrivateKey(key: PrivateKey, type?: KeyType | string): Uint8Array; export function marshalPrivateKey(key: PrivateKey, type?: KeyType | string): Buffer;
/** /**
* Converts a PEM password protected private key into its representative object. * Converts a PEM password protected private key into its representative object.
* @param pem Password protected private key in PEM format. * @param pem Password protected private key in PEM format.
* @param password The password used to protect the key. * @param password The password used to protect the key.
*/ */
function _import(pem: string, password: string, format?: string): Promise<supportedKeys.rsa.RsaPrivateKey>; function _import(pem: string, password: string): Promise<supportedKeys.rsa.RsaPrivateKey>;
export { _import as import }; export { _import as import };
} }
/** /**
* Generates a Uint8Array populated by random bytes. * Generates a Buffer populated by random bytes.
* @param The size of the random bytes Uint8Array. * @param The size of the random bytes Buffer.
*/ */
export function randomBytes(number: number): Uint8Array; export function randomBytes(number: number): Buffer;
/** /**
* Computes the Password-Based Key Derivation Function 2. * Computes the Password-Based Key Derivation Function 2.
@ -330,9 +337,9 @@ export function randomBytes(number: number): Uint8Array;
* @param hash The hash name ('sha1', 'sha2-512, ...) * @param hash The hash name ('sha1', 'sha2-512, ...)
*/ */
export function pbkdf2( export function pbkdf2(
password: string | Uint8Array, password: string | Buffer,
salt: string | Uint8Array, salt: string | Buffer,
iterations: number, iterations: number,
keySize: number, keySize: number,
hash: string hash: string
): Uint8Array; ): Buffer;

View File

@ -1,12 +1,10 @@
'use strict' 'use strict'
const errcode = require('err-code') const errcode = require('err-code')
const { Buffer } = require('buffer')
const webcrypto = require('../webcrypto') const webcrypto = require('../webcrypto')
const { base64urlToBuffer } = require('../util') const { bufferToBase64url, base64urlToBuffer } = require('../util')
const validateCurveType = require('./validate-curve-type') const validateCurveType = require('./validate-curve-type')
const uint8ArrayToString = require('uint8arrays/to-string')
const uint8ArrayConcat = require('uint8arrays/concat')
const uint8ArrayEquals = require('uint8arrays/equals')
const bits = { const bits = {
'P-256': 256, 'P-256': 256,
@ -58,7 +56,7 @@ exports.generateEphmeralKeyPair = async function (curve) {
privateKey privateKey
] ]
const buffer = await webcrypto.get().subtle.deriveBits( return Buffer.from(await webcrypto.get().subtle.deriveBits(
{ {
name: 'ECDH', name: 'ECDH',
namedCurve: curve, namedCurve: curve,
@ -66,9 +64,7 @@ exports.generateEphmeralKeyPair = async function (curve) {
}, },
keys[1], keys[1],
bits[curve] bits[curve]
) ))
return new Uint8Array(buffer, buffer.byteOffset, buffer.byteLength)
} }
const publicKey = await webcrypto.get().subtle.exportKey('jwk', pair.publicKey) const publicKey = await webcrypto.get().subtle.exportKey('jwk', pair.publicKey)
@ -91,8 +87,8 @@ const curveLengths = {
function marshalPublicKey (jwk) { function marshalPublicKey (jwk) {
const byteLen = curveLengths[jwk.crv] const byteLen = curveLengths[jwk.crv]
return uint8ArrayConcat([ return Buffer.concat([
Uint8Array.from([4]), // uncompressed point Buffer.from([4]), // uncompressed point
base64urlToBuffer(jwk.x, byteLen), base64urlToBuffer(jwk.x, byteLen),
base64urlToBuffer(jwk.y, byteLen) base64urlToBuffer(jwk.y, byteLen)
], 1 + byteLen * 2) ], 1 + byteLen * 2)
@ -102,20 +98,20 @@ function marshalPublicKey (jwk) {
function unmarshalPublicKey (curve, key) { function unmarshalPublicKey (curve, key) {
const byteLen = curveLengths[curve] const byteLen = curveLengths[curve]
if (uint8ArrayEquals(!key.slice(0, 1), Uint8Array.from([4]))) { if (!key.slice(0, 1).equals(Buffer.from([4]))) {
throw errcode(new Error('Cannot unmarshal public key - invalid key format'), 'ERR_INVALID_KEY_FORMAT') throw errcode(new Error('Cannot unmarshal public key - invalid key format'), 'ERR_INVALID_KEY_FORMAT')
} }
return { return {
kty: 'EC', kty: 'EC',
crv: curve, crv: curve,
x: uint8ArrayToString(key.slice(1, byteLen + 1), 'base64url'), x: bufferToBase64url(key.slice(1, byteLen + 1), byteLen),
y: uint8ArrayToString(key.slice(1 + byteLen), 'base64url'), y: bufferToBase64url(key.slice(1 + byteLen), byteLen),
ext: true ext: true
} }
} }
const unmarshalPrivateKey = (curve, key) => ({ const unmarshalPrivateKey = (curve, key) => ({
...unmarshalPublicKey(curve, key.public), ...unmarshalPublicKey(curve, key.public),
d: uint8ArrayToString(key.private, 'base64url') d: bufferToBase64url(key.private)
}) })

View File

@ -1,13 +1,13 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
const sha = require('multihashing-async/src/sha') const sha = require('multihashing-async/src/sha')
const protobuf = require('protons') const protobuf = require('protons')
const multibase = require('multibase')
const errcode = require('err-code') const errcode = require('err-code')
const uint8ArrayEquals = require('uint8arrays/equals')
const mh = require('multihashes')
const crypto = require('./ed25519') const crypto = require('./ed25519')
const pbm = protobuf(require('./keys.proto')) const pbm = protobuf(require('./keys.proto'))
const exporter = require('./exporter')
class Ed25519PublicKey { class Ed25519PublicKey {
constructor (key) { constructor (key) {
@ -19,7 +19,7 @@ class Ed25519PublicKey {
} }
marshal () { marshal () {
return this._key return Buffer.from(this._key)
} }
get bytes () { get bytes () {
@ -30,7 +30,7 @@ class Ed25519PublicKey {
} }
equals (key) { equals (key) {
return uint8ArrayEquals(this.bytes, key.bytes) return this.bytes.equals(key.bytes)
} }
async hash () { // eslint-disable-line require-await async hash () { // eslint-disable-line require-await
@ -39,8 +39,8 @@ class Ed25519PublicKey {
} }
class Ed25519PrivateKey { class Ed25519PrivateKey {
// key - 64 byte Uint8Array containing private key // key - 64 byte Uint8Array or Buffer containing private key
// publicKey - 32 byte Uint8Array containing public key // publicKey - 32 byte Uint8Array or Buffer containing public key
constructor (key, publicKey) { constructor (key, publicKey) {
this._key = ensureKey(key, crypto.privateKeyLength) this._key = ensureKey(key, crypto.privateKeyLength)
this._publicKey = ensureKey(publicKey, crypto.publicKeyLength) this._publicKey = ensureKey(publicKey, crypto.publicKeyLength)
@ -55,7 +55,7 @@ class Ed25519PrivateKey {
} }
marshal () { marshal () {
return this._key return Buffer.concat([Buffer.from(this._key), Buffer.from(this._publicKey)])
} }
get bytes () { get bytes () {
@ -66,7 +66,7 @@ class Ed25519PrivateKey {
} }
equals (key) { equals (key) {
return uint8ArrayEquals(this.bytes, key.bytes) return this.bytes.equals(key.bytes)
} }
async hash () { // eslint-disable-line require-await async hash () { // eslint-disable-line require-await
@ -83,41 +83,18 @@ class Ed25519PrivateKey {
* @returns {Promise<String>} * @returns {Promise<String>}
*/ */
async id () { async id () {
const encoding = mh.encode(this.public.bytes, 'identity') const hash = await this.public.hash()
return await mh.toB58String(encoding) return multibase.encode('base58btc', hash).toString().slice(1)
}
/**
* Exports the key into a password protected `format`
*
* @param {string} password - The password to encrypt the key
* @param {string} [format=libp2p-key] - The format in which to export as
* @returns {Promise<Uint8Array>} The encrypted private key
*/
async export (password, format = 'libp2p-key') { // eslint-disable-line require-await
if (format === 'libp2p-key') {
return exporter.export(this.bytes, password)
} else {
throw errcode(new Error(`export format '${format}' is not supported`), 'ERR_INVALID_EXPORT_FORMAT')
}
} }
} }
function unmarshalEd25519PrivateKey (bytes) { function unmarshalEd25519PrivateKey (bytes) {
// Try the old, redundant public key version
if (bytes.length > crypto.privateKeyLength) {
bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength) bytes = ensureKey(bytes, crypto.privateKeyLength + crypto.publicKeyLength)
const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength) const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength)
const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length) const publicKeyBytes = bytes.slice(crypto.privateKeyLength, bytes.length)
return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes) return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes)
} }
bytes = ensureKey(bytes, crypto.privateKeyLength)
const privateKeyBytes = bytes.slice(0, crypto.privateKeyLength)
const publicKeyBytes = bytes.slice(crypto.publicKeyLength)
return new Ed25519PrivateKey(privateKeyBytes, publicKeyBytes)
}
function unmarshalEd25519PublicKey (bytes) { function unmarshalEd25519PublicKey (bytes) {
bytes = ensureKey(bytes, crypto.publicKeyLength) bytes = ensureKey(bytes, crypto.publicKeyLength)
return new Ed25519PublicKey(bytes) return new Ed25519PublicKey(bytes)
@ -134,9 +111,11 @@ async function generateKeyPairFromSeed (seed) {
} }
function ensureKey (key, length) { function ensureKey (key, length) {
key = Uint8Array.from(key || []) if (Buffer.isBuffer(key)) {
if (key.length !== length) { key = new Uint8Array(key)
throw errcode(new Error(`Key must be a Uint8Array of length ${length}, got ${key.length}`), 'ERR_INVALID_KEY_TYPE') }
if (!(key instanceof Uint8Array) || key.length !== length) {
throw errcode(new Error('Key must be a Uint8Array or Buffer of length ' + length), 'ERR_INVALID_KEY_TYPE')
} }
return key return key
} }

View File

@ -16,7 +16,7 @@ exports.generateKeyFromSeed = async function (seed) { // eslint-disable-line req
exports.hashAndSign = async function (key, msg) { // eslint-disable-line require-await exports.hashAndSign = async function (key, msg) { // eslint-disable-line require-await
return forge.pki.ed25519.sign({ message: msg, privateKey: key }) return forge.pki.ed25519.sign({ message: msg, privateKey: key })
// return Uint8Array.from(nacl.sign.detached(msg, key)) // return Buffer.from(nacl.sign.detached(msg, key))
} }
exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line require-await exports.hashAndVerify = async function (key, sig, msg) { // eslint-disable-line require-await

View File

@ -1,22 +0,0 @@
'use strict'
const multibase = require('multibase')
const ciphers = require('../ciphers/aes-gcm')
module.exports = {
/**
* Exports the given PrivateKey as a base64 encoded string.
* The PrivateKey is encrypted via a password derived PBKDF2 key
* leveraging the aes-gcm cipher algorithm.
*
* @param {Uint8Array} privateKey The PrivateKey protobuf
* @param {string} password
* @returns {Promise<string>} A base64 encoded string
*/
export: async function (privateKey, password) {
const cipher = ciphers.create()
const encryptedKey = await cipher.encrypt(privateKey, password)
const base64 = multibase.names.base64
return base64.encode(encryptedKey)
}
}

View File

@ -1,22 +0,0 @@
'use strict'
const multibase = require('multibase')
const ciphers = require('../ciphers/aes-gcm')
module.exports = {
/**
* Attempts to decrypt a base64 encoded PrivateKey string
* with the given password. The privateKey must have been exported
* using the same password and underlying cipher (aes-gcm)
*
* @param {string} privateKey A base64 encoded encrypted key
* @param {string} password
* @returns {Promise<Uint8Array>} The private key protobuf
*/
import: async function (privateKey, password) {
const base64 = multibase.names.base64
const encryptedKey = base64.decode(privateKey)
const cipher = ciphers.create()
return await cipher.decrypt(encryptedKey, password)
}
}

View File

@ -1,21 +1,19 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
const protobuf = require('protons') const protobuf = require('protons')
const keysPBM = protobuf(require('./keys.proto')) const keysPBM = protobuf(require('./keys.proto'))
require('node-forge/lib/asn1') require('node-forge/lib/asn1')
require('node-forge/lib/pbe') require('node-forge/lib/pbe')
const forge = require('node-forge/lib/forge') const forge = require('node-forge/lib/forge')
const errcode = require('err-code') const errcode = require('err-code')
const uint8ArrayFromString = require('uint8arrays/from-string')
const importer = require('./importer')
exports = module.exports 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('./secp256k1-class')(keysPBM, require('../random-bytes')) secp256k1: require('libp2p-crypto-secp256k1')(keysPBM, require('../random-bytes'))
} }
exports.supportedKeys = supportedKeys exports.supportedKeys = supportedKeys
@ -111,25 +109,12 @@ exports.marshalPrivateKey = (key, type) => {
return key.bytes return key.bytes
} }
/** exports.import = async (pem, password) => { // eslint-disable-line require-await
* const key = forge.pki.decryptRsaPrivateKey(pem, password)
* @param {string} encryptedKey
* @param {string} password
*/
exports.import = async (encryptedKey, password) => { // eslint-disable-line require-await
try {
const key = await importer.import(encryptedKey, password)
return exports.unmarshalPrivateKey(key)
} catch (_) {
// Ignore and try the old pem decrypt
}
// Only rsa supports pem right now
const key = forge.pki.decryptRsaPrivateKey(encryptedKey, password)
if (key === null) { if (key === null) {
throw errcode(new Error('Cannot read the key, most likely the password is wrong or not a RSA key'), 'ERR_CANNOT_DECRYPT_PEM') throw errcode(new Error('Cannot read the key, most likely the password is wrong or not a RSA key'), 'ERR_CANNOT_DECRYPT_PEM')
} }
let der = forge.asn1.toDer(forge.pki.privateKeyToAsn1(key)) let der = forge.asn1.toDer(forge.pki.privateKeyToAsn1(key))
der = uint8ArrayFromString(der.getBytes(), 'ascii') der = Buffer.from(der.getBytes(), 'binary')
return supportedKeys.rsa.unmarshalRsaPrivateKey(der) return supportedKeys.rsa.unmarshalRsaPrivateKey(der)
} }

View File

@ -1,8 +1,6 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
const errcode = require('err-code') const errcode = require('err-code')
const uint8ArrayConcat = require('uint8arrays/concat')
const uint8ArrayFromString = require('uint8arrays/from-string')
const hmac = require('../hmac') const hmac = require('../hmac')
const cipherMap = { const cipherMap = {
@ -37,7 +35,7 @@ module.exports = async (cipherType, hash, secret) => {
const cipherKeySize = cipher.keySize const cipherKeySize = cipher.keySize
const ivSize = cipher.ivSize const ivSize = cipher.ivSize
const hmacKeySize = 20 const hmacKeySize = 20
const seed = uint8ArrayFromString('key expansion') const seed = Buffer.from('key expansion')
const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize) const resultLength = 2 * (ivSize + cipherKeySize + hmacKeySize)
const m = await hmac.create(hash, secret) const m = await hmac.create(hash, secret)
@ -47,7 +45,7 @@ module.exports = async (cipherType, hash, secret) => {
let j = 0 let j = 0
while (j < resultLength) { while (j < resultLength) {
const b = await m.digest(uint8ArrayConcat([a, seed])) const b = await m.digest(Buffer.concat([a, seed]))
let todo = b.length let todo = b.length
if (j + todo > resultLength) { if (j + todo > resultLength) {
@ -60,7 +58,7 @@ module.exports = async (cipherType, hash, secret) => {
} }
const half = resultLength / 2 const half = resultLength / 2
const resultBuffer = uint8ArrayConcat(result) const resultBuffer = Buffer.concat(result)
const r1 = resultBuffer.slice(0, half) const r1 = resultBuffer.slice(0, half)
const r2 = resultBuffer.slice(half, resultLength) const r2 = resultBuffer.slice(half, resultLength)

View File

@ -1,9 +1,8 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
const webcrypto = require('../webcrypto') const webcrypto = require('../webcrypto')
const randomBytes = require('../random-bytes') const randomBytes = require('../random-bytes')
const uint8ArrayToString = require('uint8arrays/to-string')
const uint8ArrayFromString = require('uint8arrays/from-string')
exports.utils = require('./rsa-utils') exports.utils = require('./rsa-utils')
@ -76,7 +75,7 @@ exports.hashAndSign = async function (key, msg) {
Uint8Array.from(msg) Uint8Array.from(msg)
) )
return new Uint8Array(sig, sig.byteOffset, sig.byteLength) return Buffer.from(sig)
} }
exports.hashAndVerify = async function (key, sig, msg) { exports.hashAndVerify = async function (key, sig, msg) {
@ -130,8 +129,8 @@ RSA encryption/decryption for the browser with webcrypto workarround
Explanation: Explanation:
- Convert JWK to nodeForge - Convert JWK to nodeForge
- Convert msg Uint8Array to nodeForge buffer: ByteBuffer is a "binary-string backed buffer", so let's make our Uint8Array a binary string - Convert msg buffer to nodeForge buffer: ByteBuffer is a "binary-string backed buffer", so let's make our buffer a binary string
- Convert resulting nodeForge buffer to Uint8Array: it returns a binary string, turn that into a Uint8Array - Convert resulting nodeForge buffer to buffer: it returns a binary string, turn that into a uint8array(buffer)
*/ */
@ -139,9 +138,9 @@ const { jwk2pub, jwk2priv } = require('./jwk2pem')
function convertKey (key, pub, msg, handle) { function convertKey (key, pub, msg, handle) {
const fkey = pub ? jwk2pub(key) : jwk2priv(key) const fkey = pub ? jwk2pub(key) : jwk2priv(key)
const fmsg = uint8ArrayToString(Uint8Array.from(msg), 'ascii') const fmsg = Buffer.from(msg).toString('binary')
const fomsg = handle(fmsg, fkey) const fomsg = handle(fmsg, fkey)
return uint8ArrayFromString(fomsg, 'ascii') return Buffer.from(fomsg, 'binary')
} }
exports.encrypt = function (key, msg) { exports.encrypt = function (key, msg) {

View File

@ -2,17 +2,14 @@
const sha = require('multihashing-async/src/sha') const sha = require('multihashing-async/src/sha')
const protobuf = require('protons') const protobuf = require('protons')
const multibase = require('multibase')
const errcode = require('err-code') const errcode = require('err-code')
const uint8ArrayEquals = require('uint8arrays/equals')
const uint8ArrayToString = require('uint8arrays/to-string')
require('node-forge/lib/sha512')
require('node-forge/lib/ed25519')
const forge = require('node-forge/lib/forge')
const crypto = require('./rsa') const crypto = require('./rsa')
const pbm = protobuf(require('./keys.proto')) const pbm = protobuf(require('./keys.proto'))
const exporter = require('./exporter') require('node-forge/lib/sha512')
require('node-forge/lib/ed25519')
const forge = require('node-forge/lib/forge')
class RsaPublicKey { class RsaPublicKey {
constructor (key) { constructor (key) {
@ -39,7 +36,7 @@ class RsaPublicKey {
} }
equals (key) { equals (key) {
return uint8ArrayEquals(this.bytes, key.bytes) return this.bytes.equals(key.bytes)
} }
async hash () { // eslint-disable-line require-await async hash () { // eslint-disable-line require-await
@ -49,7 +46,7 @@ class RsaPublicKey {
class RsaPrivateKey { class RsaPrivateKey {
// key - Object of the jwk format // key - Object of the jwk format
// publicKey - Uint8Array of the spki format // publicKey - Buffer of the spki format
constructor (key, publicKey) { constructor (key, publicKey) {
this._key = key this._key = key
this._publicKey = publicKey this._publicKey = publicKey
@ -87,7 +84,7 @@ class RsaPrivateKey {
} }
equals (key) { equals (key) {
return uint8ArrayEquals(this.bytes, key.bytes) return this.bytes.equals(key.bytes)
} }
async hash () { // eslint-disable-line require-await async hash () { // eslint-disable-line require-await
@ -105,33 +102,35 @@ class RsaPrivateKey {
*/ */
async id () { async id () {
const hash = await this.public.hash() const hash = await this.public.hash()
return uint8ArrayToString(hash, 'base58btc') return multibase.encode('base58btc', hash).toString().slice(1)
} }
/** /**
* Exports the key into a password protected PEM format * Exports the key into a password protected PEM format
* *
* @param {string} password - The password to read the encrypted PEM * @param {string} password - The password to read the encrypted PEM
* @param {string} [format=pkcs-8] - The format in which to export as * @param {string} [format] - Defaults to 'pkcs-8'.
*/ */
async export (password, format = 'pkcs-8') { // eslint-disable-line require-await async export (password, format = 'pkcs-8') { // eslint-disable-line require-await
if (format === 'pkcs-8') { let pem = null
const buffer = new forge.util.ByteBuffer(this.marshal()) const buffer = new forge.util.ByteBuffer(this.marshal())
const asn1 = forge.asn1.fromDer(buffer) const asn1 = forge.asn1.fromDer(buffer)
const privateKey = forge.pki.privateKeyFromAsn1(asn1) const privateKey = forge.pki.privateKeyFromAsn1(asn1)
if (format === 'pkcs-8') {
const options = { const options = {
algorithm: 'aes256', algorithm: 'aes256',
count: 10000, count: 10000,
saltSize: 128 / 8, saltSize: 128 / 8,
prfAlgorithm: 'sha512' prfAlgorithm: 'sha512'
} }
return forge.pki.encryptRsaPrivateKey(privateKey, password, options) pem = forge.pki.encryptRsaPrivateKey(privateKey, password, options)
} else if (format === 'libp2p-key') {
return exporter.export(this.bytes, password)
} else { } else {
throw errcode(new Error(`export format '${format}' is not supported`), 'ERR_INVALID_EXPORT_FORMAT') throw errcode(new Error(`Unknown export format '${format}'. Must be pkcs-8`), 'ERR_INVALID_EXPORT_FORMAT')
} }
return pem
} }
} }

View File

@ -1,15 +1,14 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
require('node-forge/lib/asn1') require('node-forge/lib/asn1')
require('node-forge/lib/rsa') require('node-forge/lib/rsa')
const forge = require('node-forge/lib/forge') const forge = require('node-forge/lib/forge')
const { bigIntegerToUintBase64url, base64urlToBigInteger } = require('./../util') const { bigIntegerToUintBase64url, base64urlToBigInteger } = require('./../util')
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string')
// Convert a PKCS#1 in ASN1 DER format to a JWK key // Convert a PKCS#1 in ASN1 DER format to a JWK key
exports.pkcs1ToJwk = function (bytes) { exports.pkcs1ToJwk = function (bytes) {
const asn1 = forge.asn1.fromDer(uint8ArrayToString(bytes, 'ascii')) const asn1 = forge.asn1.fromDer(bytes.toString('binary'))
const privateKey = forge.pki.privateKeyFromAsn1(asn1) const privateKey = forge.pki.privateKeyFromAsn1(asn1)
// https://tools.ietf.org/html/rfc7518#section-6.3.1 // https://tools.ietf.org/html/rfc7518#section-6.3.1
@ -41,12 +40,12 @@ exports.jwkToPkcs1 = function (jwk) {
qInv: base64urlToBigInteger(jwk.qi) qInv: base64urlToBigInteger(jwk.qi)
}) })
return uint8ArrayFromString(forge.asn1.toDer(asn1).getBytes(), 'ascii') return Buffer.from(forge.asn1.toDer(asn1).getBytes(), 'binary')
} }
// Convert a PKCIX in ASN1 DER format to a JWK key // Convert a PKCIX in ASN1 DER format to a JWK key
exports.pkixToJwk = function (bytes) { exports.pkixToJwk = function (bytes) {
const asn1 = forge.asn1.fromDer(uint8ArrayToString(bytes, 'ascii')) const asn1 = forge.asn1.fromDer(bytes.toString('binary'))
const publicKey = forge.pki.publicKeyFromAsn1(asn1) const publicKey = forge.pki.publicKeyFromAsn1(asn1)
return { return {
@ -65,5 +64,5 @@ exports.jwkToPkix = function (jwk) {
e: base64urlToBigInteger(jwk.e) e: base64urlToBigInteger(jwk.e)
}) })
return uint8ArrayFromString(forge.asn1.toDer(asn1).getBytes(), 'ascii') return Buffer.from(forge.asn1.toDer(asn1).getBytes(), 'binary')
} }

View File

@ -1,128 +0,0 @@
'use strict'
const sha = require('multihashing-async/src/sha')
const errcode = require('err-code')
const uint8ArrayEquals = require('uint8arrays/equals')
const uint8ArrayToString = require('uint8arrays/to-string')
const exporter = require('./exporter')
module.exports = (keysProtobuf, randomBytes, crypto) => {
crypto = crypto || require('./secp256k1')(randomBytes)
class Secp256k1PublicKey {
constructor (key) {
crypto.validatePublicKey(key)
this._key = key
}
verify (data, sig) {
return crypto.hashAndVerify(this._key, sig, data)
}
marshal () {
return crypto.compressPublicKey(this._key)
}
get bytes () {
return keysProtobuf.PublicKey.encode({
Type: keysProtobuf.KeyType.Secp256k1,
Data: this.marshal()
})
}
equals (key) {
return uint8ArrayEquals(this.bytes, key.bytes)
}
hash () {
return sha.multihashing(this.bytes, 'sha2-256')
}
}
class Secp256k1PrivateKey {
constructor (key, publicKey) {
this._key = key
this._publicKey = publicKey || crypto.computePublicKey(key)
crypto.validatePrivateKey(this._key)
crypto.validatePublicKey(this._publicKey)
}
sign (message) {
return crypto.hashAndSign(this._key, message)
}
get public () {
return new Secp256k1PublicKey(this._publicKey)
}
marshal () {
return this._key
}
get bytes () {
return keysProtobuf.PrivateKey.encode({
Type: keysProtobuf.KeyType.Secp256k1,
Data: this.marshal()
})
}
equals (key) {
return uint8ArrayEquals(this.bytes, key.bytes)
}
hash () {
return sha.multihashing(this.bytes, 'sha2-256')
}
/**
* Gets the ID of the key.
*
* The key id is the base58 encoding of the SHA-256 multihash of its public key.
* The public key is a protobuf encoding containing a type and the DER encoding
* of the PKCS SubjectPublicKeyInfo.
*
* @returns {Promise<string>}
*/
async id () {
const hash = await this.public.hash()
return uint8ArrayToString(hash, 'base58btc')
}
/**
* Exports the key into a password protected `format`
*
* @param {string} password - The password to encrypt the key
* @param {string} [format=libp2p-key] - The format in which to export as
* @returns {Promise<string>} The encrypted private key
*/
async export (password, format = 'libp2p-key') { // eslint-disable-line require-await
if (format === 'libp2p-key') {
return exporter.export(this.bytes, password)
} else {
throw errcode(new Error(`export format '${format}' is not supported`), 'ERR_INVALID_EXPORT_FORMAT')
}
}
}
function unmarshalSecp256k1PrivateKey (bytes) {
return new Secp256k1PrivateKey(bytes)
}
function unmarshalSecp256k1PublicKey (bytes) {
return new Secp256k1PublicKey(bytes)
}
async function generateKeyPair () {
const privateKeyBytes = await crypto.generateKey()
return new Secp256k1PrivateKey(privateKeyBytes)
}
return {
Secp256k1PublicKey,
Secp256k1PrivateKey,
unmarshalSecp256k1PrivateKey,
unmarshalSecp256k1PublicKey,
generateKeyPair
}
}

View File

@ -1,69 +0,0 @@
'use strict'
const secp256k1 = require('secp256k1')
const sha = require('multihashing-async/src/sha')
const HASH_ALGORITHM = 'sha2-256'
module.exports = (randomBytes) => {
const privateKeyLength = 32
function generateKey () {
let privateKey
do {
privateKey = randomBytes(32)
} while (!secp256k1.privateKeyVerify(privateKey))
return privateKey
}
async function hashAndSign (key, msg) {
const digest = await sha.digest(msg, HASH_ALGORITHM)
const sig = secp256k1.ecdsaSign(digest, key)
return secp256k1.signatureExport(sig.signature)
}
async function hashAndVerify (key, sig, msg) {
const digest = await sha.digest(msg, HASH_ALGORITHM)
sig = secp256k1.signatureImport(sig)
return secp256k1.ecdsaVerify(sig, digest, key)
}
function compressPublicKey (key) {
if (!secp256k1.publicKeyVerify(key)) {
throw new Error('Invalid public key')
}
return secp256k1.publicKeyConvert(key, true)
}
function decompressPublicKey (key) {
return secp256k1.publicKeyConvert(key, false)
}
function validatePrivateKey (key) {
if (!secp256k1.privateKeyVerify(key)) {
throw new Error('Invalid private key')
}
}
function validatePublicKey (key) {
if (!secp256k1.publicKeyVerify(key)) {
throw new Error('Invalid public key')
}
}
function computePublicKey (privateKey) {
validatePrivateKey(privateKey)
return secp256k1.publicKeyCreate(privateKey)
}
return {
generateKey,
privateKeyLength,
hashAndSign,
hashAndVerify,
compressPublicKey,
decompressPublicKey,
validatePrivateKey,
validatePublicKey,
computePublicKey
}
}

View File

@ -1,15 +1,13 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
require('node-forge/lib/util') require('node-forge/lib/util')
require('node-forge/lib/jsbn') require('node-forge/lib/jsbn')
const forge = require('node-forge/lib/forge') const forge = require('node-forge/lib/forge')
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string')
const uint8ArrayConcat = require('uint8arrays/concat')
exports.bigIntegerToUintBase64url = (num, len) => { exports.bigIntegerToUintBase64url = (num, len) => {
// Call `.abs()` to convert to unsigned // Call `.abs()` to convert to unsigned
let buf = Uint8Array.from(num.abs().toByteArray()) // toByteArray converts to big endian let buf = Buffer.from(num.abs().toByteArray()) // toByteArray converts to big endian
// toByteArray() gives us back a signed array, which will include a leading 0 // toByteArray() gives us back a signed array, which will include a leading 0
// byte if the most significant bit of the number is 1: // byte if the most significant bit of the number is 1:
@ -19,24 +17,38 @@ exports.bigIntegerToUintBase64url = (num, len) => {
if (len != null) { if (len != null) {
if (buf.length > len) throw new Error('byte array longer than desired length') if (buf.length > len) throw new Error('byte array longer than desired length')
buf = uint8ArrayConcat([new Uint8Array(len - buf.length), buf]) buf = Buffer.concat([Buffer.alloc(len - buf.length), buf])
} }
return uint8ArrayToString(buf, 'base64url') return exports.bufferToBase64url(buf)
}
// Convert a Buffer to a base64 encoded string without padding
// Adapted from https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#appendix-C
exports.bufferToBase64url = buf => {
return buf
.toString('base64')
.split('=')[0] // Remove any trailing '='s
.replace(/\+/g, '-') // 62nd char of encoding
.replace(/\//g, '_') // 63rd char of encoding
} }
// Convert a base64url encoded string to a BigInteger // Convert a base64url encoded string to a BigInteger
exports.base64urlToBigInteger = str => { exports.base64urlToBigInteger = str => {
const buf = exports.base64urlToBuffer(str) const buf = exports.base64urlToBuffer(str)
return new forge.jsbn.BigInteger(uint8ArrayToString(buf, 'base16'), 16) return new forge.jsbn.BigInteger(buf.toString('hex'), 16)
} }
exports.base64urlToBuffer = (str, len) => { exports.base64urlToBuffer = (str, len) => {
let buf = uint8ArrayFromString(str, 'base64urlpad') str = (str + '==='.slice((str.length + 3) % 4))
.replace(/-/g, '+')
.replace(/_/g, '/')
let buf = Buffer.from(str, 'base64')
if (len != null) { if (len != null) {
if (buf.length > len) throw new Error('byte array longer than desired length') if (buf.length > len) throw new Error('byte array longer than desired length')
buf = uint8ArrayConcat([new Uint8Array(len - buf.length), buf]) buf = Buffer.concat([Buffer.alloc(len - buf.length), buf])
} }
return buf return buf

View File

@ -2,7 +2,7 @@
/* eslint-disable valid-jsdoc */ /* eslint-disable valid-jsdoc */
/* 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
@ -23,10 +23,10 @@ const bytes = {
describe('AES-CTR', () => { describe('AES-CTR', () => {
Object.keys(bytes).forEach((byte) => { Object.keys(bytes).forEach((byte) => {
it(`${bytes[byte]} - encrypt and decrypt`, async () => { it(`${bytes[byte]} - encrypt and decrypt`, async () => {
const key = new Uint8Array(parseInt(byte, 10)) const key = Buffer.alloc(parseInt(byte, 10))
key.fill(5) key.fill(5)
const iv = new Uint8Array(16) const iv = Buffer.alloc(16)
iv.fill(1) iv.fill(1)
const cipher = await crypto.aes.create(key, iv) const cipher = await crypto.aes.create(key, iv)
@ -41,18 +41,18 @@ describe('AES-CTR', () => {
Object.keys(bytes).forEach((byte) => { Object.keys(bytes).forEach((byte) => {
it(`${bytes[byte]} - fixed - encrypt and decrypt`, async () => { it(`${bytes[byte]} - fixed - encrypt and decrypt`, async () => {
const key = new Uint8Array(parseInt(byte, 10)) const key = Buffer.alloc(parseInt(byte, 10))
key.fill(5) key.fill(5)
const iv = new Uint8Array(16) const iv = Buffer.alloc(16)
iv.fill(1) iv.fill(1)
const cipher = await crypto.aes.create(key, iv) const cipher = await crypto.aes.create(key, iv)
for (let i = 0; i < fixtures[byte].inputs.length; i++) { for (let i = 0; i < fixtures[byte].inputs.length; i++) {
const rawIn = fixtures[byte].inputs[i] const rawIn = fixtures[byte].inputs[i]
const input = Uint8Array.from(rawIn.data) const input = Buffer.from(rawIn)
const output = Uint8Array.from(fixtures[byte].outputs[i].data) const output = Buffer.from(fixtures[byte].outputs[i])
const encrypted = await cipher.encrypt(input) const encrypted = await cipher.encrypt(input)
expect(encrypted).to.have.length(output.length) expect(encrypted).to.have.length(output.length)
expect(encrypted).to.eql(output) expect(encrypted).to.eql(output)
@ -68,18 +68,18 @@ describe('AES-CTR', () => {
} }
it(`${bytes[byte]} - go interop - encrypt and decrypt`, async () => { it(`${bytes[byte]} - go interop - encrypt and decrypt`, async () => {
const key = new Uint8Array(parseInt(byte, 10)) const key = Buffer.alloc(parseInt(byte, 10))
key.fill(5) key.fill(5)
const iv = new Uint8Array(16) const iv = Buffer.alloc(16)
iv.fill(1) iv.fill(1)
const cipher = await crypto.aes.create(key, iv) const cipher = await crypto.aes.create(key, iv)
for (let i = 0; i < goFixtures[byte].inputs.length; i++) { for (let i = 0; i < goFixtures[byte].inputs.length; i++) {
const rawIn = goFixtures[byte].inputs[i] const rawIn = goFixtures[byte].inputs[i]
const input = Uint8Array.from(rawIn) const input = Buffer.from(rawIn)
const output = Uint8Array.from(goFixtures[byte].outputs[i]) const output = Buffer.from(goFixtures[byte].outputs[i])
const encrypted = await cipher.encrypt(input) const encrypted = await cipher.encrypt(input)
expect(encrypted).to.have.length(output.length) expect(encrypted).to.have.length(output.length)
expect(encrypted).to.eql(output) expect(encrypted).to.eql(output)
@ -90,18 +90,18 @@ describe('AES-CTR', () => {
}) })
it('checks key length', () => { it('checks key length', () => {
const key = new Uint8Array(5) const key = Buffer.alloc(5)
const iv = new Uint8Array(16) const iv = Buffer.alloc(16)
return expectErrCode(crypto.aes.create(key, iv), 'ERR_INVALID_KEY_LENGTH') return expectErrCode(crypto.aes.create(key, iv), 'ERR_INVALID_KEY_LENGTH')
}) })
}) })
// @ts-check // @ts-check
/** /**
* @type {function(Cipher): Promise<void>} * @type {function(Cipher): void}
*/ */
async function encryptAndDecrypt (cipher) { async function encryptAndDecrypt (cipher) {
const data = new Uint8Array(100) const data = Buffer.alloc(100)
data.fill(Math.ceil(Math.random() * 100)) data.fill(Math.ceil(Math.random() * 100))
const encrypted = await cipher.encrypt(data) const encrypted = await cipher.encrypt(data)

View File

@ -2,10 +2,9 @@
'use strict' 'use strict'
const chai = require('chai') const chai = require('chai')
chai.use(require('dirty-chai')) const dirtyChai = require('dirty-chai')
const expect = chai.expect const expect = chai.expect
const uint8ArrayFromString = require('uint8arrays/from-string') chai.use(dirtyChai)
const crypto = require('../') const crypto = require('../')
const webcrypto = require('../src/webcrypto') const webcrypto = require('../src/webcrypto')
@ -37,7 +36,7 @@ describe('Missing web crypto', () => {
}) })
it('should error for hmac create when web crypto is missing', () => { it('should error for hmac create when web crypto is missing', () => {
return expectMissingWebCrypto(() => crypto.hmac.create('SHA256', uint8ArrayFromString('secret'))) return expectMissingWebCrypto(() => crypto.hmac.create('SHA256', Buffer.from('secret')))
}) })
it('should error for generate ephemeral key pair when web crypto is missing', () => { it('should error for generate ephemeral key pair when web crypto is missing', () => {
@ -53,10 +52,10 @@ describe('Missing web crypto', () => {
}) })
it('should error for sign RSA private key when web crypto is missing', () => { it('should error for sign RSA private key when web crypto is missing', () => {
return expectMissingWebCrypto(() => rsaPrivateKey.sign(uint8ArrayFromString('test'))) return expectMissingWebCrypto(() => rsaPrivateKey.sign(Buffer.from('test')))
}) })
it('should error for verify RSA public key when web crypto is missing', () => { it('should error for verify RSA public key when web crypto is missing', () => {
return expectMissingWebCrypto(() => rsaPrivateKey.public.verify(uint8ArrayFromString('test'), uint8ArrayFromString('test'))) return expectMissingWebCrypto(() => rsaPrivateKey.public.verify(Buffer.from('test'), Buffer.from('test')))
}) })
}) })

View File

@ -9,7 +9,6 @@ chai.use(dirtyChai)
const crypto = require('../src') const crypto = require('../src')
const fixtures = require('./fixtures/go-key-rsa') const fixtures = require('./fixtures/go-key-rsa')
const { expectErrCode } = require('./util') const { expectErrCode } = require('./util')
const uint8ArrayEquals = require('uint8arrays/equals')
/** @typedef {import("libp2p-crypto").PrivateKey} PrivateKey */ /** @typedef {import("libp2p-crypto").PrivateKey} PrivateKey */
@ -84,7 +83,7 @@ describe('libp2p-crypto', function () {
it('unmarshal -> marshal, public key', () => { it('unmarshal -> marshal, public key', () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.public.key) const key = crypto.keys.unmarshalPublicKey(fixtures.public.key)
const marshalled = crypto.keys.marshalPublicKey(key) const marshalled = crypto.keys.marshalPublicKey(key)
expect(uint8ArrayEquals(fixtures.public.key, marshalled)).to.eql(true) expect(fixtures.public.key.equals(marshalled)).to.eql(true)
}) })
}) })

View File

@ -1,12 +1,13 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
module.exports = { module.exports = {
curve: 'P-256', curve: 'P-256',
bob: { bob: {
private: Uint8Array.from([ private: Buffer.from([
181, 217, 162, 151, 225, 36, 53, 253, 107, 66, 27, 27, 232, 72, 0, 0, 103, 167, 84, 62, 203, 91, 97, 137, 131, 193, 230, 126, 98, 242, 216, 170 181, 217, 162, 151, 225, 36, 53, 253, 107, 66, 27, 27, 232, 72, 0, 0, 103, 167, 84, 62, 203, 91, 97, 137, 131, 193, 230, 126, 98, 242, 216, 170
]), ]),
public: Uint8Array.from([ public: Buffer.from([
4, 53, 59, 128, 56, 162, 250, 72, 141, 206, 117, 232, 57, 96, 39, 39, 247, 7, 27, 57, 251, 232, 120, 186, 21, 239, 176, 139, 195, 129, 125, 85, 11, 188, 191, 32, 227, 0, 6, 163, 101, 68, 208, 1, 43, 131, 124, 112, 102, 91, 104, 79, 16, 119, 152, 208, 4, 147, 155, 83, 20, 146, 104, 55, 90 4, 53, 59, 128, 56, 162, 250, 72, 141, 206, 117, 232, 57, 96, 39, 39, 247, 7, 27, 57, 251, 232, 120, 186, 21, 239, 176, 139, 195, 129, 125, 85, 11, 188, 191, 32, 227, 0, 6, 163, 101, 68, 208, 1, 43, 131, 124, 112, 102, 91, 104, 79, 16, 119, 152, 208, 4, 147, 155, 83, 20, 146, 104, 55, 90
]) ])
} }

View File

@ -1,42 +1,29 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
module.exports = { module.exports = {
// Generation code from https://github.com/libp2p/js-libp2p-crypto/issues/175#issuecomment-634467463 // These were generated in a gore (https://github.com/motemen/gore) repl session:
// //
// package main // :import github.com/libp2p/go-libp2p-crypto
// // :import crypto/rand
// import ( // priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
// "crypto/rand" // pubkeyBytes, err := pub.Bytes()
// "fmt" // privkeyBytes, err := priv.Bytes()
// "strings"
// "github.com/libp2p/go-libp2p-core/crypto"
// )
// func main() {
// priv, pub, _ := crypto.GenerateEd25519Key(rand.Reader)
// pubkeyBytes, _ := pub.Bytes()
// privkeyBytes, _ := priv.Bytes()
// data := []byte("hello! and welcome to some awesome crypto primitives") // data := []byte("hello! and welcome to some awesome crypto primitives")
// sig, _ := priv.Sign(data) // sig, err := priv.Sign(data)
// fmt.Println("{\n publicKey: Uint8Array.from(", strings.Replace(fmt.Sprint(pubkeyBytes), " ", ",", -1), "),")
// fmt.Println(" privateKey: Uint8Array.from(", strings.Replace(fmt.Sprint(privkeyBytes), " ", ",", -1), "),")
// fmt.Println(" data: Uint8Array.from(", strings.Replace(fmt.Sprint(data), " ", ",", -1), "),")
// fmt.Println(" signature: Uint8Array.from(", strings.Replace(fmt.Sprint(sig), " ", ",", -1), ")\n}")
// }
// //
// :import io/ioutil
// The legacy key unnecessarily appends the publickey. (It's already included) See https://github.com/libp2p/js-libp2p-crypto/issues/175 // ioutil.WriteFile("/tmp/pubkey_go.bin", pubkeyBytes, 0644)
redundantPubKey: { // // etc..
privateKey: Uint8Array.from([8, 1, 18, 96, 201, 208, 1, 110, 176, 16, 230, 37, 66, 184, 149, 252, 78, 56, 206, 136, 2, 38, 118, 152, 226, 197, 117, 200, 54, 189, 156, 218, 184, 7, 118, 57, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]), //
publicKey: Uint8Array.from([8, 1, 18, 32, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]), // Then loaded into a node repl and dumped to arrays with:
data: Uint8Array.from([104, 101, 108, 108, 111, 33, 32, 97, 110, 100, 32, 119, 101, 108, 99, 111, 109, 101, 32, 116, 111, 32, 115, 111, 109, 101, 32, 97, 119, 101, 115, 111, 109, 101, 32, 99, 114, 121, 112, 116, 111, 32, 112, 114, 105, 109, 105, 116, 105, 118, 101, 115]), //
signature: Uint8Array.from([7, 230, 175, 164, 228, 58, 78, 208, 62, 243, 73, 142, 83, 195, 176, 217, 166, 62, 41, 165, 168, 164, 75, 179, 163, 86, 102, 32, 18, 84, 150, 237, 39, 207, 213, 20, 134, 237, 50, 41, 176, 183, 229, 133, 38, 255, 42, 228, 68, 186, 100, 14, 175, 156, 243, 118, 125, 125, 120, 212, 124, 103, 252, 12]) // var pubkey = Array.from(fs.readFileSync('/tmp/pubkey_go.bin'))
}, // console.log(JSON.stringify(pubkey))
verify: { verify: {
publicKey: Uint8Array.from([8, 1, 18, 32, 163, 176, 195, 47, 254, 208, 49, 5, 192, 102, 32, 63, 58, 202, 171, 153, 146, 164, 25, 212, 25, 91, 146, 26, 117, 165, 148, 6, 207, 90, 217, 126]), privateKey: Buffer.from([8, 1, 18, 96, 201, 208, 1, 110, 176, 16, 230, 37, 66, 184, 149, 252, 78, 56, 206, 136, 2, 38, 118, 152, 226, 197, 117, 200, 54, 189, 156, 218, 184, 7, 118, 57, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]),
privateKey: Uint8Array.from([8, 1, 18, 64, 232, 56, 175, 20, 240, 160, 19, 47, 92, 88, 115, 221, 164, 13, 36, 162, 158, 136, 247, 31, 29, 231, 76, 143, 12, 91, 193, 4, 88, 33, 67, 23, 163, 176, 195, 47, 254, 208, 49, 5, 192, 102, 32, 63, 58, 202, 171, 153, 146, 164, 25, 212, 25, 91, 146, 26, 117, 165, 148, 6, 207, 90, 217, 126]), publicKey: Buffer.from([8, 1, 18, 32, 233, 49, 221, 97, 164, 158, 241, 129, 73, 166, 225, 255, 193, 118, 22, 84, 55, 15, 249, 168, 225, 180, 198, 191, 14, 75, 187, 243, 150, 91, 232, 37]),
data: Uint8Array.from([104, 101, 108, 108, 111, 33, 32, 97, 110, 100, 32, 119, 101, 108, 99, 111, 109, 101, 32, 116, 111, 32, 115, 111, 109, 101, 32, 97, 119, 101, 115, 111, 109, 101, 32, 99, 114, 121, 112, 116, 111, 32, 112, 114, 105, 109, 105, 116, 105, 118, 101, 115]), data: Buffer.from([104, 101, 108, 108, 111, 33, 32, 97, 110, 100, 32, 119, 101, 108, 99, 111, 109, 101, 32, 116, 111, 32, 115, 111, 109, 101, 32, 97, 119, 101, 115, 111, 109, 101, 32, 99, 114, 121, 112, 116, 111, 32, 112, 114, 105, 109, 105, 116, 105, 118, 101, 115]),
signature: Uint8Array.from([160, 125, 30, 62, 213, 189, 239, 92, 87, 76, 205, 169, 251, 149, 187, 57, 96, 85, 175, 213, 22, 132, 229, 60, 196, 18, 117, 194, 12, 174, 135, 31, 39, 168, 174, 103, 78, 55, 37, 222, 37, 172, 222, 239, 153, 63, 197, 152, 67, 167, 191, 215, 161, 212, 216, 163, 81, 77, 45, 228, 151, 79, 101, 1]) signature: Buffer.from([7, 230, 175, 164, 228, 58, 78, 208, 62, 243, 73, 142, 83, 195, 176, 217, 166, 62, 41, 165, 168, 164, 75, 179, 163, 86, 102, 32, 18, 84, 150, 237, 39, 207, 213, 20, 134, 237, 50, 41, 176, 183, 229, 133, 38, 255, 42, 228, 68, 186, 100, 14, 175, 156, 243, 118, 125, 125, 120, 212, 124, 103, 252, 12])
} }
} }

View File

@ -1,30 +1,30 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
module.exports = { module.exports = {
private: { private: {
hash: Uint8Array.from([ hash: Buffer.from([
18, 32, 168, 125, 165, 65, 34, 157, 209, 4, 24, 158, 80, 196, 125, 86, 103, 0, 228, 145, 109, 252, 153, 7, 189, 9, 16, 37, 239, 36, 48, 78, 214, 212 18, 32, 168, 125, 165, 65, 34, 157, 209, 4, 24, 158, 80, 196, 125, 86, 103, 0, 228, 145, 109, 252, 153, 7, 189, 9, 16, 37, 239, 36, 48, 78, 214, 212
]), ]),
key: Uint8Array.from([ key: Buffer.from([
8, 0, 18, 192, 2, 48, 130, 1, 60, 2, 1, 0, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1, 2, 65, 0, 191, 59, 140, 255, 254, 23, 123, 91, 148, 19, 240, 71, 213, 26, 181, 51, 68, 181, 150, 153, 214, 65, 148, 83, 45, 103, 239, 250, 225, 237, 125, 173, 111, 244, 37, 124, 87, 178, 86, 10, 14, 207, 63, 105, 213, 37, 81, 23, 230, 4, 222, 179, 144, 40, 252, 163, 190, 7, 241, 221, 28, 54, 225, 209, 2, 33, 0, 235, 132, 229, 150, 99, 182, 176, 194, 198, 65, 210, 160, 184, 70, 82, 49, 235, 199, 14, 11, 92, 66, 237, 45, 220, 72, 235, 1, 244, 145, 205, 57, 2, 33, 0, 250, 171, 146, 180, 188, 194, 14, 152, 52, 64, 38, 52, 158, 86, 46, 109, 66, 100, 122, 43, 88, 167, 143, 98, 104, 143, 160, 60, 171, 185, 31, 135, 2, 33, 0, 206, 47, 255, 203, 100, 170, 137, 31, 75, 240, 78, 84, 212, 95, 4, 16, 158, 73, 27, 27, 136, 255, 50, 163, 166, 169, 211, 204, 87, 111, 217, 201, 2, 33, 0, 177, 51, 194, 213, 3, 175, 7, 84, 47, 115, 189, 206, 106, 180, 47, 195, 203, 48, 110, 112, 224, 14, 43, 189, 124, 127, 51, 222, 79, 226, 225, 87, 2, 32, 67, 23, 190, 222, 106, 22, 115, 139, 217, 244, 178, 53, 153, 99, 5, 176, 72, 77, 193, 61, 67, 134, 37, 238, 69, 66, 159, 28, 39, 5, 238, 125 8, 0, 18, 192, 2, 48, 130, 1, 60, 2, 1, 0, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1, 2, 65, 0, 191, 59, 140, 255, 254, 23, 123, 91, 148, 19, 240, 71, 213, 26, 181, 51, 68, 181, 150, 153, 214, 65, 148, 83, 45, 103, 239, 250, 225, 237, 125, 173, 111, 244, 37, 124, 87, 178, 86, 10, 14, 207, 63, 105, 213, 37, 81, 23, 230, 4, 222, 179, 144, 40, 252, 163, 190, 7, 241, 221, 28, 54, 225, 209, 2, 33, 0, 235, 132, 229, 150, 99, 182, 176, 194, 198, 65, 210, 160, 184, 70, 82, 49, 235, 199, 14, 11, 92, 66, 237, 45, 220, 72, 235, 1, 244, 145, 205, 57, 2, 33, 0, 250, 171, 146, 180, 188, 194, 14, 152, 52, 64, 38, 52, 158, 86, 46, 109, 66, 100, 122, 43, 88, 167, 143, 98, 104, 143, 160, 60, 171, 185, 31, 135, 2, 33, 0, 206, 47, 255, 203, 100, 170, 137, 31, 75, 240, 78, 84, 212, 95, 4, 16, 158, 73, 27, 27, 136, 255, 50, 163, 166, 169, 211, 204, 87, 111, 217, 201, 2, 33, 0, 177, 51, 194, 213, 3, 175, 7, 84, 47, 115, 189, 206, 106, 180, 47, 195, 203, 48, 110, 112, 224, 14, 43, 189, 124, 127, 51, 222, 79, 226, 225, 87, 2, 32, 67, 23, 190, 222, 106, 22, 115, 139, 217, 244, 178, 53, 153, 99, 5, 176, 72, 77, 193, 61, 67, 134, 37, 238, 69, 66, 159, 28, 39, 5, 238, 125
]) ])
}, },
public: { public: {
hash: Uint8Array.from([ hash: Buffer.from([
18, 32, 112, 151, 163, 167, 204, 243, 175, 123, 208, 162, 90, 84, 199, 174, 202, 110, 0, 119, 27, 202, 7, 149, 161, 251, 215, 168, 163, 54, 93, 54, 195, 20 18, 32, 112, 151, 163, 167, 204, 243, 175, 123, 208, 162, 90, 84, 199, 174, 202, 110, 0, 119, 27, 202, 7, 149, 161, 251, 215, 168, 163, 54, 93, 54, 195, 20
]), ]),
key: Uint8Array.from([ key: Buffer.from([
8, 0, 18, 94, 48, 92, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 75, 0, 48, 72, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1 8, 0, 18, 94, 48, 92, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 75, 0, 48, 72, 2, 65, 0, 230, 157, 160, 242, 74, 222, 87, 0, 77, 180, 91, 175, 217, 166, 2, 95, 193, 239, 195, 140, 224, 57, 84, 207, 46, 172, 113, 196, 20, 133, 117, 205, 45, 7, 224, 41, 40, 195, 254, 124, 14, 84, 223, 147, 67, 198, 48, 36, 53, 161, 112, 46, 153, 90, 19, 123, 94, 247, 5, 116, 1, 238, 32, 15, 2, 3, 1, 0, 1
]) ])
}, },
verify: { verify: {
signature: Uint8Array.from([ signature: Buffer.from([
3, 116, 81, 57, 91, 194, 7, 1, 230, 236, 229, 142, 36, 209, 208, 107, 47, 52, 164, 236, 139, 35, 155, 97, 43, 64, 145, 91, 19, 218, 149, 63, 99, 164, 191, 110, 145, 37, 18, 7, 98, 112, 144, 35, 29, 186, 169, 150, 165, 88, 145, 170, 197, 110, 42, 163, 188, 10, 42, 63, 34, 93, 91, 94, 199, 110, 10, 82, 238, 80, 93, 93, 77, 130, 22, 216, 229, 172, 36, 229, 82, 162, 20, 78, 19, 46, 82, 243, 43, 80, 115, 125, 145, 231, 194, 224, 30, 187, 55, 228, 74, 52, 203, 191, 254, 148, 136, 218, 62, 147, 171, 130, 251, 181, 105, 29, 238, 207, 197, 249, 61, 105, 202, 172, 160, 174, 43, 124, 115, 130, 169, 30, 76, 41, 52, 200, 2, 26, 53, 190, 43, 20, 203, 10, 217, 250, 47, 102, 92, 103, 197, 22, 108, 184, 74, 218, 82, 202, 180, 98, 13, 114, 12, 92, 1, 139, 150, 170, 8, 92, 32, 116, 168, 219, 157, 162, 28, 77, 29, 29, 74, 136, 144, 49, 173, 245, 253, 76, 167, 200, 169, 163, 7, 49, 133, 120, 99, 191, 53, 10, 66, 26, 234, 240, 139, 235, 134, 30, 55, 248, 150, 100, 242, 150, 159, 198, 44, 78, 150, 7, 133, 139, 59, 76, 3, 225, 94, 13, 89, 122, 34, 95, 95, 107, 74, 169, 171, 169, 222, 25, 191, 182, 148, 116, 66, 67, 102, 12, 193, 217, 247, 243, 148, 233, 161, 157 3, 116, 81, 57, 91, 194, 7, 1, 230, 236, 229, 142, 36, 209, 208, 107, 47, 52, 164, 236, 139, 35, 155, 97, 43, 64, 145, 91, 19, 218, 149, 63, 99, 164, 191, 110, 145, 37, 18, 7, 98, 112, 144, 35, 29, 186, 169, 150, 165, 88, 145, 170, 197, 110, 42, 163, 188, 10, 42, 63, 34, 93, 91, 94, 199, 110, 10, 82, 238, 80, 93, 93, 77, 130, 22, 216, 229, 172, 36, 229, 82, 162, 20, 78, 19, 46, 82, 243, 43, 80, 115, 125, 145, 231, 194, 224, 30, 187, 55, 228, 74, 52, 203, 191, 254, 148, 136, 218, 62, 147, 171, 130, 251, 181, 105, 29, 238, 207, 197, 249, 61, 105, 202, 172, 160, 174, 43, 124, 115, 130, 169, 30, 76, 41, 52, 200, 2, 26, 53, 190, 43, 20, 203, 10, 217, 250, 47, 102, 92, 103, 197, 22, 108, 184, 74, 218, 82, 202, 180, 98, 13, 114, 12, 92, 1, 139, 150, 170, 8, 92, 32, 116, 168, 219, 157, 162, 28, 77, 29, 29, 74, 136, 144, 49, 173, 245, 253, 76, 167, 200, 169, 163, 7, 49, 133, 120, 99, 191, 53, 10, 66, 26, 234, 240, 139, 235, 134, 30, 55, 248, 150, 100, 242, 150, 159, 198, 44, 78, 150, 7, 133, 139, 59, 76, 3, 225, 94, 13, 89, 122, 34, 95, 95, 107, 74, 169, 171, 169, 222, 25, 191, 182, 148, 116, 66, 67, 102, 12, 193, 217, 247, 243, 148, 233, 161, 157
]), ]),
data: Uint8Array.from([ data: Buffer.from([
10, 16, 27, 128, 228, 220, 147, 176, 53, 105, 175, 171, 32, 213, 35, 236, 203, 60, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 24, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 44, 66, 108, 111, 119, 102, 105, 115, 104, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 10, 16, 220, 83, 240, 105, 6, 203, 78, 83, 210, 115, 6, 106, 98, 82, 1, 161, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 185, 234, 19, 191, 164, 33, 65, 94, 87, 42, 74, 83, 224, 25, 142, 44, 26, 7, 92, 242, 189, 42, 170, 197, 178, 92, 45, 240, 107, 141, 128, 59, 122, 252, 48, 140, 4, 85, 85, 203, 3, 197, 8, 127, 120, 98, 44, 169, 135, 196, 70, 137, 117, 180, 177, 134, 170, 35, 165, 88, 105, 30, 114, 138, 11, 96, 68, 99, 18, 149, 223, 166, 105, 12, 176, 77, 48, 214, 22, 236, 17, 154, 213, 209, 158, 169, 202, 5, 100, 210, 83, 90, 201, 38, 205, 246, 231, 106, 63, 86, 222, 143, 157, 173, 62, 4, 85, 232, 20, 188, 6, 209, 186, 132, 192, 117, 146, 181, 233, 26, 0, 240, 138, 206, 91, 170, 114, 137, 217, 132, 139, 242, 144, 213, 103, 101, 190, 146, 188, 250, 188, 134, 255, 70, 125, 78, 65, 136, 239, 190, 206, 139, 155, 140, 163, 233, 170, 247, 205, 87, 209, 19, 29, 173, 10, 147, 43, 28, 90, 46, 6, 197, 217, 186, 66, 68, 126, 76, 64, 184, 8, 170, 23, 79, 243, 223, 119, 133, 118, 50, 226, 44, 246, 176, 10, 161, 219, 83, 54, 68, 248, 5, 14, 177, 114, 54, 63, 11, 71, 136, 142, 56, 151, 123, 230, 61, 80, 15, 180, 42, 49, 220, 148, 99, 231, 20, 230, 220, 85, 207, 187, 37, 210, 137, 171, 125, 71, 14, 53, 100, 91, 83, 209, 50, 132, 165, 253, 25, 161, 5, 97, 164, 163, 83, 95, 53, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 15, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 4, 97, 54, 203, 112, 136, 34, 231, 162, 19, 154, 131, 27, 105, 26, 121, 238, 120, 25, 203, 66, 232, 53, 198, 20, 19, 96, 119, 218, 90, 64, 170, 3, 132, 116, 1, 87, 116, 232, 165, 161, 198, 117, 167, 60, 145, 1, 253, 108, 50, 150, 117, 8, 140, 133, 48, 30, 236, 36, 84, 186, 22, 144, 87, 101 10, 16, 27, 128, 228, 220, 147, 176, 53, 105, 175, 171, 32, 213, 35, 236, 203, 60, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 24, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 44, 66, 108, 111, 119, 102, 105, 115, 104, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 10, 16, 220, 83, 240, 105, 6, 203, 78, 83, 210, 115, 6, 106, 98, 82, 1, 161, 18, 171, 2, 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 185, 234, 19, 191, 164, 33, 65, 94, 87, 42, 74, 83, 224, 25, 142, 44, 26, 7, 92, 242, 189, 42, 170, 197, 178, 92, 45, 240, 107, 141, 128, 59, 122, 252, 48, 140, 4, 85, 85, 203, 3, 197, 8, 127, 120, 98, 44, 169, 135, 196, 70, 137, 117, 180, 177, 134, 170, 35, 165, 88, 105, 30, 114, 138, 11, 96, 68, 99, 18, 149, 223, 166, 105, 12, 176, 77, 48, 214, 22, 236, 17, 154, 213, 209, 158, 169, 202, 5, 100, 210, 83, 90, 201, 38, 205, 246, 231, 106, 63, 86, 222, 143, 157, 173, 62, 4, 85, 232, 20, 188, 6, 209, 186, 132, 192, 117, 146, 181, 233, 26, 0, 240, 138, 206, 91, 170, 114, 137, 217, 132, 139, 242, 144, 213, 103, 101, 190, 146, 188, 250, 188, 134, 255, 70, 125, 78, 65, 136, 239, 190, 206, 139, 155, 140, 163, 233, 170, 247, 205, 87, 209, 19, 29, 173, 10, 147, 43, 28, 90, 46, 6, 197, 217, 186, 66, 68, 126, 76, 64, 184, 8, 170, 23, 79, 243, 223, 119, 133, 118, 50, 226, 44, 246, 176, 10, 161, 219, 83, 54, 68, 248, 5, 14, 177, 114, 54, 63, 11, 71, 136, 142, 56, 151, 123, 230, 61, 80, 15, 180, 42, 49, 220, 148, 99, 231, 20, 230, 220, 85, 207, 187, 37, 210, 137, 171, 125, 71, 14, 53, 100, 91, 83, 209, 50, 132, 165, 253, 25, 161, 5, 97, 164, 163, 83, 95, 53, 2, 3, 1, 0, 1, 26, 17, 80, 45, 50, 53, 54, 44, 80, 45, 51, 56, 52, 44, 80, 45, 53, 50, 49, 34, 15, 65, 69, 83, 45, 50, 53, 54, 44, 65, 69, 83, 45, 49, 50, 56, 42, 13, 83, 72, 65, 50, 53, 54, 44, 83, 72, 65, 53, 49, 50, 4, 97, 54, 203, 112, 136, 34, 231, 162, 19, 154, 131, 27, 105, 26, 121, 238, 120, 25, 203, 66, 232, 53, 198, 20, 19, 96, 119, 218, 90, 64, 170, 3, 132, 116, 1, 87, 116, 232, 165, 161, 198, 117, 167, 60, 145, 1, 253, 108, 50, 150, 117, 8, 140, 133, 48, 30, 236, 36, 84, 186, 22, 144, 87, 101
]), ]),
publicKey: Uint8Array.from([ publicKey: Buffer.from([
8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1 8, 0, 18, 166, 2, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 181, 113, 138, 108, 208, 103, 166, 102, 37, 36, 204, 250, 228, 165, 44, 64, 176, 210, 205, 141, 241, 55, 200, 110, 98, 68, 85, 199, 254, 19, 86, 204, 63, 250, 167, 38, 59, 249, 146, 228, 73, 171, 63, 18, 96, 104, 191, 137, 186, 244, 255, 90, 16, 119, 195, 52, 177, 213, 254, 187, 174, 84, 174, 173, 12, 236, 53, 234, 3, 209, 82, 37, 78, 111, 214, 135, 76, 195, 9, 242, 134, 188, 153, 84, 139, 231, 51, 146, 177, 60, 12, 25, 158, 91, 215, 152, 7, 0, 84, 35, 36, 230, 227, 67, 198, 72, 50, 110, 37, 209, 98, 193, 65, 93, 173, 199, 4, 198, 102, 99, 148, 144, 224, 217, 114, 53, 144, 245, 251, 114, 211, 20, 82, 163, 123, 75, 16, 192, 106, 213, 128, 2, 11, 200, 203, 84, 41, 199, 224, 155, 171, 217, 64, 109, 116, 188, 151, 183, 173, 52, 205, 164, 93, 13, 251, 65, 182, 160, 154, 185, 239, 33, 184, 84, 159, 105, 101, 173, 194, 251, 123, 84, 92, 66, 61, 180, 45, 104, 162, 224, 214, 233, 64, 220, 165, 2, 104, 116, 150, 2, 234, 203, 112, 21, 124, 23, 48, 66, 30, 63, 30, 36, 246, 135, 203, 218, 115, 22, 189, 39, 39, 125, 205, 65, 222, 220, 77, 18, 84, 121, 161, 153, 125, 25, 139, 137, 170, 239, 150, 106, 119, 168, 216, 140, 113, 121, 26, 53, 118, 110, 53, 192, 244, 252, 145, 85, 2, 3, 1, 0, 1
]) ])
} }

View File

@ -1,31 +0,0 @@
'use strict'
const uint8ArrayFromString = require('uint8arrays/from-string')
// 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
//
// gore> :import github.com/vyzo/go-libp2p-crypto
// gore> :import crypto/rand
// gore> :import io/ioutil
// gore> priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.Secp256k1, 256, rand.Reader)
// gore> privBytes, err := priv.Bytes()
// gore> pubBytes, err := pub.Bytes()
// gore> msg := []byte("hello! and welcome to some awesome crypto primitives")
// gore> sig, err := priv.Sign(msg)
// gore> ioutil.WriteFile("/tmp/secp-go-priv.bin", privBytes, 0644)
// gore> ioutil.WriteFile("/tmp/secp-go-pub.bin", pubBytes, 0644)
// gore> ioutil.WriteFile("/tmp/secp-go-sig.bin", sig, 0644)
//
// The generated files were then read in a node repl with e.g.:
// > fs.readFileSync('/tmp/secp-go-pub.bin').toString('hex')
// '08021221029c0ce5d53646ed47112560297a3e59b78b8cbd4bae37c7a0c236eeb91d0fbeaf'
//
// and the results copy/pasted in here
module.exports = {
privateKey: uint8ArrayFromString('08021220358f15db8c2014d570e8e3a622454e2273975a3cca443ec0c45375b13d381d18', 'base16'),
publicKey: uint8ArrayFromString('08021221029c0ce5d53646ed47112560297a3e59b78b8cbd4bae37c7a0c236eeb91d0fbeaf', 'base16'),
message: uint8ArrayFromString('hello! and welcome to some awesome crypto primitives'),
signature: uint8ArrayFromString('304402200e4c629e9f5d99439115e60989cd40087f6978c36078b0b50cf3d30af5c38d4102204110342c8e7f0809897c1c7a66e49e1c6b7cb0a6ed6993640ec2fe742c1899a9', 'base16')
}

View File

@ -1,30 +1,30 @@
'use strict' 'use strict'
const { Buffer } = require('buffer')
module.exports = [{ module.exports = [{
cipher: 'AES-256', cipher: 'AES-256',
hash: 'SHA256', hash: 'SHA256',
secret: Uint8Array.from([ secret: Buffer.from([
195, 191, 209, 165, 209, 201, 127, 122, 136, 111, 31, 66, 111, 68, 38, 155, 216, 204, 46, 181, 200, 188, 170, 204, 104, 74, 239, 251, 173, 114, 222, 234 195, 191, 209, 165, 209, 201, 127, 122, 136, 111, 31, 66, 111, 68, 38, 155, 216, 204, 46, 181, 200, 188, 170, 204, 104, 74, 239, 251, 173, 114, 222, 234
]), ]),
k1: { k1: {
iv: Uint8Array.from([ iv: Buffer.from([
208, 132, 203, 169, 253, 52, 40, 83, 161, 91, 17, 71, 33, 136, 67, 96 208, 132, 203, 169, 253, 52, 40, 83, 161, 91, 17, 71, 33, 136, 67, 96
]), ]),
cipherKey: Uint8Array.from([ cipherKey: Buffer.from([
156, 48, 241, 157, 92, 248, 153, 186, 114, 127, 195, 114, 106, 104, 215, 133, 35, 11, 131, 137, 123, 70, 74, 26, 15, 60, 189, 32, 67, 221, 115, 137 156, 48, 241, 157, 92, 248, 153, 186, 114, 127, 195, 114, 106, 104, 215, 133, 35, 11, 131, 137, 123, 70, 74, 26, 15, 60, 189, 32, 67, 221, 115, 137
]), ]),
macKey: Uint8Array.from([ macKey: Buffer.from([
6, 179, 91, 245, 224, 56, 153, 120, 77, 140, 29, 5, 15, 213, 187, 65, 137, 230, 202, 120 6, 179, 91, 245, 224, 56, 153, 120, 77, 140, 29, 5, 15, 213, 187, 65, 137, 230, 202, 120
]) ])
}, },
k2: { k2: {
iv: Uint8Array.from([ iv: Buffer.from([
236, 17, 34, 141, 90, 106, 197, 56, 197, 184, 157, 135, 91, 88, 112, 19 236, 17, 34, 141, 90, 106, 197, 56, 197, 184, 157, 135, 91, 88, 112, 19
]), ]),
cipherKey: Uint8Array.from([ cipherKey: Buffer.from([
151, 145, 195, 219, 76, 195, 102, 109, 187, 231, 100, 150, 132, 245, 251, 130, 254, 37, 178, 55, 227, 34, 114, 39, 238, 34, 2, 193, 107, 130, 32, 87 151, 145, 195, 219, 76, 195, 102, 109, 187, 231, 100, 150, 132, 245, 251, 130, 254, 37, 178, 55, 227, 34, 114, 39, 238, 34, 2, 193, 107, 130, 32, 87
]), ]),
macKey: Uint8Array.from([ macKey: Buffer.from([
3, 229, 77, 212, 241, 217, 23, 113, 220, 126, 38, 255, 18, 117, 108, 205, 198, 89, 1, 236 3, 229, 77, 212, 241, 217, 23, 113, 220, 126, 38, 255, 18, 117, 108, 205, 198, 89, 1, 236
]) ])
} }

View File

@ -1,10 +1,9 @@
'use strict' 'use strict'
const uint8ArrayFromString = require('uint8arrays/from-string') const { Buffer } = require('buffer')
module.exports = { module.exports = {
// protobuf marshaled key pair generated with libp2p-crypto-secp256k1 // protobuf marshaled key pair generated with libp2p-crypto-secp256k1
// and marshaled with libp2p-crypto.marshalPublicKey / marshalPrivateKey // and marshaled with libp2p-crypto.marshalPublicKey / marshalPrivateKey
pbmPrivateKey: uint8ArrayFromString('08021220e0600103010000000100000000000000be1dc82c2e000000e8d6030301000000', 'base16'), pbmPrivateKey: Buffer.from('08021220e0600103010000000100000000000000be1dc82c2e000000e8d6030301000000', 'hex'),
pbmPublicKey: uint8ArrayFromString('0802122103a9a7272a726fa083abf31ba44037f8347fbc5e5d3113d62a7c6bc26752fd8ee1', 'base16') pbmPublicKey: Buffer.from('0802122103a9a7272a726fa083abf31ba44037f8347fbc5e5d3113d62a7c6bc26752fd8ee1', 'hex')
} }

View File

@ -1,9 +1,9 @@
/* eslint-env mocha */ /* eslint-env mocha */
'use strict' 'use strict'
const uint8ArrayFromString = require('uint8arrays/from-string') const { Buffer } = require('buffer')
const util = require('util') const util = require('util')
const garbage = [uint8ArrayFromString('00010203040506070809', 'base16'), {}, null, false, undefined, true, 1, 0, uint8ArrayFromString(''), 'aGVsbG93b3JsZA==', 'helloworld', ''] const garbage = [Buffer.from('00010203040506070809', 'hex'), {}, null, false, undefined, true, 1, 0, Buffer.from(''), 'aGVsbG93b3JsZA==', 'helloworld', '']
function doTests (fncName, fnc, num, skipBuffersAndStrings) { function doTests (fncName, fnc, num, skipBuffersAndStrings) {
if (!num) { if (!num) {
@ -11,8 +11,8 @@ function doTests (fncName, fnc, num, skipBuffersAndStrings) {
} }
garbage.forEach((garbage) => { garbage.forEach((garbage) => {
if (skipBuffersAndStrings && (garbage instanceof Uint8Array || (typeof garbage) === 'string')) { if (skipBuffersAndStrings && (Buffer.isBuffer(garbage) || (typeof garbage) === 'string')) {
// skip this garbage because it's a Uint8Array or a String and we were told do do that // skip this garbage because it's a buffer or a string and we were told do do that
return return
} }
const args = [] const args = []

View File

@ -1,12 +1,11 @@
/* eslint max-nested-callbacks: ["error", 8] */ /* eslint max-nested-callbacks: ["error", 8] */
/* 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 uint8ArrayFromString = require('uint8arrays/from-string')
const crypto = require('../../src') const crypto = require('../../src')
@ -15,8 +14,8 @@ const hashes = ['SHA1', 'SHA256', 'SHA512']
describe('HMAC', () => { describe('HMAC', () => {
hashes.forEach((hash) => { hashes.forEach((hash) => {
it(`${hash} - sign and verify`, async () => { it(`${hash} - sign and verify`, async () => {
const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret')) const hmac = await crypto.hmac.create(hash, Buffer.from('secret'))
const sig = await hmac.digest(uint8ArrayFromString('hello world')) const sig = await hmac.digest(Buffer.from('hello world'))
expect(sig).to.have.length(hmac.length) expect(sig).to.have.length(hmac.length)
}) })
}) })

View File

@ -1,11 +1,11 @@
/* 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 uint8ArrayFromString = require('uint8arrays/from-string')
const crypto = require('../../src') const crypto = require('../../src')
const ed25519 = crypto.keys.supportedKeys.ed25519 const ed25519 = crypto.keys.supportedKeys.ed25519
@ -80,29 +80,9 @@ describe('ed25519', function () {
}) })
it('key id', async () => { it('key id', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey)
const id = await key.id() const id = await key.id()
expect(id).to.eql('12D3KooWLqLxEfJ9nDdEe8Kh8PFvNPQRYDQBwyL7CMM7HhVd5LsX') expect(id).to.exist()
}) expect(id).to.be.a('string')
it('should export a password encrypted libp2p-key', async () => {
const key = await crypto.keys.generateKeyPair('Ed25519')
const encryptedKey = await key.export('my secret')
// Import the key
const importedKey = await crypto.keys.import(encryptedKey, 'my secret')
expect(key.equals(importedKey)).to.equal(true)
})
it('should fail to import libp2p-key with wrong password', async () => {
const key = await crypto.keys.generateKeyPair('Ed25519')
const encryptedKey = await key.export('my secret', 'libp2p-key')
try {
await crypto.keys.import(encryptedKey, 'not my secret')
} catch (err) {
expect(err).to.exist()
return
}
expect.fail('should have thrown')
}) })
describe('key equals', () => { describe('key equals', () => {
@ -130,16 +110,16 @@ describe('ed25519', function () {
}) })
it('sign and verify', async () => { it('sign and verify', async () => {
const data = uint8ArrayFromString('hello world') const data = Buffer.from('hello world')
const sig = await key.sign(data) const sig = await key.sign(data)
const valid = await key.public.verify(data, sig) const valid = await key.public.verify(data, sig)
expect(valid).to.eql(true) expect(valid).to.eql(true)
}) })
it('fails to verify for different data', async () => { it('fails to verify for different data', async () => {
const data = uint8ArrayFromString('hello world') const data = Buffer.from('hello world')
const sig = await key.sign(data) const sig = await key.sign(data)
const valid = await key.public.verify(uint8ArrayFromString('hello'), sig) const valid = await key.public.verify(Buffer.from('hello'), sig)
expect(valid).to.be.eql(false) expect(valid).to.be.eql(false)
}) })
@ -151,35 +131,25 @@ describe('ed25519', function () {
describe('go interop', () => { describe('go interop', () => {
// @ts-check // @ts-check
/**
* @type {PrivateKey}
*/
let privateKey
before(async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey)
privateKey = key
})
it('verifies with data from go', async () => { it('verifies with data from go', async () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey) const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
const ok = await key.verify(fixtures.verify.data, fixtures.verify.signature) const ok = await key.verify(fixtures.verify.data, fixtures.verify.signature)
expect(ok).to.eql(true) expect(ok).to.eql(true)
}) })
it('does not include the redundant public key when marshalling privatekey', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.redundantPubKey.privateKey)
const bytes = key.marshal()
expect(bytes.length).to.equal(64)
expect(bytes.slice(32)).to.eql(key.public.marshal())
})
it('verifies with data from go with redundant public key', async () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.redundantPubKey.publicKey)
const ok = await key.verify(fixtures.redundantPubKey.data, fixtures.redundantPubKey.signature)
expect(ok).to.eql(true)
})
it('generates the same signature as go', async () => { it('generates the same signature as go', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.verify.privateKey) const sig = await privateKey.sign(fixtures.verify.data)
const sig = await key.sign(fixtures.verify.data)
expect(sig).to.eql(fixtures.verify.signature) expect(sig).to.eql(fixtures.verify.signature)
}) })
it('generates the same signature as go with redundant public key', async () => {
const key = await crypto.keys.unmarshalPrivateKey(fixtures.redundantPubKey.privateKey)
const sig = await key.sign(fixtures.redundantPubKey.data)
expect(sig).to.eql(fixtures.redundantPubKey.signature)
})
}) })
}) })

View File

@ -17,7 +17,7 @@ describe('keyStretcher', () => {
let res let res
// @ts-check // @ts-check
/** /**
* @type {Uint8Array} * @type {Buffer}
*/ */
let secret let secret

View File

@ -2,13 +2,13 @@
/* 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)
chai.use(require('chai-string')) chai.use(require('chai-string'))
const { expectErrCode } = require('../util') const { expectErrCode } = require('../util')
const uint8ArrayFromString = require('uint8arrays/from-string')
const crypto = require('../../src') const crypto = require('../../src')
const rsa = crypto.keys.supportedKeys.rsa const rsa = crypto.keys.supportedKeys.rsa
@ -59,9 +59,9 @@ describe('RSA', function () {
}) })
it('key id', async () => { it('key id', async () => {
const key = await crypto.keys.unmarshalPrivateKey(uint8ArrayFromString('CAASqAkwggSkAgEAAoIBAQCk0O+6oNRxhcdZe2GxEDrFBkDV4TZFZnp2ly/dL1cGMBql/8oXPZgei6h7+P5zzfDq2YCfwbjbf0IVY1AshRl6B5VGE1WS+9p1y1OZxJf5os6V1ENnTi6FTcyuBl4BN8dmIKOif0hqgqflaT5OhfYZDXfbJyVQj4vb2+Stu2Xpph3nwqAnTw/7GC/7jrt2Cq6Tu1PoZi36wSwEPYW3eQ1HAYxZjTYYDXl2iyHygnTcbkGRwAQ7vjk+mW7u60zyoolCm9f6Y7c/orJ33DDUocbaGJLlHcfd8bioBwaZy/2m7q43X8pQs0Q1/iwUt0HHZj1YARmHKbh0zR31ciFiV37dAgMBAAECggEADtJBNKnA4QKURj47r0YT2uLwkqtBi6UnDyISalQXAdXyl4n0nPlrhBewC5H9I+HZr+zmTbeIjaiYgz7el1pSy7AB4v7bG7AtWZlyx6mvtwHGjR+8/f3AXjl8Vgv5iSeAdXUq8fJ7SyS7v3wi38HZOzCEXj9bci6ud5ODMYJgLE4gZD0+i1+/V9cpuYfGpS/gLTLEMQLiw/9o8NSZ7sAnxg0UlYhotqaQY23hvXPBOe+0oa95zl2n6XTxCafa3dQl/B6CD1tUq9dhbQew4bxqMq/mhRO9pREEqZ083Uh+u4PTc1BeHgIQaS864pHPb+AY1F7KDvPtHhdojnghp8d70QKBgQDeRYFxo6sd04ohY86Z/i9icVYIyCvfXAKnaMKeGUjK7ou6sDJwFX8W97+CzXpZ/vffsk/l5GGhC50KqrITxHAy/h5IjyDODfps7NMIp0Dm9sO4PWibbw3OOVBRc8w3b3i7I8MrUUA1nLHE1T1HA1rKOTz5jYhE0fi9XKiT1ciKOQKBgQC903w+n9y7M7eaMW7Z5/13kZ7PS3HlM681eaPrk8J4J+c6miFF40/8HOsmarS38v0fgTeKkriPz5A7aLzRHhSiOnp350JNM6c3sLwPEs2qx/CRuWWx1rMERatfDdUH6mvlK6QHu0QgSfQR27EO6a6XvVSJXbvFmimjmtIaz/IpxQKBgQDWJ9HYVAGC81abZTaiWK3/A4QJYhQjWNuVwPICsgnYvI4Uib+PDqcs0ffLZ38DRw48kek5bxpBuJbOuDhro1EXUJCNCJpq7jzixituovd9kTRyR3iKii2bDM2+LPwOTXDdnk9lZRugjCEbrPkleq33Ob7uEtfAty4aBTTHe6uEwQKBgQCB+2q8RyMSXNuADhFlzOFXGrOwJm0bEUUMTPrduRQUyt4e1qOqA3klnXe3mqGcxBpnlEe/76/JacvNom6Ikxx16a0qpYRU8OWz0KU1fR6vrrEgV98241k5t6sdL4+MGA1Bo5xyXtzLb1hdUh3vpDwVU2OrnC+To3iXus/b5EBiMQKBgEI1OaBcFiyjgLGEyFKoZbtzH1mdatTExfrAQqCjOVjQByoMpGhHTXwEaosvyYu63Pa8AJPT7juSGaiKYEJFcXO9BiNyVfmQiqSHJcYeuh+fmO9IlHRHgy5xaIIC00AHS2vC/gXwmXAdPis6BZqDJeiCuOLWJ94QXn8JBT8IgGAI', 'base64pad'))
const id = await key.id() const id = await key.id()
expect(id).to.eql('QmQgsppVMDUpe83wcAqaemKbYvHeF127gnSFQ1xFnBodVw') expect(id).to.exist()
expect(id).to.be.a('string')
}) })
describe('key equals', () => { describe('key equals', () => {
@ -81,14 +81,14 @@ describe('RSA', function () {
}) })
it('sign and verify', async () => { it('sign and verify', async () => {
const data = uint8ArrayFromString('hello world') const data = Buffer.from('hello world')
const sig = await key.sign(data) const sig = await key.sign(data)
const valid = await key.public.verify(data, sig) const valid = await key.public.verify(data, sig)
expect(valid).to.be.eql(true) expect(valid).to.be.eql(true)
}) })
it('encrypt and decrypt', async () => { it('encrypt and decrypt', async () => {
const data = uint8ArrayFromString('hello world') const data = Buffer.from('hello world')
const enc = await key.public.encrypt(data) const enc = await key.public.encrypt(data)
const dec = await key.decrypt(enc) const dec = await key.decrypt(enc)
expect(dec).to.be.eql(data) expect(dec).to.be.eql(data)
@ -99,22 +99,22 @@ describe('RSA', function () {
/** /**
* @type {any} * @type {any}
*/ */
const id = await crypto.keys.unmarshalPrivateKey(uint8ArrayFromString('CAASqAkwggSkAgEAAoIBAQCk0O+6oNRxhcdZe2GxEDrFBkDV4TZFZnp2ly/dL1cGMBql/8oXPZgei6h7+P5zzfDq2YCfwbjbf0IVY1AshRl6B5VGE1WS+9p1y1OZxJf5os6V1ENnTi6FTcyuBl4BN8dmIKOif0hqgqflaT5OhfYZDXfbJyVQj4vb2+Stu2Xpph3nwqAnTw/7GC/7jrt2Cq6Tu1PoZi36wSwEPYW3eQ1HAYxZjTYYDXl2iyHygnTcbkGRwAQ7vjk+mW7u60zyoolCm9f6Y7c/orJ33DDUocbaGJLlHcfd8bioBwaZy/2m7q43X8pQs0Q1/iwUt0HHZj1YARmHKbh0zR31ciFiV37dAgMBAAECggEADtJBNKnA4QKURj47r0YT2uLwkqtBi6UnDyISalQXAdXyl4n0nPlrhBewC5H9I+HZr+zmTbeIjaiYgz7el1pSy7AB4v7bG7AtWZlyx6mvtwHGjR+8/f3AXjl8Vgv5iSeAdXUq8fJ7SyS7v3wi38HZOzCEXj9bci6ud5ODMYJgLE4gZD0+i1+/V9cpuYfGpS/gLTLEMQLiw/9o8NSZ7sAnxg0UlYhotqaQY23hvXPBOe+0oa95zl2n6XTxCafa3dQl/B6CD1tUq9dhbQew4bxqMq/mhRO9pREEqZ083Uh+u4PTc1BeHgIQaS864pHPb+AY1F7KDvPtHhdojnghp8d70QKBgQDeRYFxo6sd04ohY86Z/i9icVYIyCvfXAKnaMKeGUjK7ou6sDJwFX8W97+CzXpZ/vffsk/l5GGhC50KqrITxHAy/h5IjyDODfps7NMIp0Dm9sO4PWibbw3OOVBRc8w3b3i7I8MrUUA1nLHE1T1HA1rKOTz5jYhE0fi9XKiT1ciKOQKBgQC903w+n9y7M7eaMW7Z5/13kZ7PS3HlM681eaPrk8J4J+c6miFF40/8HOsmarS38v0fgTeKkriPz5A7aLzRHhSiOnp350JNM6c3sLwPEs2qx/CRuWWx1rMERatfDdUH6mvlK6QHu0QgSfQR27EO6a6XvVSJXbvFmimjmtIaz/IpxQKBgQDWJ9HYVAGC81abZTaiWK3/A4QJYhQjWNuVwPICsgnYvI4Uib+PDqcs0ffLZ38DRw48kek5bxpBuJbOuDhro1EXUJCNCJpq7jzixituovd9kTRyR3iKii2bDM2+LPwOTXDdnk9lZRugjCEbrPkleq33Ob7uEtfAty4aBTTHe6uEwQKBgQCB+2q8RyMSXNuADhFlzOFXGrOwJm0bEUUMTPrduRQUyt4e1qOqA3klnXe3mqGcxBpnlEe/76/JacvNom6Ikxx16a0qpYRU8OWz0KU1fR6vrrEgV98241k5t6sdL4+MGA1Bo5xyXtzLb1hdUh3vpDwVU2OrnC+To3iXus/b5EBiMQKBgEI1OaBcFiyjgLGEyFKoZbtzH1mdatTExfrAQqCjOVjQByoMpGhHTXwEaosvyYu63Pa8AJPT7juSGaiKYEJFcXO9BiNyVfmQiqSHJcYeuh+fmO9IlHRHgy5xaIIC00AHS2vC/gXwmXAdPis6BZqDJeiCuOLWJ94QXn8JBT8IgGAI', 'base64pad')) const id = await crypto.keys.unmarshalPrivateKey(Buffer.from('CAASqAkwggSkAgEAAoIBAQCk0O+6oNRxhcdZe2GxEDrFBkDV4TZFZnp2ly/dL1cGMBql/8oXPZgei6h7+P5zzfDq2YCfwbjbf0IVY1AshRl6B5VGE1WS+9p1y1OZxJf5os6V1ENnTi6FTcyuBl4BN8dmIKOif0hqgqflaT5OhfYZDXfbJyVQj4vb2+Stu2Xpph3nwqAnTw/7GC/7jrt2Cq6Tu1PoZi36wSwEPYW3eQ1HAYxZjTYYDXl2iyHygnTcbkGRwAQ7vjk+mW7u60zyoolCm9f6Y7c/orJ33DDUocbaGJLlHcfd8bioBwaZy/2m7q43X8pQs0Q1/iwUt0HHZj1YARmHKbh0zR31ciFiV37dAgMBAAECggEADtJBNKnA4QKURj47r0YT2uLwkqtBi6UnDyISalQXAdXyl4n0nPlrhBewC5H9I+HZr+zmTbeIjaiYgz7el1pSy7AB4v7bG7AtWZlyx6mvtwHGjR+8/f3AXjl8Vgv5iSeAdXUq8fJ7SyS7v3wi38HZOzCEXj9bci6ud5ODMYJgLE4gZD0+i1+/V9cpuYfGpS/gLTLEMQLiw/9o8NSZ7sAnxg0UlYhotqaQY23hvXPBOe+0oa95zl2n6XTxCafa3dQl/B6CD1tUq9dhbQew4bxqMq/mhRO9pREEqZ083Uh+u4PTc1BeHgIQaS864pHPb+AY1F7KDvPtHhdojnghp8d70QKBgQDeRYFxo6sd04ohY86Z/i9icVYIyCvfXAKnaMKeGUjK7ou6sDJwFX8W97+CzXpZ/vffsk/l5GGhC50KqrITxHAy/h5IjyDODfps7NMIp0Dm9sO4PWibbw3OOVBRc8w3b3i7I8MrUUA1nLHE1T1HA1rKOTz5jYhE0fi9XKiT1ciKOQKBgQC903w+n9y7M7eaMW7Z5/13kZ7PS3HlM681eaPrk8J4J+c6miFF40/8HOsmarS38v0fgTeKkriPz5A7aLzRHhSiOnp350JNM6c3sLwPEs2qx/CRuWWx1rMERatfDdUH6mvlK6QHu0QgSfQR27EO6a6XvVSJXbvFmimjmtIaz/IpxQKBgQDWJ9HYVAGC81abZTaiWK3/A4QJYhQjWNuVwPICsgnYvI4Uib+PDqcs0ffLZ38DRw48kek5bxpBuJbOuDhro1EXUJCNCJpq7jzixituovd9kTRyR3iKii2bDM2+LPwOTXDdnk9lZRugjCEbrPkleq33Ob7uEtfAty4aBTTHe6uEwQKBgQCB+2q8RyMSXNuADhFlzOFXGrOwJm0bEUUMTPrduRQUyt4e1qOqA3klnXe3mqGcxBpnlEe/76/JacvNom6Ikxx16a0qpYRU8OWz0KU1fR6vrrEgV98241k5t6sdL4+MGA1Bo5xyXtzLb1hdUh3vpDwVU2OrnC+To3iXus/b5EBiMQKBgEI1OaBcFiyjgLGEyFKoZbtzH1mdatTExfrAQqCjOVjQByoMpGhHTXwEaosvyYu63Pa8AJPT7juSGaiKYEJFcXO9BiNyVfmQiqSHJcYeuh+fmO9IlHRHgy5xaIIC00AHS2vC/gXwmXAdPis6BZqDJeiCuOLWJ94QXn8JBT8IgGAI', 'base64'))
const msg = uint8ArrayFromString('hello') const msg = Buffer.from('hello')
// browser // browser
const dec1 = id.decrypt(uint8ArrayFromString('YRFUDx8UjbWSfDS84cDA4WowaaOmd1qFNAv5QutodCKYb9uPtU/tDiAvJzOGu5DCJRo2J0l/35P2weiB4/C2Cb1aZgXKMx/QQC+2jSJiymhqcZaYerjTvkCFwkjCaqthoVo/YXxsaFZ1q7bdTZUDH1TaJR7hWfSyzyPcA8c0w43MIsw16pY8ZaPSclvnCwhoTg1JGjMk6te3we7+wR8QU7VrPhs54mZWxrpu3NQ8xZ6xQqIedsEiNhBUccrCSzYghgsP0Ae/8iKyGyl3U6IegsJNn8jcocvzOJrmU03rgIFPjvuBdaqB38xDSTjbA123KadB28jNoSZh18q/yH3ZIg==', 'base64pad')) const dec1 = id.decrypt(Buffer.from('YRFUDx8UjbWSfDS84cDA4WowaaOmd1qFNAv5QutodCKYb9uPtU/tDiAvJzOGu5DCJRo2J0l/35P2weiB4/C2Cb1aZgXKMx/QQC+2jSJiymhqcZaYerjTvkCFwkjCaqthoVo/YXxsaFZ1q7bdTZUDH1TaJR7hWfSyzyPcA8c0w43MIsw16pY8ZaPSclvnCwhoTg1JGjMk6te3we7+wR8QU7VrPhs54mZWxrpu3NQ8xZ6xQqIedsEiNhBUccrCSzYghgsP0Ae/8iKyGyl3U6IegsJNn8jcocvzOJrmU03rgIFPjvuBdaqB38xDSTjbA123KadB28jNoSZh18q/yH3ZIg==', 'base64'))
expect(dec1).to.be.eql(msg) expect(dec1).to.be.eql(msg)
// node // node
const dec2 = id.decrypt(uint8ArrayFromString('e6yxssqXsWc27ozDy0PGKtMkCS28KwFyES2Ijz89yiz+w6bSFkNOhHPKplpPzgQEuNoUGdbseKlJFyRYHjIT8FQFBHZM8UgSkgoimbY5on4xSxXs7E5/+twjqKdB7oNveTaTf7JCwaeUYnKSjbiYFEawtMiQE91F8sTT7TmSzOZ48tUhnddAAZ3Ac/O3Z9MSAKOCDipi+JdZtXRT8KimGt36/7hjjosYmPuHR1Xy/yMTL6SMbXtBM3yAuEgbQgP+q/7kHMHji3/JvTpYdIUU+LVtkMusXNasRA+UWG2zAht18vqjFMsm9JTiihZw9jRHD4vxAhf75M992tnC+0ZuQg==', 'base64pad')) const dec2 = id.decrypt(Buffer.from('e6yxssqXsWc27ozDy0PGKtMkCS28KwFyES2Ijz89yiz+w6bSFkNOhHPKplpPzgQEuNoUGdbseKlJFyRYHjIT8FQFBHZM8UgSkgoimbY5on4xSxXs7E5/+twjqKdB7oNveTaTf7JCwaeUYnKSjbiYFEawtMiQE91F8sTT7TmSzOZ48tUhnddAAZ3Ac/O3Z9MSAKOCDipi+JdZtXRT8KimGt36/7hjjosYmPuHR1Xy/yMTL6SMbXtBM3yAuEgbQgP+q/7kHMHji3/JvTpYdIUU+LVtkMusXNasRA+UWG2zAht18vqjFMsm9JTiihZw9jRHD4vxAhf75M992tnC+0ZuQg==', 'base64'))
expect(dec2).to.be.eql(msg) expect(dec2).to.be.eql(msg)
}) })
it('fails to verify for different data', async () => { it('fails to verify for different data', async () => {
const data = uint8ArrayFromString('hello world') const data = Buffer.from('hello world')
const sig = await key.sign(data) const sig = await key.sign(data)
const valid = await key.public.verify(uint8ArrayFromString('hello'), sig) const valid = await key.public.verify(Buffer.from('hello'), sig)
expect(valid).to.be.eql(false) expect(valid).to.be.eql(false)
}) })
@ -135,24 +135,6 @@ describe('RSA', function () {
expect(key.equals(clone)).to.eql(true) expect(key.equals(clone)).to.eql(true)
}) })
it('should export a password encrypted libp2p-key', async () => {
const encryptedKey = await key.export('my secret', 'libp2p-key')
// Import the key
const importedKey = await crypto.keys.import(encryptedKey, 'my secret')
expect(key.equals(importedKey)).to.equal(true)
})
it('should fail to import libp2p-key with wrong password', async () => {
const encryptedKey = await key.export('my secret', 'libp2p-key')
try {
await crypto.keys.import(encryptedKey, 'not my secret')
} catch (err) {
expect(err).to.exist()
return
}
expect.fail('should have thrown')
})
it('needs correct password', async () => { it('needs correct password', async () => {
const pem = await key.export('another secret') const pem = await key.export('another secret')
try { try {

View File

@ -5,283 +5,77 @@ 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)
const uint8ArrayFromString = require('uint8arrays/from-string')
const fixtures = require('../fixtures/go-key-secp256k1')
describe('secp256k1 keys', () => { describe('without libp2p-crypto-secp256k1 module present', () => {
let key before(() => {
const empty = null
before(async () => { sinon.replace(crypto.keys.supportedKeys, 'secp256k1', empty)
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 () => {
expect(key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey) const key = await crypto.keys.generateKeyPair('secp256k1', 256)
expect(key.public).to.be.an.instanceof(secp256k1.Secp256k1PublicKey) expect(key).to.exist()
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 () => { it('protobuf encoding', async () => {
const _key = await secp256k1.generateKeyPair() const key = await crypto.keys.generateKeyPair('secp256k1', 256)
expect(_key).to.be.an.instanceof(secp256k1.Secp256k1PrivateKey) expect(key).to.exist()
})
it('signs', async () => { const keyMarshal = crypto.keys.marshalPrivateKey(key)
const text = randomBytes(512) const key2 = await crypto.keys.unmarshalPrivateKey(keyMarshal)
const sig = await key.sign(text) const keyMarshal2 = crypto.keys.marshalPrivateKey(key2)
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 = pk.marshal() const pkMarshal = crypto.keys.marshalPublicKey(pk)
const pk2 = secp256k1.unmarshalSecp256k1PublicKey(pkMarshal) const pk2 = crypto.keys.unmarshalPublicKey(pkMarshal)
const pkMarshal2 = pk2.marshal() const pkMarshal2 = crypto.keys.marshalPublicKey(pk2)
expect(pkMarshal).to.eql(pkMarshal2) expect(pkMarshal).to.eql(pkMarshal2)
}) })
it('key id', async () => { it('unmarshals a secp256k1 private key', async () => {
const decoded = keysPBM.PrivateKey.decode(fixtures.privateKey) const key = await crypto.keys.unmarshalPrivateKey(fixtures.pbmPrivateKey)
const key = await secp256k1.unmarshalSecp256k1PrivateKey(decoded.Data) expect(key).to.exist()
const id = await key.id()
expect(id).to.eql('QmPCyMBGEyifPtx5aa6k6wkY9N1eBf9vHK1eKfNc35q9uq')
}) })
it('should export a password encrypted libp2p-key', async () => { it('unmarshals a secp256k1 public key', () => {
const key = await crypto.keys.generateKeyPair('secp256k1') const key = crypto.keys.unmarshalPublicKey(fixtures.pbmPublicKey)
const encryptedKey = await key.export('my secret') expect(key).to.exist()
// Import the key
const importedKey = await crypto.keys.import(encryptedKey, 'my secret')
expect(key.equals(importedKey)).to.equal(true)
})
it('should fail to import libp2p-key with wrong password', async () => {
const key = await crypto.keys.generateKeyPair('secp256k1')
const encryptedKey = await key.export('my secret', 'libp2p-key')
try {
await crypto.keys.import(encryptedKey, 'not my secret')
} catch (err) {
expect(err).to.exist()
return
}
expect.fail('should have thrown')
})
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()
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 = uint8ArrayFromString('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 = uint8ArrayFromString('hello world')
const sig = await key.sign(data)
const valid = await key.public.verify(uint8ArrayFromString('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 = () => uint8ArrayFromString('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(uint8ArrayFromString('42'))).to.throw()
expect(() => secp256k1Crypto.validatePrivateKey(uint8ArrayFromString('42'))).to.throw()
})
it('validates a correct signature', async () => {
const sig = await secp256k1Crypto.hashAndSign(privKey, uint8ArrayFromString('hello'))
const valid = await secp256k1Crypto.hashAndVerify(pubKey, sig, uint8ArrayFromString('hello'))
expect(valid).to.equal(true)
})
it('errors if given a null Uint8Array 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(uint8ArrayFromString('42'), uint8ArrayFromString('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 Uint8Array to validate', async () => {
const sig = await secp256k1Crypto.hashAndSign(privKey, uint8ArrayFromString('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, uint8ArrayFromString('invalid-sig'), uint8ArrayFromString('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(uint8ArrayFromString('42'), uint8ArrayFromString('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(uint8ArrayFromString('42'))).to.throw()
})
it('throws when decompressing an invalid public key', () => {
expect(() => secp256k1Crypto.decompressPublicKey(uint8ArrayFromString('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', () => {
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)
}) })
}) })

View File

@ -3,6 +3,7 @@
'use strict' 'use strict'
const chai = require('chai') const chai = require('chai')
const { Buffer } = require('buffer')
const dirtyChai = require('dirty-chai') const dirtyChai = require('dirty-chai')
const expect = chai.expect const expect = chai.expect
chai.use(dirtyChai) chai.use(dirtyChai)
@ -31,8 +32,8 @@ describe('Util', () => {
expect(num.equals(bn)).to.be.true() expect(num.equals(bn)).to.be.true()
}) })
it('should convert base64url encoded string to Uint8Array with padding', () => { it('should convert base64url encoded string to Buffer with padding', () => {
const buf = util.base64urlToBuffer('AP8', 2) const buf = util.base64urlToBuffer('AP8', 2)
expect(Uint8Array.from([0, 255])).to.eql(buf) expect(Buffer.from([0, 255])).to.eql(buf)
}) })
}) })

View File

@ -6,7 +6,7 @@ const expect = chai.expect
// @ts-check // @ts-check
/** /**
* @type {function(any, string): Promise<void>} * @type {function(any, string): void}
*/ */
const expectErrCode = async (p, code) => { const expectErrCode = async (p, code) => {
try { try {