npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

browserify-hybrid-crypto

v1.2.3

Published

TypeScript implementation Hybrid encryption and signing library built on Web Crypto (AES + RSA + HMAC).

Readme

🔐 browserify-hybrid-crypto

Hybrid encryption and signing library built on Web Crypto (AES + RSA + HMAC)

NPM Version License


✨ 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 hybridEncrypt and hybridDecrypt.

📦 Installation

npm install browserify-hybrid-crypto

or 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.pem

Now you’ll have:

  • private.pem → RSA private key (use in hybridDecrypt)
  • public.pem → RSA public key (use in hybridEncrypt)

🌐 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):

  1. Room Creation:

    Bob creates a chat room and immediately generates an RSA-OAEP public/private key pair.

  2. Key Exchange:

    Alice joins the room and also generates her own RSA-OAEP key pair. Both users exchange public keys.

  3. 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
  4. Encryption & Signing:

    Bob encrypts his message using the session key and IV, then signs the encrypted message with the signing key.

  5. 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).

  6. 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)
  7. 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 signature

Note: 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!