Skip to content

Commit

Permalink
Merge pull request #406 from dajiaji/merge-test-utils
Browse files Browse the repository at this point in the history
Merge test utils to @hpke/common.
  • Loading branch information
dajiaji authored Oct 6, 2024
2 parents 844f50b + 6573bde commit bf81e5a
Show file tree
Hide file tree
Showing 31 changed files with 674 additions and 394 deletions.
2 changes: 1 addition & 1 deletion packages/chacha20poly1305/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@
"test:bun": "cd test/runtimes/bun && bun install && bun test",
"cov": "deno coverage ./coverage --lcov --exclude='test'",
"dnt": "deno run --import-map=../../npm/import_map.json -A dnt.ts",
"minify": "esbuild ../../npm/packages/chacha20poly1305/esm/chacha20poly1305/mod.js --bundle --format=esm --minify"
"minify": "esbuild ../../npm/packages/chacha20poly1305/esm/mod.js --bundle --format=esm --minify"
}
}
10 changes: 5 additions & 5 deletions packages/chacha20poly1305/dnt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ await build({
homepage:
"https://github.com/dajiaji/hpke-js/tree/main/packages/chacha20poly1305#readme",
license: "MIT",
module: "./esm/chacha20poly1305/mod.js",
main: "./script/chacha20poly1305/mod.js",
types: "./esm/chacha20poly1305/mod.d.ts",
module: "./esm/mod.js",
main: "./script/mod.js",
types: "./esm/mod.d.ts",
sideEffects: false,
exports: {
".": {
"import": "./esm/chacha20poly1305/mod.js",
"require": "./script/chacha20poly1305/mod.js",
"import": "./esm/mod.js",
"require": "./script/mod.js",
},
"./package.json": "./package.json",
},
Expand Down
2 changes: 1 addition & 1 deletion packages/chacha20poly1305/test/chacha20poly1305.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { assertEquals } from "@std/assert";
import { describe, it } from "@std/testing/bdd";

import { loadCrypto } from "@hpke/common";
import {
AeadId,
CipherSuite,
DhkemP256HkdfSha256,
HkdfSha256,
} from "@hpke/core";

import { loadCrypto } from "../../core/test/utils.ts";
import { Chacha20Poly1305 } from "../mod.ts";

describe("Chacha20Poly1305", () => {
Expand Down
12 changes: 11 additions & 1 deletion packages/common/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,14 @@ export { LABEL_DKP_PRK, LABEL_SK } from "./src/interfaces/dhkemPrimitives.ts";
export { SUITE_ID_HEADER_KEM } from "./src/interfaces/kemInterface.ts";
export { EMPTY, INPUT_LENGTH_LIMIT, MINIMUM_PSK_LENGTH } from "./src/consts.ts";

export { concat, i2Osp, isCryptoKeyPair, xor } from "./src/utils/misc.ts";
export {
concat,
hexToBytes,
i2Osp,
isCryptoKeyPair,
isNode,
kemToKeyGenAlgorithm,
loadCrypto,
loadSubtleCrypto,
xor,
} from "./src/utils/misc.ts";
111 changes: 111 additions & 0 deletions packages/common/src/utils/misc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { KemId } from "../identifiers.ts";

declare const Deno: undefined;

export const isNode = (): boolean =>
// deno-lint-ignore no-explicit-any
(globalThis as any).process?.versions?.node != null;

/**
* Checks whetehr the type of input is CryptoKeyPair or not.
*/
Expand Down Expand Up @@ -29,6 +35,9 @@ export function i2Osp(n: number, w: number): Uint8Array {

/**
* Concatenates two Uint8Arrays.
* @param a Uint8Array
* @param b Uint8Array
* @returns Concatenated Uint8Array
*/
export function concat(a: Uint8Array, b: Uint8Array): Uint8Array {
const ret = new Uint8Array(a.length + b.length);
Expand All @@ -39,6 +48,8 @@ export function concat(a: Uint8Array, b: Uint8Array): Uint8Array {

/**
* Decodes Base64Url-encoded data.
* @param v Base64Url-encoded string
* @returns Uint8Array
*/
export function base64UrlToBytes(v: string): Uint8Array {
const base64 = v.replace(/-/g, "+").replace(/_/g, "/");
Expand All @@ -50,6 +61,106 @@ export function base64UrlToBytes(v: string): Uint8Array {
return ret;
}

/**
* Encodes Uint8Array to Base64Url.
* @param v Uint8Array
* @returns Base64Url-encoded string
*/
export function bytesToBase64Url(v: Uint8Array): string {
return btoa(String.fromCharCode(...v))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=*$/g, "");
}

/**
* Decodes hex string to Uint8Array.
* @param v Hex string
* @returns Uint8Array
* @throws Error if the input is not a hex string.
*/
export function hexToBytes(v: string): Uint8Array {
if (v.length === 0) {
return new Uint8Array([]);
}
const res = v.match(/[\da-f]{2}/gi);
if (res == null) {
throw new Error("Not hex string.");
}
return new Uint8Array(res.map(function (h) {
return parseInt(h, 16);
}));
}

/**
* Encodes Uint8Array to hex string.
* @param v Uint8Array
* @returns Hex string
*/
export function bytesToHex(v: Uint8Array): string {
return [...v].map((x) => x.toString(16).padStart(2, "0")).join("");
}

/**
* Converts KemId to KeyAlgorithm.
* @param kem KemId
* @returns KeyAlgorithm
*/
export function kemToKeyGenAlgorithm(kem: KemId): KeyAlgorithm {
switch (kem) {
case KemId.DhkemP256HkdfSha256:
return {
name: "ECDH",
namedCurve: "P-256",
} as KeyAlgorithm;
case KemId.DhkemP384HkdfSha384:
return {
name: "ECDH",
namedCurve: "P-384",
} as KeyAlgorithm;
case KemId.DhkemP521HkdfSha512:
return {
name: "ECDH",
namedCurve: "P-521",
} as KeyAlgorithm;
default:
// case KemId.DhkemX25519HkdfSha256
return {
name: "X25519",
};
}
}

export async function loadSubtleCrypto(): Promise<SubtleCrypto> {
if (globalThis !== undefined && globalThis.crypto !== undefined) {
// Browsers, Node.js >= v19, Cloudflare Workers, Bun, etc.
return globalThis.crypto.subtle;
}
// Node.js <= v18
try {
// @ts-ignore: to ignore "crypto"
const { webcrypto } = await import("crypto"); // node:crypto
return (webcrypto as unknown as Crypto).subtle;
} catch (_e: unknown) {
throw new Error("Failed to load SubtleCrypto");
}
}

export async function loadCrypto(): Promise<Crypto> {
if (globalThis !== undefined && globalThis.crypto !== undefined) {
// Browsers, Node.js >= v19, Cloudflare Workers, Bun, etc.
return globalThis.crypto;
}
// Node.js <= v18
try {
// @ts-ignore: to ignore "crypto"
const { webcrypto } = await import("crypto"); // node:crypto
return (webcrypto as unknown as Crypto);
} catch (_e: unknown) {
throw new Error("Web Cryptograph API not supported");
}
}

/**
* XOR for Uint8Array.
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/core/test/cipherSuite.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { assertEquals, assertRejects, assertThrows } from "@std/assert";
import { describe, it } from "@std/testing/bdd";

import { hexToBytes, isNode } from "@hpke/common";

import {
AeadId,
Aes128Gcm,
Expand All @@ -19,8 +21,6 @@ import {
KemId,
} from "../mod.ts";

import { hexToBytes, isNode } from "./utils.ts";

describe("constructor", () => {
describe("with DhkemP384HkdfSha384/HkdfSha384/Aes128Gcm", () => {
it("should have a correct ciphersuite", () => {
Expand Down
Loading

0 comments on commit bf81e5a

Please sign in to comment.