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: Shared lib directory #30

Open
wants to merge 5 commits into
base: feature/improve-key-creation-flow
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Try our demo at [kms-demo.othent.io](https://kms-demo.othent.io)!

<br />

[![Othent KMS JS SDK NPM page](https://img.shields.io/npm/v/%40othent%2Fkms?style=for-the-badge&color=%23CC3534)](https://www.npmjs.com/package/@othent/kms) [![Othent KMS Server Statements Coverage](https://img.shields.io/badge/Stmts_Coverage-81.66%25-black?style=for-the-badge&color=%23008000)](https://www.npmjs.com/package/@othent/kms)
[![Othent KMS JS SDK NPM page](https://img.shields.io/npm/v/%40othent%2Fkms?style=for-the-badge&color=%23CC3534)](https://www.npmjs.com/package/@othent/kms) [![Othent KMS Server Statements Coverage](https://img.shields.io/badge/Stmts_Coverage-81.71%25-black?style=for-the-badge&color=%23008000)](https://www.npmjs.com/package/@othent/kms)


<br />
Expand Down
23 changes: 13 additions & 10 deletions coverage/coverage-final.json

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions coverage/coverage-summary.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{"total": {"lines":{"total":750,"covered":621,"skipped":0,"pct":82.8},"statements":{"total":769,"covered":628,"skipped":0,"pct":81.66},"functions":{"total":105,"covered":81,"skipped":0,"pct":77.14},"branches":{"total":445,"covered":246,"skipped":0,"pct":55.28},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/operations/common.types.ts": {"lines":{"total":16,"covered":16,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":16,"covered":16,"skipped":0,"pct":100},"branches":{"total":11,"covered":10,"skipped":0,"pct":90.9}}
{"total": {"lines":{"total":761,"covered":631,"skipped":0,"pct":82.91},"statements":{"total":782,"covered":639,"skipped":0,"pct":81.71},"functions":{"total":102,"covered":80,"skipped":0,"pct":78.43},"branches":{"total":452,"covered":255,"skipped":0,"pct":56.41},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/operations/common.types.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/operations/common.validation.ts": {"lines":{"total":12,"covered":12,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":12,"covered":12,"skipped":0,"pct":100},"branches":{"total":4,"covered":4,"skipped":0,"pct":100}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/operations/activate-keys/activate-keys.ts": {"lines":{"total":20,"covered":20,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":20,"covered":20,"skipped":0,"pct":100},"branches":{"total":17,"covered":9,"skipped":0,"pct":52.94}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/operations/create-user/create-user.handler.ts": {"lines":{"total":15,"covered":15,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":15,"covered":15,"skipped":0,"pct":100},"branches":{"total":6,"covered":6,"skipped":0,"pct":100}}
Expand All @@ -19,11 +19,14 @@
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/server/config/config.utils.ts": {"lines":{"total":136,"covered":131,"skipped":0,"pct":96.32},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":137,"covered":132,"skipped":0,"pct":96.35},"branches":{"total":152,"covered":96,"skipped":0,"pct":63.15}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/server/errors/error.ts": {"lines":{"total":33,"covered":21,"skipped":0,"pct":63.63},"functions":{"total":4,"covered":2,"skipped":0,"pct":50},"statements":{"total":34,"covered":21,"skipped":0,"pct":61.76},"branches":{"total":23,"covered":8,"skipped":0,"pct":34.78}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/server/errors/errors.utils.ts": {"lines":{"total":12,"covered":6,"skipped":0,"pct":50},"functions":{"total":2,"covered":1,"skipped":0,"pct":50},"statements":{"total":12,"covered":6,"skipped":0,"pct":50},"branches":{"total":5,"covered":1,"skipped":0,"pct":20}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/arweave/arweaveUtils.ts": {"lines":{"total":34,"covered":22,"skipped":0,"pct":64.7},"functions":{"total":14,"covered":7,"skipped":0,"pct":50},"statements":{"total":34,"covered":22,"skipped":0,"pct":64.7},"branches":{"total":13,"covered":2,"skipped":0,"pct":15.38}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/auth/auth0.utils.ts": {"lines":{"total":47,"covered":12,"skipped":0,"pct":25.53},"functions":{"total":5,"covered":0,"skipped":0,"pct":0},"statements":{"total":48,"covered":12,"skipped":0,"pct":25},"branches":{"total":15,"covered":0,"skipped":0,"pct":0}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/kms/google-kms.utils.ts": {"lines":{"total":33,"covered":33,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":34,"covered":34,"skipped":0,"pct":100},"branches":{"total":13,"covered":11,"skipped":0,"pct":84.61}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/kms/kmsClient.ts": {"lines":{"total":27,"covered":11,"skipped":0,"pct":40.74},"functions":{"total":2,"covered":0,"skipped":0,"pct":0},"statements":{"total":28,"covered":11,"skipped":0,"pct":39.28},"branches":{"total":11,"covered":4,"skipped":0,"pct":36.36}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/kms/localKeyManagementServiceClient.ts": {"lines":{"total":90,"covered":80,"skipped":0,"pct":88.88},"functions":{"total":20,"covered":18,"skipped":0,"pct":90},"statements":{"total":90,"covered":80,"skipped":0,"pct":88.88},"branches":{"total":100,"covered":49,"skipped":0,"pct":49}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/lib/address/address.utils.ts": {"lines":{"total":4,"covered":3,"skipped":0,"pct":75},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":4,"covered":3,"skipped":0,"pct":75},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/lib/binary-data-types/binary-data-types.utils.ts": {"lines":{"total":35,"covered":27,"skipped":0,"pct":77.14},"functions":{"total":8,"covered":7,"skipped":0,"pct":87.5},"statements":{"total":36,"covered":28,"skipped":0,"pct":77.77},"branches":{"total":18,"covered":10,"skipped":0,"pct":55.55}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/lib/hash/hash.utils.ts": {"lines":{"total":3,"covered":1,"skipped":0,"pct":33.33},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":3,"covered":1,"skipped":0,"pct":33.33},"branches":{"total":1,"covered":0,"skipped":0,"pct":0}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/lib/legacy-serialized-buffers/legacy-serialized-buffer.utils.ts": {"lines":{"total":16,"covered":14,"skipped":0,"pct":87.5},"functions":{"total":5,"covered":3,"skipped":0,"pct":60},"statements":{"total":17,"covered":14,"skipped":0,"pct":82.35},"branches":{"total":12,"covered":11,"skipped":0,"pct":91.66}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/log/log.utils.ts": {"lines":{"total":23,"covered":14,"skipped":0,"pct":60.86},"functions":{"total":5,"covered":3,"skipped":0,"pct":60},"statements":{"total":29,"covered":17,"skipped":0,"pct":58.62},"branches":{"total":26,"covered":9,"skipped":0,"pct":34.61}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/slack/slack.utils.ts": {"lines":{"total":25,"covered":7,"skipped":0,"pct":28},"functions":{"total":2,"covered":1,"skipped":0,"pct":50},"statements":{"total":27,"covered":8,"skipped":0,"pct":29.62},"branches":{"total":5,"covered":1,"skipped":0,"pct":20}}
,"/home/gmzcodes/projects/clabs/KMS-server-new/src/lib/utils/tools/delay.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":2,"covered":0,"skipped":0,"pct":0},"statements":{"total":4,"covered":2,"skipped":0,"pct":50},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}}
Expand Down
63 changes: 2 additions & 61 deletions src/lib/operations/common.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Route } from "../server/server.constants";
import { B64String, b64ToUint8Array, B64UrlString, stringToUint8Array } from "../utils/arweave/arweaveUtils";
import { B64String, B64UrlString } from "../utils/lib/binary-data-types/binary-data-types.types";
import { LegacyBufferObject, LegacyBufferRecord } from "../utils/lib/legacy-serialized-buffers/legacy-serialized-buffer.types";

export interface BaseOperationIdTokenData<P extends Route> {
path: P;
Expand All @@ -12,66 +13,6 @@ export interface LegacyBaseOperationIdTokenData {
keyName: string;
}

/**
* @deprecated
*/
export type LegacyBufferRecord = Record<number, number>;

/**
* @deprecated
*/
export interface LegacyBufferObject {
type: "Buffer";
data: number[];
}

// TODO: Move to bufferUtils...

/**
* JSON-compatible representation of a Buffer.
* @deprecated This type will soon be removed and the code will be updated to work exclusively with native binary data types (e.g. `Uint8Array`).
*/
export type LegacyBufferData = LegacyBufferRecord | LegacyBufferObject;

export function isLegacyBufferObject(
legacyBufferData: LegacyBufferData,
): legacyBufferData is LegacyBufferObject {
return (
!!legacyBufferData &&
typeof legacyBufferData === "object" &&
(legacyBufferData as LegacyBufferObject).type === "Buffer" &&
Array.isArray((legacyBufferData as LegacyBufferObject).data)
);
}

export function normalizeBufferData(
data: LegacyBufferRecord | LegacyBufferObject | string | B64String | B64UrlString,
treatStringsAsB64 = false,
): Uint8Array {
if (typeof data === "string") {
return treatStringsAsB64
? b64ToUint8Array(data as B64String | B64UrlString)
: stringToUint8Array(data);
}

if (isLegacyBufferObject(data)) {
return new Uint8Array(data.data);
}

return new Uint8Array(Object.values(data));
}

export function toLegacyBufferObject(buffer: Uint8Array): LegacyBufferObject {
return {
type: "Buffer",
data: Array.from(buffer),
}
}

export function normalizeKMSResponseData(str: string | Uint8Array): Uint8Array {
return typeof str === 'string' ? stringToUint8Array(str) : new Uint8Array(str);
}

export type LegacyTokenDataFormat = "LegacyBufferObject" | "LegacyBufferRecord" | "string";

export const LEGACY_TOKEN_DATA_FORMATS = ["LegacyBufferObject", "LegacyBufferRecord", "string"] as const satisfies LegacyTokenDataFormat[];
Expand Down
2 changes: 1 addition & 1 deletion src/lib/operations/create-user/create-user.handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { createUserHandlerFactory, CreateUserIdTokenData, CreateUserResponseData
import httpMocks from "node-mocks-http";
import { ExpressRequestWithToken, UserMetadata } from '../../utils/auth/auth0.types';
import { Route } from '../../server/server.constants';
import { B64UrlString } from '../../utils/arweave/arweaveUtils';
import * as auth0Utils from "../../utils/auth/auth0.utils";
import { CONFIG } from '../../server/config/config.utils';
import * as activateKeysModule from "../activate-keys/activate-keys";
import * as delayModule from "../../utils/tools/delay";
import { B64UrlString } from '../../utils/lib/binary-data-types/binary-data-types.types';

describe('create user handler', () => {
const createUserHandler = createUserHandlerFactory();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/operations/create-user/create-user.utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {describe, expect, test} from '@jest/globals';
import { CreateUserIdTokenData } from './create-user.handler';
import { IdTokenWithData } from '../../utils/auth/auth0.types';
import { B64UrlString } from '../../utils/arweave/arweaveUtils';
import { kmsClient } from "../../utils/kms/kmsClient";
import { createKeyRing, createSignKey, createEncryptDecryptKey, createImportJob } from './create-user.utils';
import { B64UrlString } from '../../utils/lib/binary-data-types/binary-data-types.types';

describe('create user utils', () => {

Expand Down
23 changes: 13 additions & 10 deletions src/lib/operations/decrypt/decrypt.handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { decryptHandlerFactory, DecryptIdTokenData, DecryptResponseData, LegacyD
import httpMocks from "node-mocks-http";
import { ExpressRequestWithToken } from '../../utils/auth/auth0.types';
import { Route } from '../../server/server.constants';
import { B64String, B64UrlString, binaryDataTypeToString, stringToUint8Array, uint8ArrayTob64, uint8ArrayTob64Url } from '../../utils/arweave/arweaveUtils';
import { EMPTY_VALUES, LEGACY_TOKEN_DATA_FORMATS, LegacyBufferObject, LegacyBufferRecord, LegacyTokenDataFormat, normalizeBufferData, TOKEN_DATA_FORMATS, TokenDataFormat } from '../common.types';
import { EMPTY_VALUES, LEGACY_TOKEN_DATA_FORMATS, LegacyTokenDataFormat, TOKEN_DATA_FORMATS, TokenDataFormat } from '../common.types';
import { encrypt } from '../encrypt/encrypt';
import { LegacyBufferObject, LegacyBufferRecord } from '../../utils/lib/legacy-serialized-buffers/legacy-serialized-buffer.types';
import { normalizeLegacyBufferDataOrB64 } from '../../utils/lib/legacy-serialized-buffers/legacy-serialized-buffer.utils';
import { B64String, B64UrlString } from '../../utils/lib/binary-data-types/binary-data-types.types';
import { B64, B64Url, BDT, UI8A } from '../../utils/lib/binary-data-types/binary-data-types.utils';

describe('decrypt handler', () => {
const decryptHandler = decryptHandlerFactory();
Expand Down Expand Up @@ -55,9 +58,9 @@ describe('decrypt handler', () => {
let ciphertext: B64String | B64UrlString = "" as B64String;

if (format === "B64String") {
ciphertext = uint8ArrayTob64(ENCRYPTED_SECRET_BUFFER);
ciphertext = B64.from(ENCRYPTED_SECRET_BUFFER);
} else if (format === "B64UrlString") {
ciphertext = uint8ArrayTob64Url(ENCRYPTED_SECRET_BUFFER);
ciphertext = B64Url.from(ENCRYPTED_SECRET_BUFFER);
}

return {
Expand All @@ -67,7 +70,7 @@ describe('decrypt handler', () => {
};

beforeAll(async () => {
const encryptedSecretBuffer = await encrypt({ sub: "<SUB>" } as any, stringToUint8Array(SECRET));
const encryptedSecretBuffer = await encrypt({ sub: "<SUB>" } as any, UI8A.from(SECRET, "string"));

ENCRYPTED_SECRET_BUFFER = encryptedSecretBuffer;
});
Expand Down Expand Up @@ -110,8 +113,8 @@ describe('decrypt handler', () => {
}),
);

const resultDataBuffer = normalizeBufferData(data);
const decryptedText = binaryDataTypeToString(resultDataBuffer);
const resultDataBuffer = normalizeLegacyBufferDataOrB64(data);
const decryptedText = BDT.decode(resultDataBuffer);

expect(decryptedText).toEqual(SECRET);
});
Expand Down Expand Up @@ -155,8 +158,8 @@ describe('decrypt handler', () => {

expect(data).toMatch(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/);

const resultDataBuffer = normalizeBufferData(data, true);
const decryptedText = binaryDataTypeToString(resultDataBuffer);
const resultDataBuffer = normalizeLegacyBufferDataOrB64(data, true);
const decryptedText = BDT.decode(resultDataBuffer);

expect(decryptedText).toEqual(SECRET);
});
Expand All @@ -167,7 +170,7 @@ describe('decrypt handler', () => {
await expect(callDecryptHandlerWithToken({
keyName: "<KEYNAME>",
path: Route.DECRYPT,
ciphertext: uint8ArrayTob64(ENCRYPTED_SECRET_BUFFER),
ciphertext: B64.from(ENCRYPTED_SECRET_BUFFER),
})).rejects.toThrow("Invalid token data for decrypt()");
});

Expand Down
11 changes: 7 additions & 4 deletions src/lib/operations/decrypt/decrypt.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { decrypt } from "./decrypt";
import { ExpressRequestWithToken } from "../../utils/auth/auth0.types";
import { Route } from "../../server/server.constants";
import { logRequestSuccess, logRequestStart } from "../../utils/log/log.utils";
import { BaseOperationIdTokenData, LegacyBaseOperationIdTokenData, LegacyBufferData, LegacyBufferObject, normalizeBufferData, toLegacyBufferObject } from "../common.types";
import { BaseOperationIdTokenData, LegacyBaseOperationIdTokenData } from "../common.types";
import { validateDecryptIdTokenOrThrow } from "./decrypt.validation";
import { B64String, B64UrlString, uint8ArrayTob64 } from "../../utils/arweave/arweaveUtils";
import { LegacyBufferData, LegacyBufferObject } from "../../utils/lib/legacy-serialized-buffers/legacy-serialized-buffer.types";
import { B64String, B64UrlString } from "../../utils/lib/binary-data-types/binary-data-types.types";
import { normalizeLegacyBufferDataOrB64, toLegacyBufferObject } from "../../utils/lib/legacy-serialized-buffers/legacy-serialized-buffer.utils";
import { B64 } from "../../utils/lib/binary-data-types/binary-data-types.utils";

/**
* @deprecated
Expand Down Expand Up @@ -41,15 +44,15 @@ export function decryptHandlerFactory() {
const isLegacyData = !data.hasOwnProperty("path");
const treatStringAsB64 = !isLegacyData;

const ciphertextBuffer = normalizeBufferData(data.ciphertext, treatStringAsB64);
const ciphertextBuffer = normalizeLegacyBufferDataOrB64(data.ciphertext, treatStringAsB64);
const plaintext = await decrypt(idToken, ciphertextBuffer);

logRequestSuccess(Route.DECRYPT, idToken);

res.send(
isLegacyData
? { data: toLegacyBufferObject(plaintext) } satisfies LegacyDecryptResponseData
: { decryptedData: uint8ArrayTob64(plaintext) } satisfies DecryptResponseData
: { decryptedData: B64.from(plaintext) } satisfies DecryptResponseData
);
};
}
4 changes: 2 additions & 2 deletions src/lib/operations/decrypt/decrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { IdTokenWithData } from "../../utils/auth/auth0.types";
import { kmsClient } from "../../utils/kms/kmsClient";
import { getEncryptDecryptKeyPath } from "../../utils/kms/google-kms.utils";
import { DecryptIdTokenData, LegacyDecryptIdTokenData } from "./decrypt.handler";
import { normalizeKMSResponseData } from "../common.types";
import { UI8A } from "../../utils/lib/binary-data-types/binary-data-types.utils";

export async function decrypt(
idToken: IdTokenWithData<DecryptIdTokenData | LegacyDecryptIdTokenData>,
Expand Down Expand Up @@ -34,5 +34,5 @@ export async function decrypt(
throw createOrPropagateError(OthentErrorID.Decryption, 500, "No plaintext");
}

return normalizeKMSResponseData(plaintext);
return UI8A.from(plaintext, "string");
}
Loading