Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: errors introducing error codes and refactoring Apollo errors #265

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 39 additions & 59 deletions src/apollo/Apollo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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";

Expand Down Expand Up @@ -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}`);
Expand Down Expand Up @@ -215,45 +209,42 @@ 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) {
if (curve === Curve.ED25519) {
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);
}
}

Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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) {
Expand All @@ -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));

Expand All @@ -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) {
Expand All @@ -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(
Expand All @@ -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));
Expand All @@ -425,7 +408,6 @@ export default class Apollo implements ApolloInterface, KeyRestoration {
}

return baseKey;

}
}

Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/apollo/utils/Ed25519PrivateKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 5 additions & 4 deletions src/apollo/utils/Secp256k1PrivateKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
Expand All @@ -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"));
Expand Down Expand Up @@ -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()));
Expand Down
2 changes: 1 addition & 1 deletion src/apollo/utils/Secp256k1PublicKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
41 changes: 19 additions & 22 deletions src/apollo/utils/derivation/DerivationPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ export class DerivationPath {
}

get axes(): DerivationAxis[] {
return this.paths.map((path) => new DerivationAxis(path))
return this.paths.map((path) => new DerivationAxis(path));
}

get index() {
return DerivationPath.callBackOrThrow(
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");
}
Expand All @@ -34,7 +34,7 @@ export class DerivationPath {
this.derivations,
this.paths,
(path) => path.schema
)
);
}

derive(axis: DerivationAxis): DerivationPath {
Expand All @@ -56,7 +56,7 @@ export class DerivationPath {
this.derivations,
this.paths,
(path) => `m/${path.axes.map((axis) => axis.toString()).join("/")}`
)
);
}

/**
Expand All @@ -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 {
Expand All @@ -104,7 +101,7 @@ export class DerivationPath {
return path;
} catch (err) {
if (!(err instanceof ApolloError.InvalidDerivationPath)) {
throw err
throw err;
}
}
}
Expand All @@ -123,4 +120,4 @@ export class DerivationPath {
throw new ApolloError.InvalidDerivationPath("DerivationPathErr Incompatible Derivation schema");
}

}
}
2 changes: 1 addition & 1 deletion src/castor/did/prismDID/PrismDIDPublicKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
Loading
Loading