52 lines · 1.5 KB
1 /**
2 * SHA-1 hashing using the Web Crypto API.
3 * Used for computing git object IDs.
4 */
5
6 const encoder = new TextEncoder();
7
8 /** Compute SHA-1 hash of data, returning a 40-character hex string. */
9 export async function sha1(data: Uint8Array): Promise<string> {
10 const hashBuffer = await crypto.subtle.digest('SHA-1', data);
11 return hexEncode(new Uint8Array(hashBuffer));
12 }
13
14 /** Compute SHA-256 hash of data, returning a 64-character hex string. */
15 export async function sha256(data: Uint8Array): Promise<string> {
16 const hashBuffer = await crypto.subtle.digest('SHA-256', data);
17 return hexEncode(new Uint8Array(hashBuffer));
18 }
19
20 /** Encode a Uint8Array as a hex string. */
21 export function hexEncode(bytes: Uint8Array): string {
22 let hex = '';
23 for (let i = 0; i < bytes.length; i++) {
24 hex += bytes[i].toString(16).padStart(2, '0');
25 }
26 return hex;
27 }
28
29 /** Decode a hex string to Uint8Array. */
30 export function hexDecode(hex: string): Uint8Array {
31 const bytes = new Uint8Array(hex.length / 2);
32 for (let i = 0; i < hex.length; i += 2) {
33 bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
34 }
35 return bytes;
36 }
37
38 /**
39 * Compute the SHA-1 hash of a git object.
40 * Git objects are hashed as: "{type} {size}\0{content}"
41 */
42 export async function gitObjectHash(
43 type: string,
44 content: Uint8Array
45 ): Promise<string> {
46 const header = encoder.encode(`${type} ${content.length}\0`);
47 const full = new Uint8Array(header.length + content.length);
48 full.set(header, 0);
49 full.set(content, header.length);
50 return sha1(full);
51 }
52