A tiny (18.5kB gzip), zero dependency, JavaScript library to perform both synchronous and asynchronous OpenSSL RSA Encryption, Decryption, and Key Generation in both the Browser and Node.js.
🌐 Documentation: https://travistidwell.com/jsencrypt
📦 NPM Package: https://www.npmjs.com/package/jsencrypt
🚀 Interactive Demo: https://travistidwell.com/jsencrypt/demo
When choosing an RSA encryption library for JavaScript, you need a solution that's reliable, secure, and fits seamlessly into your development workflow. JSEncrypt delivers on all fronts.
JSEncrypt stands out by providing enterprise-grade RSA encryption capabilities without the complexity and security concerns that come with heavy dependencies.
- ⚡ Tiny & Fast - Just 18.5 kB gzipped - minimal impact on your bundle size.
- 🌐 Universal Compatibility - Works seamlessly in both Node.js server environments and browser applications
- 📦 Zero Dependencies - No external dependencies means better security posture and reduced bundle size
- ⚡ Flexible Execution - Supports both synchronous and asynchronous JavaScript patterns
- 🔒 OpenSSL Compatible - Direct support for PEM-formatted keys generated with OpenSSL
- 🛡️ Proven Security - Built on Tom Wu's battle-tested jsbn library without modifying core algorithms
- 🚀 Production Ready - Lightweight, well-tested, and used by thousands of developers worldwide
npm install jsencrypt
yarn add jsencrypt
Include JSEncrypt directly in your HTML:
<script src="https://cdn.jsdelivr.net/npm/jsencrypt@latest/bin/jsencrypt.min.js"></script>
import { JSEncrypt } from 'jsencrypt';
const JSEncrypt = require('jsencrypt');
// JSEncrypt is available globally when using CDN
const crypt = new JSEncrypt();
For the highest security, you'll need RSA key pairs to use JSEncrypt. Generate them using OpenSSL:
# Generate a 2048-bit private key
openssl genrsa -out private.pem 2048
# Extract the public key
openssl rsa -pubout -in private.pem -out public.pem
// Create JSEncrypt instance
const crypt = new JSEncrypt();
// Set your private key (for decryption)
crypt.setPrivateKey(`-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4f5wg5l2hKsTeNem/V41fGnJm6gOdrj8ym3rFkEjWT9u
U38KPhX7l3YXkLMfJj8sE3PUi0EaL6rN6rOUY8dq1fQhPhT1wfI6V8KQtQnq
1FKnNgQCVmQpCxK7qFR7Z+9MRWoJrPb8lZMmT1ELkKL6FBfkp3H3WcTl+BF0
XoZnLK0CfXfKzPJPm9jfKKE7dqnCsRiXYJbBwkNpQ5xo2lRKnNaH8GjPzJ4X
TZ5J7G6hDpXN1F3YzWZNVQRzfDfLB+w9FDaZ5kFhRc2PgB1Y8dNOhgK7RFJF
JDZhqBhSRnQ1YkLkQOnHq4Bz8l7YgRJkJHdIfTOO8l3YXkLMfJj8sE3PUi0E
qL6r9OOCzGJnVgQCVmQpCxK7qFR7Z+9MRWoJrPb8lZMmT1ELkKL6FBfkp3H3
...
-----END RSA PRIVATE KEY-----`);
// The public key is automatically derived from the private key
// Or you can set it explicitly:
// crypt.setPublicKey('-----BEGIN PUBLIC KEY-----...');
// Encrypt data
const originalText = 'Hello, World!';
const encrypted = crypt.encrypt(originalText);
// Decrypt data
const decrypted = crypt.decrypt(encrypted);
console.log('Original:', originalText);
console.log('Encrypted:', encrypted);
console.log('Decrypted:', decrypted);
console.log('Match:', originalText === decrypted); // true
- Public Key: Used for encryption. Safe to share publicly.
- Private Key: Used for decryption. Keep this secret!
const crypt = new JSEncrypt();
// For encryption only (using public key)
crypt.setPublicKey(publicKeyString);
const encrypted = crypt.encrypt('secret message');
// For decryption (requires private key)
crypt.setPrivateKey(privateKeyString);
const decrypted = crypt.decrypt(encrypted);
JSEncrypt supports two approaches for obtaining RSA keys: OpenSSL generation (recommended) and JavaScript generation (convenient but less secure).
For production applications and maximum security, generate keys using OpenSSL:
# Generate a 2048-bit private key (recommended minimum)
openssl genrsa -out private.pem 2048
# Generate a 4096-bit private key (higher security)
openssl genrsa -out private.pem 4096
# Extract the public key
openssl rsa -pubout -in private.pem -out public.pem
# View the private key
cat private.pem
# View the public key
cat public.pem
Why OpenSSL is more secure:
- Uses cryptographically secure random number generators
- Better entropy sources from the operating system
- Optimized and audited implementations
- Industry standard for key generation
JSEncrypt can generate keys directly in JavaScript, which is convenient for testing, demos, or non-critical applications:
// Create JSEncrypt instance
const crypt = new JSEncrypt();
// Generate a new key pair (default: 1024-bit)
const privateKey = crypt.getPrivateKey();
const publicKey = crypt.getPublicKey();
console.log('Private Key:', privateKey);
console.log('Public Key:', publicKey);
// You can also specify key size (512, 1024, 2048, 4096)
const crypt2048 = new JSEncrypt({ default_key_size: 2048 });
const strongerPrivateKey = crypt2048.getPrivateKey();
const strongerPublicKey = crypt2048.getPublicKey();
For better performance (especially with larger keys), use async generation:
// Asynchronous key generation (recommended for larger keys)
const crypt = new JSEncrypt({ default_key_size: 2048 });
crypt.getKey(() => {
const privateKey = crypt.getPrivateKey();
const publicKey = crypt.getPublicKey();
console.log('Generated private key:', privateKey);
console.log('Generated public key:', publicKey);
// Now you can use the keys
const encrypted = crypt.encrypt('Hello, World!');
const decrypted = crypt.decrypt(encrypted);
});
// 512-bit (fast but less secure - only for testing)
const crypt512 = new JSEncrypt({ default_key_size: 512 });
// 1024-bit (default - basic security)
const crypt1024 = new JSEncrypt({ default_key_size: 1024 });
// 2048-bit (recommended minimum for production)
const crypt2048 = new JSEncrypt({ default_key_size: 2048 });
// 4096-bit (high security but slower)
const crypt4096 = new JSEncrypt({ default_key_size: 4096 });
💡 Use Cases for JavaScript Generation:
- Rapid prototyping and testing
- Client-side demos and examples
- Educational purposes
- Non-critical applications
- When OpenSSL is not available
// Sign with the private key
const sign = new JSEncrypt();
sign.setPrivateKey(privateKey);
const signature = sign.signSha256(data);
// Verify with the public key
const verify = new JSEncrypt();
verify.setPublicKey(publicKey);
const verified = verify.verifySha256(data, signature);
// Encrypt with OAEP padding and SHA-256 hash
const encrypt = new JSEncrypt();
encrypt.setPublicKey(publicKey);
const encrypted = encrypt.encryptOAEP(data);
When using signatures, you can specify the hash type:
-
md2
,md5
,sha1
,sha224
,sha256
,sha384
,sha512
,ripemd160
For direct browser usage without a build system:
<!DOCTYPE html>
<html>
<head>
<title>JSEncrypt Example</title>
<script src="https://cdn.jsdelivr.net/npm/jsencrypt/bin/jsencrypt.min.js"></script>
</head>
<body>
<script>
const crypt = new JSEncrypt();
crypt.setPrivateKey(crypt.getPrivateKey());
// Use the library
const encrypted = crypt.encrypt('Hello World!');
const decrypted = crypt.decrypt(encrypted);
console.log('Original:', 'Hello World!');
console.log('Encrypted:', encrypted);
console.log('Decrypted:', decrypted);
</script>
</body>
</html>
For use within Node.js, you can use the following.
const JSEncrypt = require('jsencrypt');
const crypt = new JSEncrypt();
crypt.setPrivateKey(crypt.getPrivateKey());
// Use the library
const encrypted = crypt.encrypt('Hello World!');
const decrypted = crypt.decrypt(encrypted);
console.log('Original:', 'Hello World!');
console.log('Encrypted:', encrypted);
console.log('Decrypted:', decrypted);
# Run all tests (Node.js + Browser)
npm test
# Run only Node.js tests
npm run test:mocha
# Run only example validation tests
npm run test:examples
# Build the library
npm run build
# Build test bundle for browser testing
npm run build:test
Visit the test page to run browser-based tests:
-
Local development:
http://localhost:4000/test/
(when running Jekyll) - Online: https://travistidwell.com/jsencrypt/test/
For comprehensive documentation, examples, and API reference:
📖 Visit the Documentation Site
This library provides a simple JavaScript wrapper around Tom Wu's excellent jsbn library. The core cryptographic functions remain untouched, ensuring security and reliability.
JSEncrypt works with standard PEM-formatted RSA keys:
Private Key (PKCS#1):
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDHikastc8+I81zCg/qWW8dMr8mqvXQ3qbPAmu0RjxoZVI47tvs...
-----END RSA PRIVATE KEY-----
Public Key (PKCS#8):
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtN...
-----END PUBLIC KEY-----
The library translates PEM key components to jsbn library variables:
PEM Component | jsbn Variable |
---|---|
modulus | n |
public exponent | e |
private exponent | d |
prime1 | p |
prime2 | q |
exponent1 | dmp1 |
exponent2 | dmq1 |
coefficient | coeff |
Contributions are welcome! Please read our contributing guidelines and ensure all tests pass before submitting a pull request.
# Clone the repository
git clone https://github.com/travist/jsencrypt.git
cd jsencrypt
# Install dependencies
npm install
# Run tests
npm test
# Build the project
npm run build
This project is licensed under the MIT License - see the LICENSE.txt file for details.
- Tom Wu's jsbn library: http://www-cs-students.stanford.edu/~tjw/jsbn/
- RSA Key Breakdown: http://etherhack.co.uk/asymmetric/docs/rsa_key_breakdown.html
- RSA Algorithm Details: http://www.di-mgt.com.au/rsa_alg.html
- ASN.1 Key Structures: https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem
Made with ❤️ by Travis Tidwell