UNPKG

@hpke/common

Version:

A Hybrid Public Key Encryption (HPKE) internal-use common module for @hpke family modules.

177 lines (176 loc) 4.86 kB
import * as dntShim from "../../_dnt.shims.js"; import { KemId } from "../identifiers.js"; export const isDenoV1 = () => // deno-lint-ignore no-explicit-any dntShim.dntGlobalThis.process === undefined; /** * Checks whether the runtime is Deno or not (Node.js). * @returns boolean - true if the runtime is Deno, false Node.js. */ export function isDeno() { // deno-lint-ignore no-explicit-any if (dntShim.dntGlobalThis.process === undefined) { return true; } // deno-lint-ignore no-explicit-any return dntShim.dntGlobalThis.process?.versions?.deno !== undefined; } /** * Checks whetehr the type of input is CryptoKeyPair or not. */ export const isCryptoKeyPair = (x) => typeof x === "object" && x !== null && typeof x.privateKey === "object" && typeof x.publicKey === "object"; /** * Converts integer to octet string. I2OSP implementation. */ export function i2Osp(n, w) { if (w <= 0) { throw new Error("i2Osp: too small size"); } if (n >= 256 ** w) { throw new Error("i2Osp: too large integer"); } const ret = new Uint8Array(w); for (let i = 0; i < w && n; i++) { ret[w - (i + 1)] = n % 256; n = Math.floor(n / 256); } return ret; } /** * Concatenates two Uint8Arrays. * @param a Uint8Array * @param b Uint8Array * @returns Concatenated Uint8Array */ export function concat(a, b) { const ret = new Uint8Array(a.length + b.length); ret.set(a, 0); ret.set(b, a.length); return ret; } /** * Decodes Base64Url-encoded data. * @param v Base64Url-encoded string * @returns Uint8Array */ export function base64UrlToBytes(v) { const base64 = v.replace(/-/g, "+").replace(/_/g, "/"); const byteString = atob(base64); const ret = new Uint8Array(byteString.length); for (let i = 0; i < byteString.length; i++) { ret[i] = byteString.charCodeAt(i); } return ret; } /** * Encodes Uint8Array to Base64Url. * @param v Uint8Array * @returns Base64Url-encoded string */ export function bytesToBase64Url(v) { 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) { 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) { return [...v].map((x) => x.toString(16).padStart(2, "0")).join(""); } /** * Converts KemId to KeyAlgorithm. * @param kem KemId * @returns KeyAlgorithm */ export function kemToKeyGenAlgorithm(kem) { switch (kem) { case KemId.DhkemP256HkdfSha256: return { name: "ECDH", namedCurve: "P-256", }; case KemId.DhkemP384HkdfSha384: return { name: "ECDH", namedCurve: "P-384", }; case KemId.DhkemP521HkdfSha512: return { name: "ECDH", namedCurve: "P-521", }; default: // case KemId.DhkemX25519HkdfSha256 return { name: "X25519", }; } } export async function loadSubtleCrypto() { if (dntShim.dntGlobalThis !== 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.subtle; } catch (_e) { throw new Error("Failed to load SubtleCrypto"); } } export async function loadCrypto() { if (typeof dntShim.dntGlobalThis !== "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; } catch (_e) { throw new Error("failed to load Crypto"); } } /** * XOR for Uint8Array. */ export function xor(a, b) { if (a.byteLength !== b.byteLength) { throw new Error("xor: different length inputs"); } const buf = new Uint8Array(a.byteLength); for (let i = 0; i < a.byteLength; i++) { buf[i] = a[i] ^ b[i]; } return buf; }