From 1257c90ff031153aa181e1b8ff4d01681e5d7a40 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Tue, 22 Oct 2024 22:07:18 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=94=92=20update=20hash=20algorithm?= =?UTF-8?q?=20names=20to=20include=20hyphens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content/docs/reference/scripts/parsers.md | 2 +- packages/core/src/cache.ts | 2 +- packages/core/src/crypto.ts | 45 ++++++++++++------- packages/core/src/types/prompt_template.d.ts | 2 +- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/docs/src/content/docs/reference/scripts/parsers.md b/docs/src/content/docs/reference/scripts/parsers.md index 1584ed0fc4..88ee2effce 100644 --- a/docs/src/content/docs/reference/scripts/parsers.md +++ b/docs/src/content/docs/reference/scripts/parsers.md @@ -324,7 +324,7 @@ Utility to hash an object, array into a string that is appropriate for hashing p const h = parsers.hash({ obj, other }, { length: 12 }) ``` -By default, uses `sha1`, but `sha256` can also be used. The hash packing logic may change between versions of genaiscript. +By default, uses `sha-1`, but `sha-256` can also be used. The hash packing logic may change between versions of genaiscript. ## Command line diff --git a/packages/core/src/cache.ts b/packages/core/src/cache.ts index 82811d1da7..f0542e5b6a 100644 --- a/packages/core/src/cache.ts +++ b/packages/core/src/cache.ts @@ -207,5 +207,5 @@ export class JSONLineCache extends MemoryCache { * @returns A promise resolving to the SHA256 hash string */ async function keySHA(key: any) { - return await hash(key, { algorithm: "sha256", version: true }) // Compute SHA256 hash + return await hash(key, { algorithm: "sha-256", version: true }) // Compute SHA256 hash } diff --git a/packages/core/src/crypto.ts b/packages/core/src/crypto.ts index 4139d686b6..8723aec56b 100644 --- a/packages/core/src/crypto.ts +++ b/packages/core/src/crypto.ts @@ -1,8 +1,26 @@ // crypto.ts - Provides cryptographic functions for secure operations // Importing the toHex function from the util module to convert byte arrays to hexadecimal strings -import { toHex, utf8Encode } from "./util" -import { getRandomValues, createHash } from "crypto" +import { concatBuffers, toHex, utf8Encode } from "./util" + +async function getRandomValues(bytes: Uint8Array) { + if (typeof self !== "undefined" && self.crypto) { + self.crypto.getRandomValues(bytes) + } else { + const { getRandomValues } = await import("crypto") + getRandomValues(bytes) + } +} + +async function digest(algorithm: string, data: Uint8Array) { + algorithm = algorithm.toUpperCase() + if (typeof self !== "undefined" && self.crypto) { + return self.crypto.subtle.digest(algorithm, data) + } else { + const { subtle } = await import("crypto") + return subtle.digest(algorithm, data) + } +} /** * Generates a random hexadecimal string of a specified size. @@ -22,37 +40,32 @@ export function randomHex(size: number) { } export async function hash(value: any, options?: HashOptions) { - const { algorithm = "sha1", length, ...rest } = options || {} + const { algorithm = "sha-1", length, ...rest } = options || {} - const h = createHash(algorithm) + const h: Uint8Array[] = [] const append = async (v: any) => { if ( typeof v == "string" || typeof v === "number" || typeof v === "boolean" ) - h.update(String(v), "utf8") + h.push(utf8Encode(String(v))) else if (Array.isArray(v)) for (const c of v) await append(c) - else if (v instanceof Buffer) h.update(v) + else if (v instanceof Buffer) h.push(new Uint8Array(v)) else if (v instanceof Blob) - h.update(new Uint8Array(await v.arrayBuffer())) + h.push(new Uint8Array(await v.arrayBuffer())) else if (typeof v === "object") for (const c of Object.keys(v).sort()) { - h.update(c, "utf8") + h.push(utf8Encode(c)) await append(v[c]) } - else h.update(utf8Encode(JSON.stringify(v))) + else h.push(utf8Encode(JSON.stringify(v))) } await append(value) await append(rest) - const buf = await h.digest() - let res: string - try { - res = await buf.toString("hex") - } catch (e) { - res = toHex(new Uint8Array(buf)) - } + const buf = await digest(algorithm, concatBuffers(...h)) + let res = toHex(new Uint8Array(buf)) if (length) res = res.slice(0, length) return res } diff --git a/packages/core/src/types/prompt_template.d.ts b/packages/core/src/types/prompt_template.d.ts index a6d3e717be..07dcd2cbcd 100644 --- a/packages/core/src/types/prompt_template.d.ts +++ b/packages/core/src/types/prompt_template.d.ts @@ -1115,7 +1115,7 @@ interface Tokenizers { } interface HashOptions { - algorithm?: "sha1" | "sha256" + algorithm?: "sha-1" | "sha-256" length?: number version?: boolean }