yescrypt-wasm
Version:
WebAssembly module for Yescrypt
60 lines (55 loc) • 2.15 kB
text/typescript
// Encode bytes as base64. Uses Buffer when available (Node) for speed, and a
// chunked btoa() fallback in the browser that avoids building one giant
// intermediate string (the previous reduce()-based version was O(n^2) and could
// overflow the call stack / be very slow for large inputs such as the embedded
// .wasm binary).
export function bytesToBase64(bytes: Uint8Array): string {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const B = (globalThis as any).Buffer;
if (typeof B !== 'undefined') {
return B.from(bytes).toString('base64');
}
let binary = '';
const chunkSize = 0x8000; // 32 KiB worth of chars per fromCharCode call
for (let i = 0; i < bytes.length; i += chunkSize) {
const chunk = bytes.subarray(i, i + chunkSize);
binary += String.fromCharCode(...chunk);
}
return btoa(binary);
}
export function base64ToBytes(base64: string): Uint8Array {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const B = (globalThis as any).Buffer;
if (typeof B !== 'undefined') {
return new Uint8Array(B.from(base64, 'base64'));
}
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
}
// Encode bytes as a hex string. By default a "0x" prefix is prepended (kept for
// backward compatibility); pass `prefix = false` to get a bare hex string.
export function bytesToHex(bytes: Uint8Array, prefix = true): string {
let hex = '';
for (const byte of bytes) {
hex += byte.toString(16).padStart(2, '0');
}
return prefix ? '0x' + hex : hex;
}
export function hexToBytes(hexStr: string): Uint8Array {
if (hexStr.startsWith('0x')) {
hexStr = hexStr.slice(2);
}
if (hexStr.length % 2 !== 0) {
hexStr = '0' + hexStr;
}
if (hexStr.length === 0) {
return new Uint8Array(0);
}
if (!/^[0-9a-fA-F]+$/.test(hexStr)) {
throw new Error('hexToBytes: invalid hex string');
}
const out = new Uint8Array(hexStr.length / 2);
for (let i = 0; i < out.length; i++) {
out[i] = parseInt(hexStr.substr(i * 2, 2), 16);
}
return out;
}