audit-labs/gh-attest

GitHub Audit Evidence Extractor

clone: git clone https://gitbay.org/audit-labs/gh-attest.git

v1.0.0: 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] = 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}