From f99c565c8c0d2f97e78c8bba6a64e07e22d5a0b6 Mon Sep 17 00:00:00 2001 From: Curtis Date: Mon, 19 Aug 2024 14:08:28 +0100 Subject: [PATCH] feat: errors introducing error codes and refactoring Apollo errors (#265) Signed-off-by: Curtish --- src/apollo/Apollo.ts | 98 +++++-------- src/apollo/utils/Ed25519PrivateKey.ts | 2 +- src/apollo/utils/Secp256k1PrivateKey.ts | 9 +- src/apollo/utils/Secp256k1PublicKey.ts | 2 +- src/apollo/utils/derivation/DerivationPath.ts | 41 +++--- src/castor/did/prismDID/PrismDIDPublicKey.ts | 2 +- src/domain/models/errors/Apollo.ts | 135 ++++++++++-------- src/domain/models/errors/Common.ts | 12 +- src/domain/models/errors/Mnemonic.ts | 23 --- src/domain/models/errors/Pollux.ts | 7 +- src/domain/models/keyManagement/Key.ts | 2 +- src/domain/utils/hash.ts | 55 +++---- src/pollux/Pollux.ts | 5 +- tests/apollo/Apollo.test.ts | 18 ++- tests/castor/PrismDID.test.ts | 3 +- tests/pollux/Pollux.revocation.test.ts | 4 +- 16 files changed, 190 insertions(+), 228 deletions(-) delete mode 100644 src/domain/models/errors/Mnemonic.ts diff --git a/src/apollo/Apollo.ts b/src/apollo/Apollo.ts index 6235e3b3c..11b2bdf51 100644 --- a/src/apollo/Apollo.ts +++ b/src/apollo/Apollo.ts @@ -16,10 +16,6 @@ import { StorableKey, KeyRestoration, } from "../domain"; -import { - MnemonicLengthException, - MnemonicWordException, -} from "../domain/models/errors/Mnemonic"; import { Ed25519PrivateKey } from "./utils/Ed25519PrivateKey"; import { X25519PrivateKey } from "./utils/X25519PrivateKey"; @@ -30,7 +26,7 @@ import { Secp256k1PublicKey } from "./utils/Secp256k1PublicKey"; import { Ed25519PublicKey } from "./utils/Ed25519PublicKey"; import { X25519PublicKey } from "./utils/X25519PublicKey"; -import { notEmptyString } from "../utils"; +import { isEmpty, notEmptyString } from "../utils"; import ApolloPKG from "@hyperledger/identus-apollo"; import { PrismDerivationPath } from "../domain/models/derivation/schemas/PrismDerivation"; @@ -154,13 +150,11 @@ export default class Apollo implements ApolloInterface, KeyRestoration { const mnemonicString = mnemonics.join(" "); if (mnemonics.length != 12 && mnemonics.length != 24) { - throw new MnemonicLengthException( - "Word list must be 12 or 24 words in length" - ); + throw new ApolloError.MnemonicLengthError(); } if (!bip39.validateMnemonic(mnemonicString, wordlist)) { - throw new MnemonicWordException(`Invalid mnemonic word/s`); + throw new ApolloError.MnemonicWordError(mnemonics); } const seed = Mnemonic.createSeed(mnemonics, `mnemonic${passphrase}`); @@ -215,22 +209,18 @@ export default class Apollo implements ApolloInterface, KeyRestoration { createPublicKey(parameters: { [name: KeyProperties | string]: any; }): PublicKey { - if (!parameters[KeyProperties.type]) { - throw new ApolloError.InvalidKeyType( - parameters[KeyProperties.type], - Object.values(KeyTypes) - ); + const keyType = parameters[KeyProperties.type]; + const keyCurve = parameters[KeyProperties.curve]; + + if (isEmpty(keyType)) { + throw new ApolloError.InvalidKeyType(keyType); } - if (!parameters[KeyProperties.curve]) { - throw new ApolloError.InvalidKeyCurve( - parameters[KeyProperties.curve], - Object.values(Curve) - ); + + if (isEmpty(keyCurve)) { + throw new ApolloError.InvalidKeyCurve(keyCurve); } - const keyType = parameters[KeyProperties.type]; - const { curve } = getKeyCurveByNameAndIndex( - parameters[KeyProperties.curve] - ); + + const { curve } = getKeyCurveByNameAndIndex(keyCurve); const keyData = parameters[KeyProperties.rawKey]; if (keyType === KeyTypes.EC) { @@ -238,22 +228,23 @@ export default class Apollo implements ApolloInterface, KeyRestoration { if (keyData) { return new Ed25519PublicKey(keyData); } - throw new ApolloError.InvalidPrivateKey("Missing raw bytes"); + + throw new ApolloError.MissingKeyParameters(KeyProperties.rawKey); } + if (curve === Curve.SECP256K1) { if (keyData) { return new Secp256k1PublicKey(keyData); } else { const xData = parameters[KeyProperties.curvePointX]; const yData = parameters[KeyProperties.curvePointY]; + if (xData && yData) { - return Secp256k1PublicKey.secp256k1FromByteCoordinates( - xData, - yData - ); + return Secp256k1PublicKey.secp256k1FromByteCoordinates(xData, yData); } } - throw new ApolloError.InvalidPrivateKey("Missing raw bytes or coordinates"); + + throw new ApolloError.MissingKeyParameters(KeyProperties.rawKey, KeyProperties.curvePointX, KeyProperties.curvePointY); } } @@ -262,11 +253,12 @@ export default class Apollo implements ApolloInterface, KeyRestoration { if (keyData) { return new X25519PublicKey(keyData); } - throw new ApolloError.InvalidPrivateKey("Missing raw bytes"); + + throw new ApolloError.MissingKeyParameters(KeyProperties.rawKey); } } - throw new ApolloError.InvalidKeyType(keyType, Object.values(KeyTypes)); + throw new ApolloError.MissingKeyParameters(KeyProperties.rawKey); } /** @@ -329,23 +321,18 @@ export default class Apollo implements ApolloInterface, KeyRestoration { createPrivateKey(parameters: { [name: KeyProperties | string]: any; }): PrivateKey { - if (!parameters[KeyProperties.type]) { - throw new ApolloError.InvalidKeyType( - parameters[KeyProperties.type], - Object.values(KeyTypes) - ); + const keyType = parameters[KeyProperties.type]; + const keyCurve = parameters[KeyProperties.curve]; + + if (isEmpty(keyType)) { + throw new ApolloError.InvalidKeyType(keyType); } - if (!parameters[KeyProperties.curve]) { - throw new ApolloError.InvalidKeyCurve( - parameters[KeyProperties.curve], - Object.values(Curve) - ); + + if (isEmpty(keyCurve)) { + throw new ApolloError.InvalidKeyCurve(keyCurve); } - const keyType = parameters[KeyProperties.type]; - const { curve } = getKeyCurveByNameAndIndex( - parameters[KeyProperties.curve] - ); + const { curve } = getKeyCurveByNameAndIndex(parameters[KeyProperties.curve]); const keyData = parameters[KeyProperties.rawKey]; if (keyType === KeyTypes.EC) { @@ -356,14 +343,10 @@ export default class Apollo implements ApolloInterface, KeyRestoration { const seedHex = parameters[KeyProperties.seed]; if (notEmptyString(seedHex)) { - const derivationIndex = parameters[KeyProperties.index] ?? "0"; const derivationParam = parameters[KeyProperties.derivationPath]; const defaultPath: string = derivationParam ?? PrismDerivationPath.init(derivationIndex).toString(); - - const seed = Int8Array.from(Buffer.from(seedHex, "hex")); - const hdKey = ApolloSDK.derivation.EdHDKey.Companion.initFromSeed(seed); const baseKey = new Ed25519PrivateKey(Uint8Array.from(hdKey.privateKey)); @@ -375,12 +358,12 @@ export default class Apollo implements ApolloInterface, KeyRestoration { const privateKey = baseKey.derive(defaultPath); return privateKey; } + return baseKey; } const keyPair = Ed25519KeyPair.generateKeyPair(); return keyPair.privateKey; - } if (curve === Curve.SECP256K1) { @@ -389,11 +372,11 @@ export default class Apollo implements ApolloInterface, KeyRestoration { } const seedHex = parameters[KeyProperties.seed]; - if (!seedHex) { - throw new ApolloError.MissingKeyParameters(["seed"]); + if (isEmpty(seedHex)) { + throw new ApolloError.MissingKeyParameters(KeyProperties.seed); } - const seed = Buffer.from(seedHex, "hex"); + const seed = Buffer.from(seedHex, "hex"); const derivationIndex = parameters[KeyProperties.index] ?? "0"; const derivationParam = parameters[KeyProperties.derivationPath]; const defaultPath: string = derivationParam ?? PrismDerivationPath.init( @@ -407,11 +390,11 @@ export default class Apollo implements ApolloInterface, KeyRestoration { ); if (hdKey.privateKey == null) { - throw new ApolloError.MissingPrivateKey(); + throw new ApolloError.ApolloLibError("Key generated incorrectly: missing privateKey"); } if (hdKey.chainCode == null) { - throw new ApolloError.MissingChainCode(); + throw new ApolloError.ApolloLibError("Key generated incorrectly: missing chainCode"); } const baseKey = new Secp256k1PrivateKey(Uint8Array.from(hdKey.privateKey)); @@ -425,7 +408,6 @@ export default class Apollo implements ApolloInterface, KeyRestoration { } return baseKey; - } } @@ -454,12 +436,10 @@ export default class Apollo implements ApolloInterface, KeyRestoration { const keyPair = X25519KeyPair.generateKeyPair(); return keyPair.privateKey; - - } } - throw new ApolloError.InvalidKeyType(keyType, Object.values(KeyTypes)); + throw new ApolloError.InvalidKeyType(keyType); } restorePrivateKey(key: StorableKey): PrivateKey { diff --git a/src/apollo/utils/Ed25519PrivateKey.ts b/src/apollo/utils/Ed25519PrivateKey.ts index 3f4bd5bc1..02d322ab1 100644 --- a/src/apollo/utils/Ed25519PrivateKey.ts +++ b/src/apollo/utils/Ed25519PrivateKey.ts @@ -43,7 +43,7 @@ export class Ed25519PrivateKey extends PrivateKey implements DerivableKey, Expor derive(derivationPath: string): PrivateKey { const chainCodeHex = this.getProperty(KeyProperties.chainCode); if (!chainCodeHex) { - throw new ApolloError.MissingKeyParameters([KeyProperties.chainCode]); + throw new ApolloError.MissingKeyParameters(KeyProperties.chainCode); } const derivationPathStr = derivationPath.toString(); const skRaw = Int8Array.from(this.raw); diff --git a/src/apollo/utils/Secp256k1PrivateKey.ts b/src/apollo/utils/Secp256k1PrivateKey.ts index f2ca9e853..64a379ded 100644 --- a/src/apollo/utils/Secp256k1PrivateKey.ts +++ b/src/apollo/utils/Secp256k1PrivateKey.ts @@ -42,8 +42,9 @@ export class Secp256k1PrivateKey constructor(nativeValue: Uint8Array) { if (nativeValue.length !== ECConfig.PRIVATE_KEY_BYTE_SIZE) { - throw new ApolloError.ECPublicKeyInitialization(); + throw new ApolloError.KeyInitializationError(`Invalid byte size: ${ECConfig.PRIVATE_KEY_BYTE_SIZE} exptected, ${nativeValue.length} given`); } + super(); this.keySpecification.set(KeyProperties.curve, Curve.SECP256K1); @@ -54,7 +55,7 @@ export class Secp256k1PrivateKey derive(derivationPath: string): Secp256k1PrivateKey { const chainCodeHex = this.getProperty(KeyProperties.chainCode); if (!chainCodeHex) { - throw new ApolloError.MissingKeyParameters([KeyProperties.chainCode]); + throw new ApolloError.MissingKeyParameters(KeyProperties.chainCode); } const chaincode = Buffer.from(chainCodeHex, "hex"); const derivationPathStr = derivationPath.toString(); @@ -67,7 +68,7 @@ export class Secp256k1PrivateKey ); const derivedKey = hdKey.derive(derivationPathStr); if (derivedKey.privateKey == null) { - throw new ApolloError.MissingPrivateKey(); + throw new ApolloError.ApolloLibError("Key generated incorrectly: missing privateKey"); } const privateKey = new Secp256k1PrivateKey(Buffer.from(derivedKey.privateKey)); privateKey.keySpecification.set(KeyProperties.derivationPath, Buffer.from(derivationPathStr).toString("hex")); @@ -104,7 +105,7 @@ export class Secp256k1PrivateKey static secp256k1FromBytes(encoded: Uint8Array): Secp256k1PrivateKey { if (encoded.length !== ECConfig.PRIVATE_KEY_BYTE_SIZE) { - throw new ApolloError.ECPublicKeyInitialization(); + throw new ApolloError.KeyInitializationError(`Invalid byte size: ${ECConfig.PRIVATE_KEY_BYTE_SIZE} exptected, ${encoded.length} given`); } const bnprv = new BN(encoded); return new Secp256k1PrivateKey(Uint8Array.from(bnprv.toArray())); diff --git a/src/apollo/utils/Secp256k1PublicKey.ts b/src/apollo/utils/Secp256k1PublicKey.ts index 9bd95ee7e..b010a1c40 100644 --- a/src/apollo/utils/Secp256k1PublicKey.ts +++ b/src/apollo/utils/Secp256k1PublicKey.ts @@ -53,7 +53,7 @@ export class Secp256k1PublicKey extends PublicKey implements StorableKey, Export nativeValue.at(0) === 0x04; if (!isCompressed && !isUnCompressed) { - throw new ApolloError.ECPublicKeyInitialization(); + throw new ApolloError.KeyInitializationError(`Invalid key bytes`); } this.keySpecification.set(KeyProperties.curve, Curve.SECP256K1); this.keySpecification.set("compressed", isCompressed ? "true" : "false"); diff --git a/src/apollo/utils/derivation/DerivationPath.ts b/src/apollo/utils/derivation/DerivationPath.ts index 3dc39e605..66d42d5b4 100644 --- a/src/apollo/utils/derivation/DerivationPath.ts +++ b/src/apollo/utils/derivation/DerivationPath.ts @@ -10,7 +10,7 @@ export class DerivationPath { } get axes(): DerivationAxis[] { - return this.paths.map((path) => new DerivationAxis(path)) + return this.paths.map((path) => new DerivationAxis(path)); } get index() { @@ -18,13 +18,13 @@ export class DerivationPath { this.derivations, this.paths, (path) => path.index - ) + ); } at(index: number): number { const num = this.paths.at(index); if (num !== undefined) { - return num + return num; } throw new ApolloError.InvalidDerivationPath("DerivationPathErr Incompatible Derivation schema"); } @@ -34,7 +34,7 @@ export class DerivationPath { this.derivations, this.paths, (path) => path.schema - ) + ); } derive(axis: DerivationAxis): DerivationPath { @@ -56,7 +56,7 @@ export class DerivationPath { this.derivations, this.paths, (path) => `m/${path.axes.map((axis) => axis.toString()).join("/")}` - ) + ); } /** @@ -66,23 +66,20 @@ export class DerivationPath { * optionally a ' added after to mark hardened axis e.g. m/21/37'/0 */ static fromPath(path: string, derivations: DerivationClass[]): DerivationPath { - try { - if (typeof path === "string") { - const splitPath = path.split("/"); - if (splitPath.at(0)?.trim().toLowerCase() !== "m") { - throw new ApolloError.InvalidDerivationPath("Path needs to start with m or M"); - } - const paths = splitPath.slice(1).map(DerivationPath.parseAxis).map((a) => a.number); - return DerivationPath.callBackOrThrow( - derivations, - paths, - (path) => new DerivationPath(path.axes.map((a) => a.number), derivations) - ) + if (typeof path === "string") { + const splitPath = path.split("/"); + if (splitPath.at(0)?.trim().toLowerCase() !== "m") { + throw new ApolloError.InvalidDerivationPath("Path needs to start with m or M"); } - throw new ApolloError.InvalidDerivationPath(`Derivation path should be string`) - } catch (err) { - throw new ApolloError.InvalidDerivationPath(`DerivationPathErr ${(err as Error).message}`) + const paths = splitPath.slice(1).map(DerivationPath.parseAxis).map((a) => a.number); + return DerivationPath.callBackOrThrow( + derivations, + paths, + (path) => new DerivationPath(path.axes.map((a) => a.number), derivations) + ); } + throw new ApolloError.InvalidDerivationPath(`Derivation path should be string`); + } private static parseAxis(axis: string): DerivationAxis { @@ -104,7 +101,7 @@ export class DerivationPath { return path; } catch (err) { if (!(err instanceof ApolloError.InvalidDerivationPath)) { - throw err + throw err; } } } @@ -123,4 +120,4 @@ export class DerivationPath { throw new ApolloError.InvalidDerivationPath("DerivationPathErr Incompatible Derivation schema"); } -} \ No newline at end of file +} diff --git a/src/castor/did/prismDID/PrismDIDPublicKey.ts b/src/castor/did/prismDID/PrismDIDPublicKey.ts index 7c36b30cc..07e426634 100644 --- a/src/castor/did/prismDID/PrismDIDPublicKey.ts +++ b/src/castor/did/prismDID/PrismDIDPublicKey.ts @@ -89,7 +89,7 @@ export class PrismDIDPublicKey { this.fromEd25519ORX25519Proto(apollo, proto) ); } else { - throw new ApolloError.InvalidKeyCurve(curve, Object.values(Curve)) + throw new ApolloError.InvalidKeyCurve(curve); } } diff --git a/src/domain/models/errors/Apollo.ts b/src/domain/models/errors/Apollo.ts index a1e66b5d3..26b7b9ccf 100644 --- a/src/domain/models/errors/Apollo.ts +++ b/src/domain/models/errors/Apollo.ts @@ -1,86 +1,105 @@ -import { SupportedHashingAlg } from "../../utils/hash"; -import { StorableKey } from "../keyManagement"; +import { SDKError } from "./Common"; +import { KeyTypes, StorableKey } from "../keyManagement"; +import { asArray } from "../../../utils"; +import { Curve } from "../KeyCurve"; -export class InvalidMnemonicWord extends Error { - constructor(message?: string) { - super(message || "Invalid mnemonic word"); +/** + * thrown when at least one Mnemonic word does not match in the wordlist + */ +export class MnemonicWordError extends SDKError { + constructor(words?: string[]) { + super(11, `Invalid mnemonic word(s) [${asArray(words).join(", ")}]`); } } -export class CouldNotParseMessageString extends Error { - constructor(message?: string) { - super(message || "Could not parse message string"); - } +/** + * thrown when the number of Mnemonic words is different to expected + */ +export class MnemonicLengthError extends SDKError { + constructor() { super(112, "Mnemonics must be 12 or 24 words in length"); } } -export class InvalidPrivateKey extends Error { - constructor(message?: string) { - super(message || "Invalid private key"); - } +/** + * // ?? + */ +export class CouldNotParseMessageString extends SDKError { + constructor() { super(12, "Could not parse message string"); } } -export class InvalidHashingAlgorithm extends Error { - constructor(message?: string) { - const supported = Object.keys(Object.fromEntries(Object.entries(SupportedHashingAlg))) - super(message || `Invalid Hashing Algorithm, supported ${supported.join(", ")}`); - } -} +/** + * thrown when restoring a key from a JWK + */ +// export class InvalidJWK extends SDKError { +// constructor() { super(13, "Invalid JWK") } +// } +/** + * not thrown + * swift throws in X25519PublicKey.verify() + */ +// export class KeyAgreementDoesNotSupportVerification extends SDKError { +// constructor() { super(14, "Invalid JWK") } +// } -export class InvalidKeyCurve extends Error { - constructor(invalidKeyCurve: string, validKeyCurves: string[]) { - super( - `Invalid key curve: ${invalidKeyCurve ? invalidKeyCurve : "undefined" - }. Valid options are: ${validKeyCurves.join(",")}` - ); - } -} - -export class InvalidDerivationPath extends Error { - constructor(message?: string) { - super(message || "Invalid derivation path"); +/** + * thrown when Key recovery fails during restoration attempt + */ +export class KeyRestoratonFailed extends SDKError { + constructor(key?: StorableKey) { + super(15, `Key Restoration Failed: recoveryId [${key?.recoveryId}] not matched or invalid`); } } - -export class ECPublicKeyInitialization extends Error { - constructor() { - super( - "ECPoint corresponding to a public key doesn't belong to Secp256k1 curve" - ); +/** + * thrown when given Key Curve is not supported + */ +export class InvalidKeyCurve extends SDKError { + constructor(keyCurve?: string) { + const options = Object.values(Curve); + const msg = `Invalid key curve: ${keyCurve ?? "undefined"}. Valid options are: ${options.join(", ")}`; + super(16, msg); } } -export class InvalidKeyType extends Error { - constructor(invalidKeyType: string, validKeyTypes: string[]) { - super( - `Invalid key type: ${invalidKeyType ? invalidKeyType : "undefined" - }. Valid options are: ${validKeyTypes.join(",")}` - ); +/** + * thrown when give Key Type is not supported + */ +export class InvalidKeyType extends SDKError { + constructor(keyType?: string) { + const options = Object.values(KeyTypes); + const msg = `Invalid key type: ${keyType ?? "undefined"}. Valid options are: ${options.join(", ")}`; + super(17, msg); } } -export class MissingKeyParameters extends Error { - constructor(missing: string[]) { - super(`Missing key parameters: ${missing.join(",")}`); +/** + * thrown when expected parameter is missing for Key operation + */ +export class MissingKeyParameters extends SDKError { + constructor(...missing: string[]) { + super(18, `Missing key parameters: ${missing.join(", ")}`); } } -export class KeyRestoratonFailed extends Error { - constructor(key?: StorableKey) { - super(`Key Restoration Failed: [${key?.recoveryId}]`); - } +/** + * thrown when failing to create a key + */ +export class KeyInitializationError extends SDKError { + constructor(message: string) { super(181, message); } } -export class MissingPrivateKey extends Error { - constructor(message?: string) { - super(message || "Private key is missing"); +/** + * thrown when failing to create a DerivationPath + */ +export class InvalidDerivationPath extends SDKError { + constructor(message: string) { + super(182, message); } } -export class MissingChainCode extends Error { - constructor(message?: string) { - super(message || "Chain code is missing"); - } +/** + * thrown when Apollo library returns unexpected result + */ +export class ApolloLibError extends SDKError { + constructor(message: string) { super(199, message); } } - diff --git a/src/domain/models/errors/Common.ts b/src/domain/models/errors/Common.ts index e99e59edd..b8966d939 100644 --- a/src/domain/models/errors/Common.ts +++ b/src/domain/models/errors/Common.ts @@ -1,6 +1,10 @@ - -export class SomethingWentWrongError extends Error { - constructor(message?: string) { - super(message); +export class SDKError extends Error { + constructor(code: number, message: string) { + super(`${code}: ${message}`); + this.name = this.constructor.name; } } + +export class UnknownError extends SDKError { + constructor() { super(-1, "Something went wrong"); } +} diff --git a/src/domain/models/errors/Mnemonic.ts b/src/domain/models/errors/Mnemonic.ts deleted file mode 100644 index e38a20428..000000000 --- a/src/domain/models/errors/Mnemonic.ts +++ /dev/null @@ -1,23 +0,0 @@ -export class MnemonicException extends Error { - constructor(message?: string) { - super(message || "Mnemonic exception occurred"); - } -} - -export class MnemonicLengthException extends Error { - constructor(message?: string) { - super(message || "Mnemonic length exception occurred"); - } -} - -export class MnemonicWordException extends Error { - constructor(message?: string) { - super(message || "Mnemonic word exception occurred"); - } -} - -export class MnemonicChecksumException extends Error { - constructor(message?: string) { - super(message || "Mnemonic checksum exception occurred"); - } -} diff --git a/src/domain/models/errors/Pollux.ts b/src/domain/models/errors/Pollux.ts index b0a1e337d..17ad0509c 100644 --- a/src/domain/models/errors/Pollux.ts +++ b/src/domain/models/errors/Pollux.ts @@ -80,4 +80,9 @@ export class InvalidDescriptorFormatError extends Error { constructor(message?: string) { super(message || "Invalid Descriptor format") } -} \ No newline at end of file +} + +/** + * general Revocation error, message should contain details + */ +export class RevocationError extends Error {} diff --git a/src/domain/models/keyManagement/Key.ts b/src/domain/models/keyManagement/Key.ts index f6be6eadc..6944ce7eb 100644 --- a/src/domain/models/keyManagement/Key.ts +++ b/src/domain/models/keyManagement/Key.ts @@ -144,7 +144,7 @@ export function getKeyCurveByNameAndIndex( case Curve.SECP256K1: return { curve: Curve.SECP256K1, index }; default: - throw new ApolloError.InvalidKeyCurve(name, Object.keys(Curve)); + throw new ApolloError.InvalidKeyCurve(name); } } diff --git a/src/domain/utils/hash.ts b/src/domain/utils/hash.ts index b82f38794..be712ddfb 100644 --- a/src/domain/utils/hash.ts +++ b/src/domain/utils/hash.ts @@ -1,43 +1,26 @@ import { sha512, sha256 } from "hash.js"; -import { ApolloError } from "../../domain"; -export enum SupportedHashingAlg { - SHA256 = 'SHA256', - SHA512 = 'SHA512' +enum Alg { + SHA256 = 'SHA256', + SHA512 = 'SHA512' } -function isSupported(alg: string): boolean { - if (alg === SupportedHashingAlg.SHA256) { - return true; - } - if (alg === SupportedHashingAlg.SHA512) { - return true; - } - return true; +class InvalidHashingAlgorithm extends Error { + constructor() { + super(`Invalid Hashing Algorithm. Valid options are: ${Alg.SHA256}, ${Alg.SHA512}`); + } } -export async function hash(data: string | Uint8Array, alg: string) { - if (!isSupported(alg)) { - throw new ApolloError.InvalidHashingAlgorithm() - } - if (alg === SupportedHashingAlg.SHA256) { - return Uint8Array.from(sha256().update(data).digest()); - } - if (alg === SupportedHashingAlg.SHA512) { - return Uint8Array.from(sha512().update(data).digest()); - } - throw new ApolloError.InvalidHashingAlgorithm() -} +export const hashSync = (data: string | Uint8Array, alg: string) => { + if (alg === Alg.SHA256) { + return Uint8Array.from(sha256().update(data).digest()); + } -export function hashSync(data: string, alg: string) { - if (!isSupported(alg)) { - throw new ApolloError.InvalidHashingAlgorithm() - } - if (alg === SupportedHashingAlg.SHA256) { - return Uint8Array.from(sha256().update(data).digest()); - } - if (alg === SupportedHashingAlg.SHA512) { - return Uint8Array.from(sha512().update(data).digest()); - } - throw new ApolloError.InvalidHashingAlgorithm() -} + if (alg === Alg.SHA512) { + return Uint8Array.from(sha512().update(data).digest()); + } + + throw new InvalidHashingAlgorithm(); +}; + +export const hash = async (data: string | Uint8Array, alg: string) => hashSync(data, alg); diff --git a/src/pollux/Pollux.ts b/src/pollux/Pollux.ts index b6f338ca7..6021ab75a 100644 --- a/src/pollux/Pollux.ts +++ b/src/pollux/Pollux.ts @@ -39,7 +39,6 @@ import { JWTRevocationStatus, RevocationType, JWTStatusListResponse, - ApolloError, Curve, KeyProperties, KeyTypes, @@ -239,10 +238,10 @@ export default class Pollux implements IPollux { const curve = decodedVerificationMethod.publicKeyJwk.crv; const kty = decodedVerificationMethod.publicKeyJwk.kty; if (kty !== KeyTypes.EC) { - throw new ApolloError.InvalidKeyType(kty, Object.values(KeyTypes)) + throw new PolluxError.RevocationError(`Invalid JWK kty: ${kty}, should be ${KeyTypes.EC}`); } if (curve !== Curve.SECP256K1.toLocaleLowerCase()) { - throw new ApolloError.InvalidKeyCurve(curve, Object.values(Curve)) + throw new PolluxError.RevocationError(`Invalid JWK crv: ${curve}, should be ${Curve.SECP256K1.toLocaleLowerCase()}`); } const { x, y } = decodedVerificationMethod.publicKeyJwk; const pk = this.apollo.createPublicKey({ diff --git a/tests/apollo/Apollo.test.ts b/tests/apollo/Apollo.test.ts index 01e9e7121..635e1fa45 100644 --- a/tests/apollo/Apollo.test.ts +++ b/tests/apollo/Apollo.test.ts @@ -12,7 +12,6 @@ import { X25519PrivateKey } from "../../src/apollo/utils/X25519PrivateKey"; import { Ed25519PublicKey } from "../../src/apollo/utils/Ed25519PublicKey"; import { X25519PublicKey } from "../../src/apollo/utils/X25519PublicKey"; import { Secp256k1PublicKey } from "../../src/apollo/utils/Secp256k1PublicKey"; -import { MnemonicLengthException, MnemonicWordException } from "../../src/domain/models/errors/Mnemonic"; import { ApolloError, Curve, @@ -29,7 +28,7 @@ import { DeprecatedDerivationPath } from "../../src/domain/models/derivation/sch import { DerivationAxis } from "../../src/domain/models/derivation/DerivationAxis"; import ApolloPKG from "@hyperledger/identus-apollo"; import { normaliseDER } from "../../src/domain/utils/DER"; -import { hash, hashSync, SupportedHashingAlg } from '../../src/domain/utils/hash'; +import { hash, hashSync } from '../../src/domain/utils/hash'; import { randomBytes } from "../../src/domain/utils/randomBytes"; const ApolloSDK = ApolloPKG.org.hyperledger.identus.apollo; @@ -112,7 +111,7 @@ describe("Apollo", () => { assert.throws( () => apollo.createSeed(mnemonics as any, ""), - MnemonicLengthException + ApolloError.MnemonicLengthError ); }); } @@ -123,8 +122,7 @@ describe("Apollo", () => { () => { apollo.createSeed(mnemonicCode, ""); }, - Error, - "Invalid mnemonic word/s" + ApolloError.MnemonicWordError ); }); @@ -153,7 +151,7 @@ describe("Apollo", () => { ] as MnemonicWordList; assert.throws(() => { apollo.createSeed(mnemonicCode, ""); - }, MnemonicWordException); + }, ApolloError.MnemonicWordError); }); }); @@ -207,7 +205,7 @@ describe("Apollo", () => { it("Should test our hashing libraries", async () => { const text = "test"; - const validHashing = [SupportedHashingAlg.SHA256, SupportedHashingAlg.SHA512]; + const validHashing = ["SHA256", "SHA512"]; validHashing.forEach((alg) => { expect(() => hashSync(text, alg)).to.not.be.undefined; expect(hash(text, alg)).to.eventually.not.be.undefined; @@ -391,18 +389,18 @@ describe("Apollo", () => { expect(() => DerivationAxis.hardened(-1)).to.throws("Number corresponding to the axis should be a positive number"); }); it("Should throw an error when invalid path is used", async () => { - expect(() => DerivationPath.fromPath("m/x", [DeprecatedDerivationPath, PrismDerivationPath])).to.throws("DerivationPathErr Invalid axis, not a number"); + expect(() => DerivationPath.fromPath("m/x", [DeprecatedDerivationPath, PrismDerivationPath])).to.throws("182: Invalid axis, not a number"); }); it("Should throw an error when invalid (non string) path is used", async () => { - expect(() => DerivationPath.fromPath(null as any, [DeprecatedDerivationPath, PrismDerivationPath])).to.throws("DerivationPathErr Derivation path should be string"); + expect(() => DerivationPath.fromPath(null as any, [DeprecatedDerivationPath, PrismDerivationPath])).to.throws("182: Derivation path should be string"); }); it("Should throw an error when empty derivation schema is used", async () => { const path = DerivationPath.empty([DeprecatedDerivationPath, PrismDerivationPath]); expect(() => path.toString()).to.throws("DerivationPathErr Derivation path is empty"); }); it("Should throw an error when wrong path not starting with m or M", async () => { - expect(() => DerivationPath.fromPath("d/0", [DeprecatedDerivationPath, PrismDerivationPath]).toString()).to.throws("DerivationPathErr Path needs to start with m or M"); + expect(() => DerivationPath.fromPath("d/0", [DeprecatedDerivationPath, PrismDerivationPath]).toString()).to.throws("182: Path needs to start with m or M"); }); it("Should throw an error when invalid derivation schema is used", async () => { const path = DerivationPath.empty([DeprecatedDerivationPath, PrismDerivationPath]); diff --git a/tests/castor/PrismDID.test.ts b/tests/castor/PrismDID.test.ts index 5794832d4..f1c639eff 100644 --- a/tests/castor/PrismDID.test.ts +++ b/tests/castor/PrismDID.test.ts @@ -78,8 +78,7 @@ describe("PrismDID", () => { ); const masterPkProto = masterPk.toProto(); - expect(() => PrismDIDPublicKey.fromProto(apollo, masterPkProto)).to.throw(`Invalid key curve: ${unsupportedCurve}. Valid options are: X25519,Ed25519,Secp256k1`); - + expect(() => PrismDIDPublicKey.fromProto(apollo, masterPkProto)).to.throw(`16: Invalid key curve: ${unsupportedCurve}. Valid options are: X25519, Ed25519, Secp256k1`); }); }); diff --git a/tests/pollux/Pollux.revocation.test.ts b/tests/pollux/Pollux.revocation.test.ts index 061a33a27..e6fdb43b8 100644 --- a/tests/pollux/Pollux.revocation.test.ts +++ b/tests/pollux/Pollux.revocation.test.ts @@ -298,7 +298,7 @@ describe("Pollux", () => { ); await expect(pollux.isCredentialRevoked(JWTCredential.fromJWS(revocableJWTCredential))) - .to.eventually.rejectedWith("Err Invalid key type: undefined. Valid options are: EC,Curve25519,unknown") + .to.eventually.rejectedWith("Err Invalid JWK kty: undefined, should be EC") }) @@ -333,7 +333,7 @@ describe("Pollux", () => { ); await expect(pollux.isCredentialRevoked(JWTCredential.fromJWS(revocableJWTCredential))) - .to.eventually.rejectedWith("Err Invalid key curve: undefined. Valid options are: X25519,Ed25519,Secp256k1") + .to.eventually.rejectedWith("Err Invalid JWK crv: undefined, should be secp256k1") })