mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-06-25 09:11:41 +00:00
chore: add error codes (#155)
* chore: add error codes * chore: create errors with new Error() * fix: better error testin * refactor: simplify random bytes error checks
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
const errcode = require('err-code')
|
||||
const webcrypto = require('../webcrypto.js')
|
||||
const BN = require('asn1.js').bignum
|
||||
const { toBase64, toBn } = require('../util')
|
||||
const validateCurveType = require('./validate-curve-type')
|
||||
|
||||
const bits = {
|
||||
'P-256': 256,
|
||||
@ -11,6 +13,8 @@ const bits = {
|
||||
}
|
||||
|
||||
exports.generateEphmeralKeyPair = async function (curve) {
|
||||
validateCurveType(Object.keys(bits), curve)
|
||||
|
||||
const pair = await webcrypto.subtle.generateKey(
|
||||
{
|
||||
name: 'ECDH',
|
||||
@ -96,7 +100,7 @@ function unmarshalPublicKey (curve, key) {
|
||||
const byteLen = curveLengths[curve]
|
||||
|
||||
if (!key.slice(0, 1).equals(Buffer.from([4]))) {
|
||||
throw new Error('Invalid key format')
|
||||
throw errcode(new Error('Cannot unmarshal public key - invalid key format'), 'ERR_INVALID_KEY_FORMAT')
|
||||
}
|
||||
const x = new BN(key.slice(1, byteLen + 1))
|
||||
const y = new BN(key.slice(1 + byteLen))
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const crypto = require('crypto')
|
||||
const validateCurveType = require('./validate-curve-type')
|
||||
|
||||
const curves = {
|
||||
'P-256': 'prime256v1',
|
||||
@ -9,9 +10,8 @@ const curves = {
|
||||
}
|
||||
|
||||
exports.generateEphmeralKeyPair = async function (curve) { // eslint-disable-line require-await
|
||||
if (!curves[curve]) {
|
||||
throw new Error(`Unkown curve: ${curve}`)
|
||||
}
|
||||
validateCurveType(Object.keys(curves), curve)
|
||||
|
||||
const ecdh = crypto.createECDH(curves[curve])
|
||||
ecdh.generateKeys()
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
const multihashing = require('multihashing-async')
|
||||
const protobuf = require('protons')
|
||||
const bs58 = require('bs58')
|
||||
const errcode = require('err-code')
|
||||
|
||||
const crypto = require('./ed25519')
|
||||
const pbm = protobuf(require('./keys.proto'))
|
||||
@ -49,10 +50,6 @@ class Ed25519PrivateKey {
|
||||
}
|
||||
|
||||
get public () {
|
||||
if (!this._publicKey) {
|
||||
throw new Error('public key not provided')
|
||||
}
|
||||
|
||||
return new Ed25519PublicKey(this._publicKey)
|
||||
}
|
||||
|
||||
@ -117,7 +114,7 @@ function ensureKey (key, length) {
|
||||
key = new Uint8Array(key)
|
||||
}
|
||||
if (!(key instanceof Uint8Array) || key.length !== length) {
|
||||
throw new Error('Key must be a Uint8Array or Buffer of length ' + length)
|
||||
throw errcode(new Error('Key must be a Uint8Array or Buffer of length ' + length), 'ERR_INVALID_KEY_TYPE')
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ require('node-forge/lib/asn1')
|
||||
require('node-forge/lib/rsa')
|
||||
require('node-forge/lib/pbe')
|
||||
const forge = require('node-forge/lib/forge')
|
||||
const errcode = require('err-code')
|
||||
|
||||
exports = module.exports
|
||||
|
||||
@ -18,9 +19,18 @@ const supportedKeys = {
|
||||
exports.supportedKeys = supportedKeys
|
||||
exports.keysPBM = keysPBM
|
||||
|
||||
function isValidKeyType (keyType) {
|
||||
const key = supportedKeys[keyType.toLowerCase()]
|
||||
return key !== undefined
|
||||
const ErrMissingSecp256K1 = {
|
||||
message: 'secp256k1 support requires libp2p-crypto-secp256k1 package',
|
||||
code: 'ERR_MISSING_PACKAGE'
|
||||
}
|
||||
|
||||
function typeToKey (type) {
|
||||
let key = supportedKeys[type.toLowerCase()]
|
||||
if (!key) {
|
||||
const supported = Object.keys(supportedKeys).join(' / ')
|
||||
throw errcode(new Error(`invalid or unsupported key type ${type}. Must be ${supported}`), 'ERR_UNSUPPORTED_KEY_TYPE')
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
exports.keyStretcher = require('./key-stretcher')
|
||||
@ -28,24 +38,15 @@ exports.generateEphemeralKeyPair = require('./ephemeral-keys')
|
||||
|
||||
// Generates a keypair of the given type and bitsize
|
||||
exports.generateKeyPair = async (type, bits) => { // eslint-disable-line require-await
|
||||
let key = supportedKeys[type.toLowerCase()]
|
||||
|
||||
if (!key) {
|
||||
throw new Error('invalid or unsupported key type')
|
||||
}
|
||||
|
||||
return key.generateKeyPair(bits)
|
||||
return typeToKey(type).generateKeyPair(bits)
|
||||
}
|
||||
|
||||
// Generates a keypair of the given type and bitsize
|
||||
// seed is a 32 byte uint8array
|
||||
exports.generateKeyPairFromSeed = async (type, seed, bits) => { // eslint-disable-line require-await
|
||||
let key = supportedKeys[type.toLowerCase()]
|
||||
if (!key) {
|
||||
throw new Error('invalid or unsupported key type')
|
||||
}
|
||||
const key = typeToKey(type)
|
||||
if (type.toLowerCase() !== 'ed25519') {
|
||||
throw new Error('Seed key derivation is unimplemented for RSA or secp256k1')
|
||||
throw errcode(new Error('Seed key derivation is unimplemented for RSA or secp256k1'), 'ERR_UNSUPPORTED_KEY_DERIVATION_TYPE')
|
||||
}
|
||||
return key.generateKeyPairFromSeed(seed, bits)
|
||||
}
|
||||
@ -65,20 +66,17 @@ exports.unmarshalPublicKey = (buf) => {
|
||||
if (supportedKeys.secp256k1) {
|
||||
return supportedKeys.secp256k1.unmarshalSecp256k1PublicKey(data)
|
||||
} else {
|
||||
throw new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')
|
||||
throw errcode(new Error(ErrMissingSecp256K1.message), ErrMissingSecp256K1.code)
|
||||
}
|
||||
default:
|
||||
throw new Error('invalid or unsupported key type')
|
||||
typeToKey(decoded.Type) // throws because type is not supported
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a public key object into a protobuf serialized public key
|
||||
exports.marshalPublicKey = (key, type) => {
|
||||
type = (type || 'rsa').toLowerCase()
|
||||
if (!isValidKeyType(type)) {
|
||||
throw new Error('invalid or unsupported key type')
|
||||
}
|
||||
|
||||
typeToKey(type) // check type
|
||||
return key.bytes
|
||||
}
|
||||
|
||||
@ -97,27 +95,24 @@ exports.unmarshalPrivateKey = async (buf) => { // eslint-disable-line require-aw
|
||||
if (supportedKeys.secp256k1) {
|
||||
return supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey(data)
|
||||
} else {
|
||||
throw new Error('secp256k1 support requires libp2p-crypto-secp256k1 package')
|
||||
throw errcode(new Error(ErrMissingSecp256K1.message), ErrMissingSecp256K1.code)
|
||||
}
|
||||
default:
|
||||
throw new Error('invalid or unsupported key type')
|
||||
typeToKey(decoded.Type) // throws because type is not supported
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a private key object into a protobuf serialized private key
|
||||
exports.marshalPrivateKey = (key, type) => {
|
||||
type = (type || 'rsa').toLowerCase()
|
||||
if (!isValidKeyType(type)) {
|
||||
throw new Error('invalid or unsupported key type')
|
||||
}
|
||||
|
||||
typeToKey(type) // check type
|
||||
return key.bytes
|
||||
}
|
||||
|
||||
exports.import = async (pem, password) => { // eslint-disable-line require-await
|
||||
const key = forge.pki.decryptRsaPrivateKey(pem, password)
|
||||
if (key === null) {
|
||||
throw new Error('Cannot read the key, most likely the password is wrong or not a RSA key')
|
||||
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))
|
||||
der = Buffer.from(der.getBytes(), 'binary')
|
||||
|
@ -1,5 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const errcode = require('err-code')
|
||||
const hmac = require('../hmac')
|
||||
|
||||
const cipherMap = {
|
||||
@ -23,11 +24,12 @@ module.exports = async (cipherType, hash, secret) => {
|
||||
const cipher = cipherMap[cipherType]
|
||||
|
||||
if (!cipher) {
|
||||
throw new Error('unkown cipherType passed')
|
||||
const allowed = Object.keys(cipherMap).join(' / ')
|
||||
throw errcode(new Error(`unknown cipher type '${cipherType}'. Must be ${allowed}`), 'ERR_INVALID_CIPHER_TYPE')
|
||||
}
|
||||
|
||||
if (!hash) {
|
||||
throw new Error('unkown hashType passed')
|
||||
throw errcode(new Error(`missing hash type`), 'ERR_MISSING_HASH_TYPE')
|
||||
}
|
||||
|
||||
const cipherKeySize = cipher.keySize
|
||||
|
@ -3,6 +3,7 @@
|
||||
const multihashing = require('multihashing-async')
|
||||
const protobuf = require('protons')
|
||||
const bs58 = require('bs58')
|
||||
const errcode = require('err-code')
|
||||
|
||||
const crypto = require('./rsa')
|
||||
const pbm = protobuf(require('./keys.proto'))
|
||||
@ -61,7 +62,7 @@ class RsaPrivateKey {
|
||||
|
||||
get public () {
|
||||
if (!this._publicKey) {
|
||||
throw new Error('public key not provided')
|
||||
throw errcode(new Error('public key not provided'), 'ERR_PUBKEY_NOT_PROVIDED')
|
||||
}
|
||||
|
||||
return new RsaPublicKey(this._publicKey)
|
||||
@ -123,7 +124,7 @@ class RsaPrivateKey {
|
||||
}
|
||||
pem = forge.pki.encryptRsaPrivateKey(privateKey, password, options)
|
||||
} else {
|
||||
throw new Error(`Unknown export format '${format}'`)
|
||||
throw errcode(new Error(`Unknown export format '${format}'. Must be pkcs-8`), 'ERR_INVALID_EXPORT_FORMAT')
|
||||
}
|
||||
|
||||
return pem
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const crypto = require('crypto')
|
||||
const errcode = require('err-code')
|
||||
const randomBytes = require('../random-bytes')
|
||||
|
||||
let keypair
|
||||
@ -40,7 +41,7 @@ exports.generateKey = async function (bits) { // eslint-disable-line require-awa
|
||||
// Takes a jwk key
|
||||
exports.unmarshalPrivateKey = async function (key) { // eslint-disable-line require-await
|
||||
if (!key) {
|
||||
throw new Error('Key is invalid')
|
||||
throw errcode(new Error('Missing key parameter'), 'ERR_MISSING_KEY')
|
||||
}
|
||||
return {
|
||||
privateKey: key,
|
||||
|
10
src/keys/validate-curve-type.js
Normal file
10
src/keys/validate-curve-type.js
Normal file
@ -0,0 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
const errcode = require('err-code')
|
||||
|
||||
module.exports = function (curveTypes, type) {
|
||||
if (!curveTypes.includes(type)) {
|
||||
const names = curveTypes.join(' / ')
|
||||
throw errcode(new Error(`Unknown curve: ${type}. Must be ${names}`), 'ERR_INVALID_CURVE')
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user