Skip to content
File

Blob: src/worker/auth/bytes.ts

typescript71 lines
1const textEncoder = new TextEncoder();
2const textDecoder = new TextDecoder();
3const base32Alphabet = "abcdefghijklmnopqrstuvwxyz234567";
4 
5export function utf8Bytes(value: string): Uint8Array {
6 return textEncoder.encode(value);
7}
8 
9export function utf8String(bytes: Uint8Array): string {
10 return textDecoder.decode(bytes);
11}
12 
13export function randomBytes(length: number): Uint8Array {
14 const bytes = new Uint8Array(length);
15 crypto.getRandomValues(bytes);
16 return bytes;
17}
18 
19export function hexFromBytes(bytes: Uint8Array): string {
20 return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
21}
22 
23export function randomHex(byteLength: number): string {
24 return hexFromBytes(randomBytes(byteLength));
25}
26 
27export function base32FromBytes(bytes: Uint8Array): string {
28 let output = "";
29 let buffer = 0;
30 let bits = 0;
31 
32 for (const byte of bytes) {
33 buffer = (buffer << 8) | byte;
34 bits += 8;
35 
36 while (bits >= 5) {
37 output += base32Alphabet[(buffer >>> (bits - 5)) & 31];
38 bits -= 5;
39 }
40 }
41 
42 if (bits > 0) output += base32Alphabet[(buffer << (5 - bits)) & 31];
43 return output;
44}
45 
46export function base64UrlEncode(bytes: Uint8Array): string {
47 let binary = "";
48 for (const byte of bytes) binary += String.fromCharCode(byte);
49 return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
50}
51 
52export function base64UrlDecode(value: string): Uint8Array {
53 const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
54 const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
55 const binary = atob(padded);
56 const bytes = new Uint8Array(binary.length);
57 for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
58 return bytes;
59}
60 
61export function constantTimeEqual(a: string, b: string): boolean {
62 const maxLength = Math.max(a.length, b.length);
63 let diff = a.length ^ b.length;
64 
65 for (let i = 0; i < maxLength; i += 1) {
66 diff |= (a.charCodeAt(i) || 0) ^ (b.charCodeAt(i) || 0);
67 }
68 
69 return diff === 0;
70}