audit-labs/gh-attest
GitHub Audit Evidence Extractor
clone: git clone https://gitbay.org/audit-labs/gh-attest.git
v1.0.1: src/crypto-utils.ts · raw
1export function hexToBytes(hex: string): Uint8Array {
2 const bytes = new Uint8Array(hex.length / 2);
3 for (let i = 0; i < bytes.length; i++) {
4 bytes[i] = Number.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
5 }
6 return bytes;
7}
8
9export function bytesToHex(bytes: Uint8Array): string {
10 return Array.from(bytes)
11 .map((b) => b.toString(16).padStart(2, "0"))
12 .join("");
13}
14
15export async function hmacHex(data: string, secret: string): Promise<string> {
16 const key = await crypto.subtle.importKey(
17 "raw",
18 new TextEncoder().encode(secret),
19 { name: "HMAC", hash: "SHA-256" },
20 false,
21 ["sign"],
22 );
23 const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(data));
24 return bytesToHex(new Uint8Array(signature));
25}
26
27// crypto.subtle.timingSafeEqual throws on mismatched-length inputs rather
28// than returning false, so length is checked explicitly first.
29export function timingSafeEqualHex(a: string, b: string): boolean {
30 if (a.length !== b.length) return false;
31 return crypto.subtle.timingSafeEqual(hexToBytes(a), hexToBytes(b));
32}