browserify-hybrid-crypto
Version:
TypeScript implementation Hybrid encryption and signing library built on Web Crypto (AES + RSA + HMAC).
84 lines (71 loc) • 2.15 kB
text/typescript
import { importPrivateKey } from "./import-key";
import { HybridEncryption, HybridCryptoOptions } from "./interfaces";
import { getCryptoImpl } from "./utils";
import { getAesParams } from "./aes-params";
export async function hybridDecrypt(
privateKeyPEM: string,
{
encryptedSessionKey,
encryptedSigningKey,
encryptedData,
signature,
iv,
}: HybridEncryption,
options: HybridCryptoOptions = {},
): Promise<string> {
const crypto = getCryptoImpl();
const { aesAlgorithm = "AES-GCM", hmacHash = "SHA-256" } = options;
// Import private key
const privateKey = await importPrivateKey(privateKeyPEM);
// Decrypt the session key with the private key using RSA-OAEP
const sessionKey = await crypto.subtle.decrypt(
{ name: "RSA-OAEP" },
privateKey,
encryptedSessionKey,
);
// Import the session key into a CryptoKey object for AES-GCM decryption
const sessionCryptoKey = await crypto.subtle.importKey(
"raw",
sessionKey,
{ name: aesAlgorithm },
false,
["decrypt"],
);
// Decrypt the signing key with the privateKey using RSA-OAEP
const signingKey = await crypto.subtle.decrypt(
{ name: "RSA-OAEP" },
privateKey,
encryptedSigningKey,
);
// Import the signing key into a CryptoKey object for HMAC verification
const signingCryptoKey = await crypto.subtle.importKey(
"raw",
signingKey,
{
name: "HMAC",
hash: hmacHash,
},
false,
["verify"],
);
// Verify the signature of the encrypted data
const isValidSignature = await crypto.subtle.verify(
{ name: "HMAC" },
signingCryptoKey,
signature,
encryptedData,
);
if (!isValidSignature) {
throw new Error("Signature verification failed");
}
// Get AES params and IV/counter for decryption
const aesParams = getAesParams(aesAlgorithm, options, iv);
// Decrypt the data with the session key using AES
const decryptedData = await crypto.subtle.decrypt(
aesParams.aesParams,
sessionCryptoKey,
encryptedData,
);
// Decode the decrypted data from ArrayBuffer to string
return new TextDecoder().decode(decryptedData);
}