A WebCrypto polyfill for Node.js that provides comprehensive cryptographic operations using standard Web Crypto API
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Cryptographic hash functions for data integrity, digital signatures, and key derivation. Supports SHA family, SHA-3, and SHAKE extendable-output functions.
Standard SHA (Secure Hash Algorithm) functions widely used in cryptographic applications.
/**
* SHA hash algorithms
*/
type ShaAlgorithm = "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512";Usage Example:
// Compute SHA-256 hash
const data = new TextEncoder().encode("Data to hash");
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
console.log("SHA-256:", hashHex);/**
* SHA-1 hash function (deprecated for security-critical applications)
*/
interface Sha1Algorithm extends Algorithm {
name: "SHA-1";
}/**
* SHA-256 hash function (256-bit output)
*/
interface Sha256Algorithm extends Algorithm {
name: "SHA-256";
}/**
* SHA-384 hash function (384-bit output)
*/
interface Sha384Algorithm extends Algorithm {
name: "SHA-384";
}/**
* SHA-512 hash function (512-bit output)
*/
interface Sha512Algorithm extends Algorithm {
name: "SHA-512";
}SHA-3 hash functions based on Keccak algorithm (availability depends on Node.js crypto support).
/**
* SHA-3 hash algorithms (platform-dependent)
*/
type Sha3Algorithm = "SHA3-256" | "SHA3-384" | "SHA3-512";
interface Sha3Params extends Algorithm {
name: "SHA3-256" | "SHA3-384" | "SHA3-512";
}Usage Example:
// SHA-3 availability check and usage
try {
const data = new TextEncoder().encode("SHA-3 test data");
const hash = await crypto.subtle.digest("SHA3-256", data);
console.log("SHA3-256 supported");
} catch (error) {
console.log("SHA3-256 not available on this platform");
}SHAKE functions provide variable-length output for specialized applications.
/**
* SHAKE extendable-output function parameters
*/
interface ShakeParams extends Algorithm {
name: "shake128" | "shake256";
length: number; // Output length in bytes
}Usage Example:
// SHAKE128 with custom output length
const data = new TextEncoder().encode("Data for SHAKE");
const shakeOutput = await crypto.subtle.digest(
{ name: "shake128", length: 32 }, // 32 bytes output
data
);
// SHAKE256 with different output length
const shake256Output = await crypto.subtle.digest(
{ name: "shake256", length: 64 }, // 64 bytes output
data
);| Algorithm | Output Size | Security Level | Performance | Use Cases |
|---|---|---|---|---|
| SHA-1 | 160 bits | Deprecated | Fast | Legacy compatibility only |
| SHA-256 | 256 bits | High | Good | General purpose, Bitcoin |
| SHA-384 | 384 bits | High | Moderate | High security requirements |
| SHA-512 | 512 bits | High | Good | High security, 64-bit platforms |
| SHA3-256 | 256 bits | High | Moderate | Alternative to SHA-256 |
| SHA3-384 | 384 bits | High | Moderate | Alternative to SHA-384 |
| SHA3-512 | 512 bits | High | Moderate | Alternative to SHA-512 |
| SHAKE128 | Variable | High | Moderate | Custom output length |
| SHAKE256 | Variable | High | Moderate | Custom output length |
async function computeMultipleHashes(data: ArrayBuffer) {
const algorithms: Algorithm[] = [
"SHA-1",
"SHA-256",
"SHA-384",
"SHA-512"
];
const hashes = await Promise.all(
algorithms.map(async (algorithm) => {
try {
const hash = await crypto.subtle.digest(algorithm, data);
return { algorithm, hash, success: true };
} catch (error) {
return { algorithm, error, success: false };
}
})
);
return hashes;
}
// Usage
const data = new TextEncoder().encode("Test data");
const results = await computeMultipleHashes(data);async function hashFile(fileData: ArrayBuffer, algorithm = "SHA-256") {
const hashBuffer = await crypto.subtle.digest(algorithm, fileData);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
// Usage for file verification
const fileHash = await hashFile(fileData);
const expectedHash = "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3";
const isValid = fileHash === expectedHash;// For large data, consider chunked processing
async function hashLargeData(dataChunks: ArrayBuffer[]) {
// Note: WebCrypto doesn't directly support streaming
// This concatenates chunks for demonstration
const totalLength = dataChunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
const combined = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of dataChunks) {
combined.set(new Uint8Array(chunk), offset);
offset += chunk.byteLength;
}
return await crypto.subtle.digest("SHA-256", combined);
}class Sha1Provider extends core.ProviderCrypto {
public name: "SHA-1";
public usages: never[]; // Digest only
}
class Sha256Provider extends core.ProviderCrypto {
public name: "SHA-256";
public usages: never[]; // Digest only
}
class Sha384Provider extends core.ProviderCrypto {
public name: "SHA-384";
public usages: never[]; // Digest only
}
class Sha512Provider extends core.ProviderCrypto {
public name: "SHA-512";
public usages: never[]; // Digest only
}
class Shake128Provider extends core.ProviderCrypto {
public name: "shake128";
public usages: never[]; // Digest only
}
class Shake256Provider extends core.ProviderCrypto {
public name: "shake256";
public usages: never[]; // Digest only
}async function safeDigest(algorithm: string, data: BufferSource) {
try {
return await crypto.subtle.digest(algorithm, data);
} catch (error) {
if (error.name === "NotSupportedError") {
throw new Error(`Hash algorithm ${algorithm} not supported`);
}
if (error.name === "TypeError") {
throw new Error("Invalid data format for hashing");
}
throw error;
}
}Install with Tessl CLI
npx tessl i tessl/npm-peculiar--webcrypto