From e01977c5a353d39422acbecbb518e78c7514c227 Mon Sep 17 00:00:00 2001 From: Carson Farmer Date: Fri, 17 Jan 2020 03:04:52 -0800 Subject: [PATCH] feat: add typescript types + linting/tests (#161) * feat: adds typescript types + linting/tests Signed-off-by: Carson Farmer * feat: much better types testing Signed-off-by: Carson Farmer * chore: revert eslintignore Signed-off-by: Carson Farmer * feat: update types entry Signed-off-by: Carson Farmer * chore: exclude has no effect here Signed-off-by: Carson Farmer * feat: more nuanced return types on keypair Signed-off-by: Carson Farmer --- package.json | 10 +- src/index.d.ts | 345 +++++++++++++++++++++++++++++++ src/keys/rsa-class.js | 1 - src/keys/rsa.js | 5 +- test/aes/aes.spec.js | 7 + test/crypto.spec.js | 10 +- test/keys/ed25519.spec.js | 14 +- test/keys/ephemeral-keys.spec.js | 4 + test/keys/key-stretcher.spec.js | 4 + test/keys/rsa.spec.js | 23 ++- test/keys/secp256k1.spec.js | 3 +- test/util/index.js | 5 + tsconfig.json | 30 +++ 13 files changed, 449 insertions(+), 12 deletions(-) create mode 100644 src/index.d.ts create mode 100644 tsconfig.json diff --git a/package.json b/package.json index 4581820..96026e7 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.17.1", "description": "Crypto primitives for libp2p", "main": "src/index.js", + "types": "src/index.d.ts", "leadMaintainer": "Jacob Heun ", "browser": { "./src/hmac/index.js": "./src/hmac/index-browser.js", @@ -25,7 +26,8 @@ "release-minor": "aegir release --type minor", "release-major": "aegir release --type major", "coverage": "aegir coverage --ignore src/keys/keys.proto.js", - "size": "aegir build --bundlesize" + "size": "aegir build --bundlesize", + "test:types": "npx tsc" }, "keywords": [ "IPFS", @@ -53,6 +55,12 @@ "ursa-optional": "~0.10.1" }, "devDependencies": { + "@types/bn.js": "^4.11.6", + "@types/chai": "^4.2.7", + "@types/chai-string": "^1.4.2", + "@types/dirty-chai": "^2.0.2", + "@types/mocha": "^5.2.7", + "@types/sinon": "^7.5.1", "aegir": "^20.4.1", "benchmark": "^2.1.4", "chai": "^4.2.0", diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 0000000..d9d5d9c --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,345 @@ +/// + +/** + * Supported key types. + */ +export type KeyType = "Ed25519" | "RSA" | "secp256k1"; + +/** + * Maps an IPFS hash name to its node-forge equivalent. + * See https://github.com/multiformats/multihash/blob/master/hashtable.csv + */ +export type HashType = "SHA1" | "SHA256" | "SHA512"; + +/** + * Supported curve types. + */ +export type CurveType = "P-256" | "P-384" | "P-521"; + +/** + * Supported cipher types. + */ +export type CipherType = "AES-128" | "AES-256" | "Blowfish"; + +/** + * Exposes an interface to AES encryption (formerly Rijndael), + * as defined in U.S. Federal Information Processing Standards Publication 197. + * This uses CTR mode. + */ +export namespace aes { + /** + * AES Cipher in CTR mode. + */ + interface Cipher { + encrypt(data: Buffer): Promise; + decrypt(data: Buffer): Promise; + } + /** + * 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 iv Must have length 16. + */ + function create(key: Buffer, iv: Buffer): Promise; +} + +/** + * Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) + * as defined in U.S. Federal Information Processing Standards Publication 198. + * An HMAC is a cryptographic hash that uses a key to sign a message. + * The receiver verifies the hash by recomputing it using the same key. + */ +export namespace hmac { + /** + * HMAC Digest. + */ + interface Digest { + digest(data: Buffer): Promise; + length: 20 | 32 | 64 | number; + } + /** + * Create a new HMAC Digest. + */ + function create( + hash: "SHA1" | "SHA256" | "SHA512" | string, + secret: Buffer + ): Promise; +} + +/** + * Generic public key interface. + */ +export interface PublicKey { + readonly bytes: Buffer; + verify(data: Buffer, sig: Buffer): Promise; + marshal(): Buffer; + equals(key: PublicKey): boolean; + hash(): Promise; +} + +/** + * Generic private key interface. + */ +export interface PrivateKey { + readonly public: PublicKey; + readonly bytes: Buffer; + sign(data: Buffer): Promise; + marshal(): Buffer; + equals(key: PrivateKey): boolean; + hash(): Promise; + /** + * 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. + */ + id(): Promise; +} + +export interface Keystretcher { + (res: Buffer): Keystretcher; + iv: Buffer; + cipherKey: Buffer; + macKey: Buffer; +} + +export interface StretchPair { + k1: Keystretcher; + k2: Keystretcher; +} + +/** + * Exposes an interface to various cryptographic key generation routines. + * 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 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. + */ +export namespace keys { + export {}; + export namespace supportedKeys { + namespace rsa { + class RsaPublicKey implements PublicKey { + constructor(key: Buffer); + readonly bytes: Buffer; + verify(data: Buffer, sig: Buffer): Promise; + marshal(): Buffer; + encrypt(bytes: Buffer): Buffer; + equals(key: PublicKey): boolean; + hash(): Promise; + } + + // Type alias for export method + export type KeyInfo = any; + + class RsaPrivateKey implements PrivateKey { + constructor(key: any, publicKey: Buffer); + readonly public: RsaPublicKey; + readonly bytes: Buffer; + genSecret(): Buffer; + sign(data: Buffer): Promise; + decrypt(bytes: Buffer): Buffer; + marshal(): Buffer; + equals(key: PrivateKey): boolean; + hash(): Promise; + id(): Promise; + /** + * 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: Buffer): RsaPublicKey; + function unmarshalRsaPrivateKey(buf: Buffer): Promise; + function generateKeyPair(bits: number): Promise; + function fromJwk(jwk: Buffer): Promise; + } + + namespace ed25519 { + class Ed25519PublicKey implements PublicKey { + constructor(key: Buffer); + readonly bytes: Buffer; + verify(data: Buffer, sig: Buffer): Promise; + marshal(): Buffer; + encrypt(bytes: Buffer): Buffer; + equals(key: PublicKey): boolean; + hash(): Promise; + } + + class Ed25519PrivateKey implements PrivateKey { + constructor(key: Buffer, publicKey: Buffer); + readonly public: Ed25519PublicKey; + readonly bytes: Buffer; + sign(data: Buffer): Promise; + marshal(): Buffer; + equals(key: PrivateKey): boolean; + hash(): Promise; + id(): Promise; + } + + function unmarshalEd25519PrivateKey( + buf: Buffer + ): Promise; + function unmarshalEd25519PublicKey(buf: Buffer): Ed25519PublicKey; + function generateKeyPair(): Promise; + function generateKeyPairFromSeed( + seed: Buffer + ): Promise; + } + + namespace secp256k1 { + class Secp256k1PublicKey implements PublicKey { + constructor(key: Buffer); + readonly bytes: Buffer; + verify(data: Buffer, sig: Buffer): Promise; + marshal(): Buffer; + encrypt(bytes: Buffer): Buffer; + equals(key: PublicKey): boolean; + hash(): Promise; + } + + class Secp256k1PrivateKey implements PrivateKey { + constructor(key: Uint8Array | Buffer, publicKey: Uint8Array | Buffer); + readonly public: Secp256k1PublicKey; + readonly bytes: Buffer; + sign(data: Buffer): Promise; + marshal(): Buffer; + equals(key: PrivateKey): boolean; + hash(): Promise; + id(): Promise; + } + + function unmarshalSecp256k1PrivateKey( + bytes: Buffer + ): Promise; + function unmarshalSecp256k1PublicKey(bytes: Buffer): Secp256k1PublicKey; + function generateKeyPair(): Promise; + } + } + + export const keysPBM: any; + + /** + * Generates a keypair of the given type and bitsize. + * @param type One of the supported key types. + * @param bits Number of bits. Minimum of 1024. + */ + export function generateKeyPair( + type: KeyType | string, + bits: number + ): Promise; + export function generateKeyPair( + type: "Ed25519", + bits: number + ): Promise; + export function generateKeyPair( + type: "RSA", + bits: number + ): Promise; + export function generateKeyPair( + type: "secp256k1", + bits: number + ): Promise; + + /** + * Generates a keypair of the given type and bitsize. + * @param type One of the supported key types. Currently only 'Ed25519' is supported. + * @param seed A 32 byte uint8array. + * @param bits Number of bits. Minimum of 1024. + */ + export function generateKeyPairFromSeed( + type: KeyType | string, + seed: Uint8Array, + bits: number + ): Promise; + export function generateKeyPairFromSeed( + type: "Ed25519", + seed: Uint8Array, + bits: number + ): Promise; + + /** + * Generates an ephemeral public key and returns a function that will compute the shared secret key. + * Focuses only on ECDH now, but can be made more general in the future. + * @param curve The curve to use. One of 'P-256', 'P-384', 'P-521' is currently supported. + */ + export function generateEphemeralKeyPair( + curve: CurveType | string + ): Promise<{ + key: Buffer; + genSharedKey: (theirPub: Buffer, forcePrivate?: any) => Promise; + }>; + + /** + * Generates a set of keys for each party by stretching the shared key. + * @param cipherType The cipher type to use. One of 'AES-128', 'AES-256', or 'Blowfish' + * @param hashType The hash type to use. One of 'SHA1', 'SHA2256', or 'SHA2512'. + * @param secret The shared key secret. + */ + export function keyStretcher( + cipherType: CipherType | string, + hashType: HashType | string, + secret: Buffer | string + ): Promise; + + /** + * Converts a protobuf serialized public key into its representative object. + * @param buf The protobuf serialized public key. + */ + export function unmarshalPublicKey(buf: Buffer): PublicKey; + + /** + * Converts a public key object into a protobuf serialized public key. + * @param key An RSA, Ed25519, or Secp256k1 public key object. + * @param type One of the supported key types. + */ + export function marshalPublicKey(key: PublicKey, type?: KeyType | string): Buffer; + + /** + * Converts a protobuf serialized private key into its representative object. + * @param buf The protobuf serialized private key. + */ + export function unmarshalPrivateKey(buf: Buffer): Promise; + + /** + * Converts a private key object into a protobuf serialized private key. + * @param key An RSA, Ed25519, or Secp256k1 private key object. + * @param type One of the supported key types. + */ + export function marshalPrivateKey(key: PrivateKey, type?: KeyType | string): Buffer; + + /** + * Converts a PEM password protected private key into its representative object. + * @param pem Password protected private key in PEM format. + * @param password The password used to protect the key. + */ + function _import(pem: string, password: string): Promise; + export { _import as import }; +} + +/** + * Generates a Buffer populated by random bytes. + * @param The size of the random bytes Buffer. + */ +export function randomBytes(number: number): Buffer; + +/** + * Computes the Password-Based Key Derivation Function 2. + * @param password The password. + * @param salt The salt. + * @param iterations Number of iterations to use. + * @param keySize The size of the output key in bytes. + * @param hash The hash name ('sha1', 'sha2-512, ...) + */ +export function pbkdf2( + password: string | Buffer, + salt: string | Buffer, + iterations: number, + keySize: number, + hash: string +): Buffer; diff --git a/src/keys/rsa-class.js b/src/keys/rsa-class.js index bc9289a..6a4775c 100644 --- a/src/keys/rsa-class.js +++ b/src/keys/rsa-class.js @@ -110,7 +110,6 @@ class RsaPrivateKey { * * @param {string} password - The password to read the encrypted PEM * @param {string} [format] - Defaults to 'pkcs-8'. - * @returns {KeyInfo} */ async export (password, format = 'pkcs-8') { // eslint-disable-line require-await let pem = null diff --git a/src/keys/rsa.js b/src/keys/rsa.js index 06605a3..f5704e8 100644 --- a/src/keys/rsa.js +++ b/src/keys/rsa.js @@ -3,7 +3,10 @@ const crypto = require('crypto') const errcode = require('err-code') const randomBytes = require('../random-bytes') - +// @ts-check +/** + * @type {PrivateKey} + */ let keypair try { if (process.env.LP2P_FORCE_CRYPTO_LIB === 'keypair') { diff --git a/test/aes/aes.spec.js b/test/aes/aes.spec.js index ff11658..1c0cdd7 100644 --- a/test/aes/aes.spec.js +++ b/test/aes/aes.spec.js @@ -1,4 +1,5 @@ /* eslint max-nested-callbacks: ["error", 8] */ +/* eslint-disable valid-jsdoc */ /* eslint-env mocha */ 'use strict' @@ -17,6 +18,8 @@ const bytes = { 32: 'AES-256' } +/** @typedef {import("libp2p-crypto").aes.Cipher} Cipher */ + describe('AES-CTR', () => { Object.keys(bytes).forEach((byte) => { it(`${bytes[byte]} - encrypt and decrypt`, async () => { @@ -93,6 +96,10 @@ describe('AES-CTR', () => { }) }) +// @ts-check +/** + * @type {function(Cipher): void} + */ async function encryptAndDecrypt (cipher) { const data = Buffer.alloc(100) data.fill(Math.ceil(Math.random() * 100)) diff --git a/test/crypto.spec.js b/test/crypto.spec.js index 0476c8d..c3213e9 100644 --- a/test/crypto.spec.js +++ b/test/crypto.spec.js @@ -10,8 +10,14 @@ const crypto = require('../src') const fixtures = require('./fixtures/go-key-rsa') const { expectErrCode } = require('./util') +/** @typedef {import("libp2p-crypto").PrivateKey} PrivateKey */ + describe('libp2p-crypto', function () { this.timeout(20 * 1000) + // @ts-check + /** + * @type {PrivateKey} + */ let key before(async () => { key = await crypto.keys.generateKeyPair('RSA', 512) @@ -109,9 +115,9 @@ describe('libp2p-crypto', function () { }) describe('randomBytes', () => { - it('throws with no number passed', () => { + it('throws with invalid number passed', () => { expect(() => { - crypto.randomBytes() + crypto.randomBytes(-1) }).to.throw() }) diff --git a/test/keys/ed25519.spec.js b/test/keys/ed25519.spec.js index 914bfc4..1fc2716 100644 --- a/test/keys/ed25519.spec.js +++ b/test/keys/ed25519.spec.js @@ -12,8 +12,14 @@ const fixtures = require('../fixtures/go-key-ed25519') const testGarbage = require('../helpers/test-garbage-error-handling') +/** @typedef {import("libp2p-crypto").PrivateKey} PrivateKey */ + describe('ed25519', function () { this.timeout(20 * 1000) + // @ts-check + /** + * @type {PrivateKey} + */ let key before(async () => { key = await crypto.keys.generateKeyPair('Ed25519', 512) @@ -118,11 +124,15 @@ describe('ed25519', function () { describe('throws error instead of crashing', () => { const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey) - testGarbage.doTests('key.verify', key.verify.bind(key), 2) - testGarbage.doTests('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys)) + testGarbage.doTests('key.verify', key.verify.bind(key), 2, null) + testGarbage.doTests('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys), null, null) }) describe('go interop', () => { + // @ts-check + /** + * @type {PrivateKey} + */ let privateKey before(async () => { diff --git a/test/keys/ephemeral-keys.spec.js b/test/keys/ephemeral-keys.spec.js index 57fcb00..a139626 100644 --- a/test/keys/ephemeral-keys.spec.js +++ b/test/keys/ephemeral-keys.spec.js @@ -11,6 +11,10 @@ const fixtures = require('../fixtures/go-elliptic-key') const crypto = require('../../src') const curves = ['P-256', 'P-384'] // 'P-521' fails in tests :( no clue why +// @ts-check +/** + * @type {Record} + */ const lengths = { 'P-256': 65, 'P-384': 97, diff --git a/test/keys/key-stretcher.spec.js b/test/keys/key-stretcher.spec.js index b0e528e..70ef392 100644 --- a/test/keys/key-stretcher.spec.js +++ b/test/keys/key-stretcher.spec.js @@ -15,6 +15,10 @@ describe('keyStretcher', () => { const ciphers = ['AES-128', 'AES-256', 'Blowfish'] const hashes = ['SHA1', 'SHA256', 'SHA512'] let res + // @ts-check + /** + * @type {Buffer} + */ let secret before(async () => { diff --git a/test/keys/rsa.spec.js b/test/keys/rsa.spec.js index 22be3bc..dc8db15 100644 --- a/test/keys/rsa.spec.js +++ b/test/keys/rsa.spec.js @@ -15,12 +15,18 @@ const fixtures = require('../fixtures/go-key-rsa') const testGarbage = require('../helpers/test-garbage-error-handling') +/** @typedef {import('libp2p-crypto').keys.supportedKeys.rsa.RsaPrivateKey} RsaPrivateKey */ + describe('RSA', function () { this.timeout(20 * 1000) + // @ts-check + /** + * @type {RsaPrivateKey} + */ let key before(async () => { - key = await crypto.keys.generateKeyPair('RSA', 512) + key = await rsa.generateKeyPair(512) }) it('generates a valid key', async () => { @@ -88,15 +94,19 @@ describe('RSA', function () { }) it('encrypt decrypt browser/node interop', async () => { + // @ts-check + /** + * @type {any} + */ 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 = Buffer.from('hello') // browser - const dec1 = await id.decrypt(Buffer.from('YRFUDx8UjbWSfDS84cDA4WowaaOmd1qFNAv5QutodCKYb9uPtU/tDiAvJzOGu5DCJRo2J0l/35P2weiB4/C2Cb1aZgXKMx/QQC+2jSJiymhqcZaYerjTvkCFwkjCaqthoVo/YXxsaFZ1q7bdTZUDH1TaJR7hWfSyzyPcA8c0w43MIsw16pY8ZaPSclvnCwhoTg1JGjMk6te3we7+wR8QU7VrPhs54mZWxrpu3NQ8xZ6xQqIedsEiNhBUccrCSzYghgsP0Ae/8iKyGyl3U6IegsJNn8jcocvzOJrmU03rgIFPjvuBdaqB38xDSTjbA123KadB28jNoSZh18q/yH3ZIg==', 'base64')) + const dec1 = id.decrypt(Buffer.from('YRFUDx8UjbWSfDS84cDA4WowaaOmd1qFNAv5QutodCKYb9uPtU/tDiAvJzOGu5DCJRo2J0l/35P2weiB4/C2Cb1aZgXKMx/QQC+2jSJiymhqcZaYerjTvkCFwkjCaqthoVo/YXxsaFZ1q7bdTZUDH1TaJR7hWfSyzyPcA8c0w43MIsw16pY8ZaPSclvnCwhoTg1JGjMk6te3we7+wR8QU7VrPhs54mZWxrpu3NQ8xZ6xQqIedsEiNhBUccrCSzYghgsP0Ae/8iKyGyl3U6IegsJNn8jcocvzOJrmU03rgIFPjvuBdaqB38xDSTjbA123KadB28jNoSZh18q/yH3ZIg==', 'base64')) expect(dec1).to.be.eql(msg) // node - const dec2 = await id.decrypt(Buffer.from('e6yxssqXsWc27ozDy0PGKtMkCS28KwFyES2Ijz89yiz+w6bSFkNOhHPKplpPzgQEuNoUGdbseKlJFyRYHjIT8FQFBHZM8UgSkgoimbY5on4xSxXs7E5/+twjqKdB7oNveTaTf7JCwaeUYnKSjbiYFEawtMiQE91F8sTT7TmSzOZ48tUhnddAAZ3Ac/O3Z9MSAKOCDipi+JdZtXRT8KimGt36/7hjjosYmPuHR1Xy/yMTL6SMbXtBM3yAuEgbQgP+q/7kHMHji3/JvTpYdIUU+LVtkMusXNasRA+UWG2zAht18vqjFMsm9JTiihZw9jRHD4vxAhf75M992tnC+0ZuQg==', 'base64')) + 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) }) @@ -142,7 +152,12 @@ describe('RSA', function () { describe('throws error instead of crashing', () => { const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey) testGarbage.doTests('key.verify', key.verify.bind(key), 2, true) - testGarbage.doTests('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys)) + testGarbage.doTests( + 'crypto.keys.unmarshalPrivateKey', + crypto.keys.unmarshalPrivateKey.bind(crypto.keys), + null, + null + ) }) describe('go interop', () => { diff --git a/test/keys/secp256k1.spec.js b/test/keys/secp256k1.spec.js index a40de23..2f17613 100644 --- a/test/keys/secp256k1.spec.js +++ b/test/keys/secp256k1.spec.js @@ -12,7 +12,8 @@ const crypto = require('../../src') describe('without libp2p-crypto-secp256k1 module present', () => { before(() => { - sinon.replace(crypto.keys.supportedKeys, 'secp256k1', null) + const empty = null + sinon.replace(crypto.keys.supportedKeys, 'secp256k1', empty) }) after(() => { diff --git a/test/util/index.js b/test/util/index.js index 905fad9..7293d4f 100644 --- a/test/util/index.js +++ b/test/util/index.js @@ -1,8 +1,13 @@ +/* eslint-disable valid-jsdoc */ 'use strict' const chai = require('chai') const expect = chai.expect +// @ts-check +/** + * @type {function(any, string): void} + */ const expectErrCode = async (p, code) => { try { await p diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5eb556d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "target": "ES5", + "noImplicitAny": false, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "baseUrl": ".", + "paths": { + "libp2p-crypto": [ + "./src", + "../../src", + "../src" + ] + }, + "types": ["node", "mocha", "chai"], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": ["./src/index.d.ts",], + "include": ["./test/**/*.spec.js"] +}