browserify-hybrid-crypto
v1.2.3
Published
TypeScript implementation Hybrid encryption and signing library built on Web Crypto (AES + RSA + HMAC).
Maintainers
Readme
🔐 browserify-hybrid-crypto
Hybrid encryption and signing library built on Web Crypto (AES + RSA + HMAC)
✨ Features
- 🔒 Hybrid Encryption: AES-GCM for fast encryption + RSA-OAEP for secure key exchange.
- 🖊️ Integrity Protection: HMAC-SHA signatures to ensure authenticity, protecting against tampering.
- 📦 Lightweight: Uses only the native Web Crypto API.
- 🌐 Cross-Platform: Works in modern browsers and Node.js.
- 🛠️ Simple API: Just call
hybridEncryptandhybridDecrypt.
📦 Installation
npm install browserify-hybrid-cryptoor with yarn:
yarn add browserify-hybrid-crypto🚀 Usage
🔒 Encrypt
import { hybridEncrypt } from "browserify-hybrid-crypto";
const publicKeyPEM = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...
-----END PUBLIC KEY-----`;
async function runEncrypt() {
// You can pass options to configure encryption
const result = await hybridEncrypt(publicKeyPEM, "Hello Hybrid Crypto! 🔐", {
aesAlgorithm: "AES-GCM", // "AES-GCM" | "AES-CBC" | "AES-CTR"
aesKeyLength: 256, // 128 | 192 | 256
ivLength: 12, // IV length in bytes (default: 12 for GCM)
hmacHash: "SHA-256", // "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512"
rsaOaepHash: "SHA-256", // "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512"
ctrCounter: undefined, // Uint8Array (for AES-CTR only)
ctrLength: 64, // Counter length in bits (for AES-CTR only)
});
console.log(result);
/*
{
encryptedSessionKey: Uint8Array,
encryptedSigningKey: Uint8Array,
encryptedData: Uint8Array,
signature: Uint8Array,
iv: Uint8Array // IV or counter used for AES
}
*/
}🔓 Decrypt
import { hybridDecrypt } from "browserify-hybrid-crypto";
const privateKeyPEM = `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...
-----END PRIVATE KEY-----`;
async function runDecrypt(encryptedPayload) {
// Pass the same options used for encryption if you customized them
const message = await hybridDecrypt(privateKeyPEM, encryptedPayload, {
aesAlgorithm: "AES-GCM",
aesKeyLength: 256,
ivLength: 12,
hmacHash: "SHA-256",
rsaOaepHash: "SHA-256",
ctrCounter: undefined,
ctrLength: 64,
});
console.log("Decrypted message:", message);
// "Hello Hybrid Crypto! 🔐"
}🔑 Generating RSA Keys
You’ll need an RSA key pair in PEM format. You can generate them either via OpenSSL or directly in the browser.
🖥️ Option 1: Using OpenSSL (Node/CLI)
# Generate a 4096-bit private key
openssl genrsa -out private.pem 4096
# Extract the public key from the private key
openssl rsa -in private.pem -pubout -out public.pemNow you’ll have:
private.pem→ RSA private key (use inhybridDecrypt)public.pem→ RSA public key (use inhybridEncrypt)
🌐 Option 2: Generate Keys in the Browser
You can generate RSA keys directly with the Web Crypto API:
async function generateRSAKeyPair() {
const keyPair = await crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]), // 65537
hash: "SHA-256",
},
true,
["encrypt", "decrypt"],
);
const spki = await crypto.subtle.exportKey("spki", keyPair.publicKey);
const pkcs8 = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
const publicKeyPEM = toPEM(spki, "PUBLIC KEY");
const privateKeyPEM = toPEM(pkcs8, "PRIVATE KEY");
console.log("Public Key PEM:\n", publicKeyPEM);
console.log("Private Key PEM:\n", privateKeyPEM);
return { publicKeyPEM, privateKeyPEM };
}
function toPEM(buffer, type) {
const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));
const chunks = base64.match(/.{1,64}/g).join("\n");
return `-----BEGIN ${type}-----\n${chunks}\n-----END ${type}-----`;
}This will generate a fresh key pair and export both keys in PEM format, ready to use with hybridEncrypt and hybridDecrypt.
🛡️ Secure Chat Example
browserify-hybrid-crypto combines asymmetric encryption (RSA-OAEP), symmetric session keys (AES-CBC), and signing keys (HMAC) to ensure secure, authenticated communication.
Below is a typical flow for a chat between Alice and Bob (the same process applies to group chats):
Room Creation:
Bob creates a chat room and immediately generates an RSA-OAEP public/private key pair.
Key Exchange:
Alice joins the room and also generates her own RSA-OAEP key pair. Both users exchange public keys.
Message Preparation:
When Bob sends a message, he generates:
- A random session key (AES-CBC)
- A signing key (HMAC-SHA256)
- An initialization vector (IV) for encryption
Encryption & Signing:
Bob encrypts his message using the session key and IV, then signs the encrypted message with the signing key.
Key Wrapping:
The session key and signing key are each encrypted (wrapped) with every recipient’s public key (for a group chat, this is done for each participant).
Sending the Package:
Bob sends a package to all recipients containing:
- The encrypted message
- The IV
- The signature
- The encrypted session key(s)
- The encrypted signing key(s)
Decryption & Verification:
Each recipient (e.g., Alice) decrypts the session and signing keys with their private key, decrypts the message, and verifies the signature.
Group chats follow the same process: each recipient receives their own encrypted keys, and can independently decrypt and verify messages.
🔄 Sequence Diagram
sequenceDiagram
participant Bob
participant Alice
Bob->>Bob: Generate RSA key pair
Alice->>Alice: Generate RSA key pair
Bob->>Alice: Send Bob's public key
Alice->>Bob: Send Alice's public key
Bob->>Bob: hybridEncrypt(Alice's public key, message)
Bob->>Alice: Send { encrypted message, IV, signature, encrypted session key, encrypted signing key }
Alice->>Alice: hybridDecrypt(Alice's private key, encrypted payload)
Note over Alice: Decrypts session key and signing key<br>Decrypts message<br>Verifies signature
Alice->>Alice: hybridEncrypt(Bob's public key, reply message)
Alice->>Bob: Send { encrypted reply, IV, signature, encrypted session key, encrypted signing key }
Bob->>Bob: hybridDecrypt(Bob's private key, encrypted payload)
Note over Bob: Decrypts session key and signing key<br>Decrypts reply message<br>Verifies signatureNote: In group chats, Bob repeats the key encryption step for each participant, so every user receives their own encrypted session and signing keys.
🔐 Replay Attack Prevention
To protect against replay attacks, you can include a nonce or timestamp in each message. This ensures that even if an attacker intercepts a message, they cannot resend it without the correct nonce or timestamp.
It's recommended to implement a mechanism to track used nonces or timestamps on the server side, so that each one can only be used once.
Beware that this library does not handle replay attack prevention directly; you need to implement it in your application logic.
⚖️ License
MIT © Vlad Kucherov
💡 Notes
- Supports RSA-OAEP + AES-GCM + HMAC-SHA256.
- Works in browsers and Node.js environments.
- RSA key length recommended: 4096 bits.
- Always keep your private key secret!
