### Index
---
layout: default
title: Docs
nav_order: 2
has_children: true
permalink: /docs/
---
# Documentation
Welcome to the JSEncrypt documentation! Here you'll find everything you need to integrate RSA encryption into your JavaScript applications.
## Overview
JSEncrypt is a JavaScript library that provides a simple interface for RSA encryption and decryption using OpenSSL-compatible key formats. It's built on top of the proven [jsbn library](http://www-cs-students.stanford.edu/~tjw/jsbn/) by Tom Wu.
## What You'll Learn
- **[Getting Started](getting-started/)** - Install and set up JSEncrypt
- **[API Reference](api/)** - Complete API documentation
- **[Examples](examples/)** - Real-world usage examples
- **[Key Management](key-management/)** - Working with RSA keys
- **[Security Best Practices](security/)** - Keep your implementations secure
## Quick Navigation
New to JSEncrypt? Start with our [Getting Started Guide](getting-started/).
Looking for specific methods? Check the [API Reference](api/).
Want to see examples? Browse our [Examples](examples/) section.
---
## Need Help?
- 🐛 **Found a bug?** [Report it on GitHub](https://github.com/travist/jsencrypt/issues)
- 💡 **Have a question?** [Start a discussion](https://github.com/travist/jsencrypt/discussions)
- 📚 **Want to contribute?** See our [Contributing Guide](https://github.com/travist/jsencrypt/blob/master/CONTRIBUTING.md)
---
### Getting Started
---
layout: default
title: Getting Started
parent: Docs
nav_order: 1
permalink: /docs/getting-started/
aliases:
- /docs/getting-started.html
---
# Getting Started with JSEncrypt
{: .no_toc }
This guide will help you get up and running with JSEncrypt in just a few minutes.
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
---
## Installation
### Using npm
```bash
npm install jsencrypt
```
### Using yarn
```bash
yarn add jsencrypt
```
### Using CDN
Include JSEncrypt directly in your HTML:
```html
```
## Basic Usage
### 1. Import the Library
#### ES6 Modules
```javascript
import { JSEncrypt } from 'jsencrypt';
```
#### CommonJS
```javascript
const JSEncrypt = require('jsencrypt');
```
#### Browser Global
```javascript
// JSEncrypt is available globally when using CDN
const crypt = new JSEncrypt();
```
### 2. Create RSA Keys
You'll need RSA key pairs to use JSEncrypt. Generate them using OpenSSL:
```bash
# 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
```
### 3. Basic Encryption/Decryption
```javascript
// 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
```
## Key Concepts
### Public vs Private Keys
- **Public Key**: Used for **encryption**. Safe to share publicly.
- **Private Key**: Used for **decryption**. Keep this secret!
```javascript
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);
```
## Key Generation
JSEncrypt supports two approaches for obtaining RSA keys: **OpenSSL generation (recommended)** and **JavaScript generation (convenient but less secure)**.
### Option 1: OpenSSL Key Generation (Recommended)
For production applications and maximum security, generate keys using OpenSSL:
```bash
# 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
### Option 2: JavaScript Key Generation (Convenience)
JSEncrypt can generate keys directly in JavaScript, which is convenient for testing, demos, or non-critical applications:
```javascript
// 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();
```
#### Asynchronous Key Generation
For better performance (especially with larger keys), use async generation:
```javascript
// 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);
});
```
#### Different Key Sizes
```javascript
// 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 });
```
**⚠️ Security Note:** JavaScript key generation uses browser/Node.js random number generators which may have less entropy than dedicated cryptographic tools. For production applications handling sensitive data, prefer OpenSSL-generated keys.
**💡 Use Cases for JavaScript Generation:**
- Rapid prototyping and testing
- Client-side demos and examples
- Educational purposes
- Non-critical applications
- When OpenSSL is not available
### Key Size Limitations
RSA encryption has limitations based on key size:
- **1024-bit key**: Can encrypt up to 117 bytes
- **2048-bit key**: Can encrypt up to 245 bytes
- **4096-bit key**: Can encrypt up to 501 bytes
For larger data, use hybrid encryption (RSA + AES).
## Next Steps
Now that you have JSEncrypt working, explore these topics:
- **[API Reference](../api/)** - Complete method documentation
- **[Examples](../examples/)** - Real-world usage patterns
- **[Key Management](../key-management/)** - Advanced key handling
- **[Security Best Practices](../security/)** - Keep your app secure
---
## Troubleshooting
### Common Issues
**"Invalid key" error**
: Make sure your key is in PEM format and includes the BEGIN/END headers.
**"Message too long" error**
: Your message exceeds the key size limit. Use shorter messages or implement hybrid encryption.
**Encryption works but decryption fails**
: Ensure you're using the correct private key that corresponds to the public key used for encryption.
### Getting Help
If you're still having issues:
1. Check our [Examples](../examples/) for working code
2. Search [existing issues](https://github.com/travist/jsencrypt/issues) on GitHub
3. [Open a new issue](https://github.com/travist/jsencrypt/issues/new) with a minimal reproduction case
---
### Api
---
layout: default
title: API Reference
parent: Docs
nav_order: 2
permalink: /docs/api/
aliases:
- /docs/api.html
---
# API Reference
{: .no_toc }
Complete reference for all JSEncrypt methods and properties.
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
---
## Constructor
### `new JSEncrypt(options?)`
Creates a new JSEncrypt instance.
#### Parameters
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `options` | `Object` | `{}` | Configuration options |
| `options.default_key_size` | `number` | `1024` | Default key size for key generation |
#### Example
```javascript
// Default constructor
const crypt = new JSEncrypt();
// With custom key size
const crypt = new JSEncrypt({ default_key_size: 2048 });
```
---
## Key Management
### `setKey(key)`
{: .d-inline-block }
Alias
{: .label .label-yellow }
Sets either a private or public key. This is an alias for both `setPrivateKey()` and `setPublicKey()`.
#### Parameters
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `key` | `string` | PEM-formatted RSA key |
#### Example
```javascript
// Can be used with either key type
crypt.setKey(privateKeyPem);
crypt.setKey(publicKeyPem);
```
### `setPrivateKey(key)`
Sets the private key for decryption operations.
#### Parameters
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `key` | `string` | PEM-formatted RSA private key |
#### Returns
`void`
#### Example
```javascript
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4f5wg5l2hKsTeNem/V41fGnJm6gOdrj8ym3rFkEjWT9u
...
-----END RSA PRIVATE KEY-----`;
crypt.setPrivateKey(privateKey);
```
### `setPublicKey(key)`
Sets the public key for encryption operations.
#### Parameters
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `key` | `string` | PEM-formatted RSA public key |
#### Returns
`void`
#### Example
```javascript
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4f5wg5l2hKsTeNem
...
-----END PUBLIC KEY-----`;
crypt.setPublicKey(publicKey);
```
### `getPrivateKey()`
Returns the current private key in PEM format.
#### Returns
`string` - PEM-formatted private key
#### Example
```javascript
const privateKey = crypt.getPrivateKey();
console.log(privateKey);
```
### `getPublicKey()`
Returns the current public key in PEM format. If only a private key is set, this will derive and return the corresponding public key.
#### Returns
`string` - PEM-formatted public key
#### Example
```javascript
// After setting a private key
crypt.setPrivateKey(privateKey);
const publicKey = crypt.getPublicKey(); // Derived from private key
```
### `getKey(callback?)`
Generates a new RSA key pair.
#### Parameters
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `callback` | `function` | Optional callback for async generation |
#### Returns
- If `callback` provided: `void` (result passed to callback)
- If no callback: `Object` with `key` property
#### Example
```javascript
// Synchronous generation
const result = crypt.getKey();
console.log('Generated key');
// Asynchronous generation
crypt.getKey(() => {
console.log('Key generated asynchronously');
const privateKey = crypt.getPrivateKey();
const publicKey = crypt.getPublicKey();
});
```
---
## Encryption/Decryption
### `encrypt(text)`
Encrypts the given text using the current public key.
#### Parameters
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `text` | `string` | Text to encrypt |
#### Returns
`string | false` - Base64-encoded encrypted text, or `false` if encryption fails
#### Example
```javascript
crypt.setPublicKey(publicKey);
const encrypted = crypt.encrypt('Hello, World!');
if (encrypted) {
console.log('Encrypted:', encrypted);
} else {
console.log('Encryption failed');
}
```
#### Notes
- Requires a public key to be set
- Input length is limited by key size (see [Key Size Limitations](../getting-started/#key-size-limitations))
- Returns `false` if no key is set or encryption fails
### `decrypt(text)`
Decrypts the given encrypted text using the current private key.
#### Parameters
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `text` | `string` | Base64-encoded encrypted text |
#### Returns
`string | false` - Decrypted text, or `false` if decryption fails
#### Example
```javascript
crypt.setPrivateKey(privateKey);
const decrypted = crypt.decrypt(encryptedText);
if (decrypted) {
console.log('Decrypted:', decrypted);
} else {
console.log('Decryption failed');
}
```
#### Notes
- Requires a private key to be set
- Returns `false` if no key is set, wrong key is used, or decryption fails
---
## Signing/Verification
### `sign(text, digestMethod, digestEncoding)`
Signs the given text using the private key.
#### Parameters
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `text` | `string` | - | Text to sign |
| `digestMethod` | `string` | `'sha256'` | Hash algorithm |
| `digestEncoding` | `string` | `'base64'` | Encoding for the signature |
#### Returns
`string | false` - Signature, or `false` if signing fails
#### Example
```javascript
crypt.setPrivateKey(privateKey);
const signature = crypt.sign('message to sign');
console.log('Signature:', signature);
```
### `verify(text, signature, digestMethod)`
Verifies a signature using the public key.
#### Parameters
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `text` | `string` | - | Original text |
| `signature` | `string` | - | Signature to verify |
| `digestMethod` | `string` | `'sha256'` | Hash algorithm |
#### Returns
`boolean` - `true` if signature is valid, `false` otherwise
#### Example
```javascript
crypt.setPublicKey(publicKey);
const isValid = crypt.verify('message to sign', signature);
console.log('Signature valid:', isValid);
```
---
## Utility Methods
### `getKeySize()`
Returns the size of the current key in bits.
#### Returns
`number` - Key size in bits
#### Example
```javascript
crypt.setPrivateKey(privateKey);
const keySize = crypt.getKeySize();
console.log('Key size:', keySize, 'bits');
```
### `getMaxMessageSize()`
Returns the maximum message size that can be encrypted with the current key.
#### Returns
`number` - Maximum message size in bytes
#### Example
```javascript
crypt.setPublicKey(publicKey);
const maxSize = crypt.getMaxMessageSize();
console.log('Max message size:', maxSize, 'bytes');
```
---
## Error Handling
All methods return `false` when they fail. Common failure scenarios:
- **No key set**: Attempting encryption/decryption without setting appropriate keys
- **Invalid key format**: Malformed PEM keys
- **Message too long**: Exceeding key size limitations
- **Wrong key**: Using incorrect key for decryption
- **Corruption**: Tampered encrypted data
### Best Practices
Always check return values:
```javascript
const encrypted = crypt.encrypt(message);
if (!encrypted) {
throw new Error('Encryption failed');
}
const decrypted = crypt.decrypt(encrypted);
if (!decrypted) {
throw new Error('Decryption failed');
}
```
---
## Type Definitions
For TypeScript users, JSEncrypt includes type definitions:
```typescript
interface JSEncryptOptions {
default_key_size?: number;
}
declare class JSEncrypt {
constructor(options?: JSEncryptOptions);
setKey(key: string): void;
setPrivateKey(key: string): void;
setPublicKey(key: string): void;
getPrivateKey(): string;
getPublicKey(): string;
getKey(callback?: () => void): any;
encrypt(text: string): string | false;
decrypt(text: string): string | false;
sign(text: string, digestMethod?: string, digestEncoding?: string): string | false;
verify(text: string, signature: string, digestMethod?: string): boolean;
getKeySize(): number;
getMaxMessageSize(): number;
}
```
---
### Examples
---
layout: default
title: Examples
parent: Docs
nav_order: 3
permalink: /docs/examples/
aliases:
- /docs/examples.html
---
# Examples
{: .no_toc }
Real-world examples showing how to use JSEncrypt for common encryption scenarios.
{: .fs-6 .fw-300 }
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
---
## Basic Encryption/Decryption
### Simple Text Encryption
```javascript
import { JSEncrypt } from 'jsencrypt';
// Initialize JSEncrypt
const crypt = new JSEncrypt();
// Set your RSA key pair
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA...
-----END RSA PRIVATE KEY-----`;
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----`;
crypt.setPrivateKey(privateKey);
crypt.setPublicKey(publicKey);
// Encrypt sensitive data
const message = "This is a secret message";
const encrypted = crypt.encrypt(message);
console.log('Encrypted:', encrypted);
// Decrypt the message
const decrypted = crypt.decrypt(encrypted);
console.log('Decrypted:', decrypted); // "This is a secret message"
```
### Encrypting User Credentials
```javascript
import { JSEncrypt } from 'jsencrypt';
function encryptCredentials(username, password, publicKey) {
const crypt = new JSEncrypt();
crypt.setPublicKey(publicKey);
// Create credentials object
const credentials = JSON.stringify({
username: username,
password: password,
timestamp: Date.now()
});
// Encrypt the credentials
const encrypted = crypt.encrypt(credentials);
return encrypted;
}
// Usage
const publicKey = `-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----`;
const encryptedCreds = encryptCredentials('john.doe', 'myPassword123', publicKey);
// Send encrypted credentials to server
fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ encryptedCredentials: encryptedCreds })
});
```
---
## SHA-256 Digital Signatures
### Using the Convenience Methods
JSEncrypt provides convenient `signSha256()` and `verifySha256()` methods that automatically handle SHA-256 hashing for you.
```javascript
import { JSEncrypt } from 'jsencrypt';
// Initialize with your key pair
const crypt = new JSEncrypt();
crypt.setPrivateKey(privateKey);
crypt.setPublicKey(publicKey);
// Simple message signing with SHA-256
const message = "Important data to sign";
const signature = crypt.signSha256(message);
console.log('Signature:', signature);
const isValid = crypt.verifySha256(message, signature);
console.log('Signature valid:', isValid); // true
```
### API Token Validation
```
/* Detailed source-code truncated for AI context efficiency. */
```
### Message Integrity Verification
```
/* Detailed source-code truncated for AI context efficiency. */
```
### Simple JWT Implementation
Here's a straightforward JWT implementation using the `signSha256` and `verifySha256` methods:
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## JWT Token Validation with Public Key
### Validating JWT Tokens with RSA Signatures / Public Key
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## Secure API Communication
### Client-Server Encrypted Communication
```javascript
// Client-side encryption
class SecureAPIClient {
constructor(serverPublicKey, clientPrivateKey) {
this.serverPublicKey = serverPublicKey;
this.clientPrivateKey = clientPrivateKey;
this.encryptor = new JSEncrypt();
this.decryptor = new JSEncrypt();
this.encryptor.setPublicKey(serverPublicKey);
this.decryptor.setPrivateKey(clientPrivateKey);
}
async secureRequest(endpoint, data) {
// Encrypt the request data
const encryptedData = this.encryptor.encrypt(JSON.stringify(data));
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Encrypted': 'true'
},
body: JSON.stringify({ encrypted: encryptedData })
});
const result = await response.json();
// Decrypt the response
if (result.encrypted) {
const decryptedResponse = this.decryptor.decrypt(result.encrypted);
return JSON.parse(decryptedResponse);
}
return result;
}
}
// Usage
const client = new SecureAPIClient(serverPublicKey, clientPrivateKey);
const userData = await client.secureRequest('/api/user/profile', {
userId: 12345,
fields: ['name', 'email', 'preferences']
});
```
### Server-side Decryption (Node.js)
```javascript
// Server-side (Node.js with Express)
const express = require('express');
const JSEncrypt = require('jsencrypt');
const app = express();
app.use(express.json());
const serverPrivateKey = `-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----`;
const serverPublicKey = `-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----`;
const decryptor = new JSEncrypt();
const encryptor = new JSEncrypt();
decryptor.setPrivateKey(serverPrivateKey);
encryptor.setPublicKey(serverPublicKey);
app.post('/api/user/profile', (req, res) => {
try {
// Decrypt incoming data
const encryptedData = req.body.encrypted;
const decryptedData = decryptor.decrypt(encryptedData);
const requestData = JSON.parse(decryptedData);
// Process the request
const userProfile = getUserProfile(requestData.userId, requestData.fields);
// Encrypt the response
const encryptedResponse = encryptor.encrypt(JSON.stringify(userProfile));
res.json({ encrypted: encryptedResponse });
} catch (error) {
res.status(400).json({ error: 'Decryption failed' });
}
});
```
---
## Digital Document Signing
### Document Integrity and Authentication
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## Secure File Upload
### Encrypting Files Before Upload
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## License Key Generation and Validation
### Software License Management
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## Browser Storage Encryption
### Encrypting Sensitive Data in localStorage
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## Key Generation and Management
### Generating RSA Key Pairs
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## Error Handling and Best Practices
### Robust Encryption with Error Handling
```
/* Detailed source-code truncated for AI context efficiency. */
```
---
## Security Considerations
### Best Practices for Production Use
```
/* Detailed source-code truncated for AI context efficiency. */
```
These examples demonstrate practical, real-world applications of the JSEncrypt library. Remember to:
1. **Never expose private keys** in client-side code
2. **Use HTTPS** for all communications
3. **Validate input data** before encryption
4. **Handle errors gracefully**
5. **Keep keys secure** and rotate them regularly
6. **Consider key size** (minimum 2048 bits for RSA)
7. **Use proper random number generation** for nonces and salts
---
### Key Management
---
layout: default
title: Key Management
parent: Docs
nav_order: 5
permalink: /docs/key-management/
---
# Key Management
{: .fs-9 }
Comprehensive guide to managing RSA keys with JSEncrypt
{: .fs-6 .fw-300 }
---
## Overview
Proper key management is crucial for maintaining the security of your RSA encryption implementation. This guide covers best practices for generating, storing, and using RSA keys with JSEncrypt.
## Key Generation Methods
### OpenSSL Generation (Recommended)
For production applications, generate keys using OpenSSL for maximum security:
```bash
# Generate 2048-bit private key (minimum recommended)
openssl genrsa -out private.pem 2048
# Generate 4096-bit private key (higher security)
openssl genrsa -out private.pem 4096
# Extract public key
openssl rsa -pubout -in private.pem -out public.pem
# Generate encrypted private key (password protected)
openssl genrsa -aes256 -out private_encrypted.pem 2048
```
### JSEncrypt Generation (Development/Testing)
For development, testing, or client-side applications:
```javascript
import { JSEncrypt } from 'jsencrypt';
// Generate key pair synchronously
const crypt = new JSEncrypt({ default_key_size: 2048 });
const privateKey = crypt.getPrivateKey();
const publicKey = crypt.getPublicKey();
// Generate key pair asynchronously (recommended for larger keys)
const cryptAsync = new JSEncrypt({ default_key_size: 2048 });
cryptAsync.getKey(() => {
const privateKey = cryptAsync.getPrivateKey();
const publicKey = cryptAsync.getPublicKey();
// Keys are ready to use
});
```
## Key Formats
### PEM Format (Standard)
JSEncrypt supports standard PEM-formatted keys:
**Private Key (PKCS#1):**
```
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4f5wg5l2hKsTeNem/V41fGnJm6gOdrj8ym3rFkEjWT9u...
-----END RSA PRIVATE KEY-----
```
**Public Key (PKCS#8):**
```
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDw...
-----END PUBLIC KEY-----
```
### Key Components
RSA keys contain several mathematical components:
| Component | Description | JSEncrypt Property |
|-----------|-------------|-------------------|
| n | Modulus | `getKey().n` |
| e | Public exponent | `getKey().e` |
| d | Private exponent | `getKey().d` |
| p | Prime factor 1 | `getKey().p` |
| q | Prime factor 2 | `getKey().q` |
| dmp1 | d mod (p-1) | `getKey().dmp1` |
| dmq1 | d mod (q-1) | `getKey().dmq1` |
| coeff | Coefficient | `getKey().coeff` |
## Working with Keys
### Loading Existing Keys
```javascript
import { JSEncrypt } from 'jsencrypt';
const crypt = new JSEncrypt();
// Load private key (enables both encryption and decryption)
crypt.setPrivateKey(`-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA...
-----END RSA PRIVATE KEY-----`);
// Load public key only (encryption only)
crypt.setPublicKey(`-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD...
-----END PUBLIC KEY-----`);
```
### Extracting Keys
```javascript
// Get keys as PEM strings
const privateKeyPEM = crypt.getPrivateKey();
const publicKeyPEM = crypt.getPublicKey();
// Get keys as base64 (without headers)
const privateKeyB64 = crypt.getPrivateKeyB64();
const publicKeyB64 = crypt.getPublicKeyB64();
// Get key object for advanced operations
const keyObject = crypt.getKey();
console.log('Key size:', keyObject.n.bitLength());
```
### Key Validation
```javascript
function validateKey(crypt) {
const key = crypt.getKey();
if (!key) {
throw new Error('No key loaded');
}
// Check key size
const keySize = key.n.bitLength();
if (keySize < 1024) {
console.warn(`Key size ${keySize} is below recommended minimum (2048)`);
}
// Test encryption/decryption if private key is available
if (key.d) {
const testMessage = 'test';
const encrypted = crypt.encrypt(testMessage);
const decrypted = crypt.decrypt(encrypted);
if (testMessage !== decrypted) {
throw new Error('Key validation failed: encryption/decryption mismatch');
}
}
return true;
}
```
## Troubleshooting
### Common Key Issues
**1. Invalid Key Format**
```javascript
// Ensure proper PEM headers and line breaks
const invalidKey = "MIIEowIBAAKCAQEA..."; // Missing headers
const validKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA...
-----END RSA PRIVATE KEY-----`;
```
**2. Key Size Problems**
```javascript
// Check key size
const keySize = crypt.getKey().n.bitLength();
if (keySize < 2048) {
console.warn('Key size too small for production use');
}
```
**3. Mixed Key Types**
```javascript
// Don't mix different key types
// Wrong:
crypt.setPublicKey(somePrivateKey);
// Correct:
crypt.setPrivateKey(privateKey); // Sets both private and derives public
// OR
crypt.setPublicKey(publicKey); // Sets only public key
```
### Key Compatibility
```javascript
// Test key compatibility
function testKeyCompatibility(privateKey, publicKey) {
const sender = new JSEncrypt();
const receiver = new JSEncrypt();
sender.setPublicKey(publicKey);
receiver.setPrivateKey(privateKey);
const testData = 'compatibility test';
const encrypted = sender.encrypt(testData);
const decrypted = receiver.decrypt(encrypted);
return testData === decrypted;
}
```
## Security Considerations
- **Never expose private keys** in client-side code or logs
- **Use strong key sizes** (minimum 2048-bit for production)
- **Implement key rotation** for long-running applications
- **Validate key integrity** before use
- **Use encrypted storage** for sensitive keys
- **Monitor key usage** and access patterns
---
## Next Steps
- Review [Security Best Practices](../security/) for comprehensive security guidance
- Check the [API Reference](../api/) for detailed method documentation
- Explore [Examples](../examples/) for practical implementation patterns
---
### Security
---
layout: default
title: Security Best Practices
parent: Docs
nav_order: 6
permalink: /docs/security/
---
# Security Best Practices
{: .fs-9 }
Essential security guidelines for implementing RSA encryption with JSEncrypt
{: .fs-6 .fw-300 }
---
## Overview
Security is paramount when implementing RSA encryption. This guide provides comprehensive security best practices to ensure your JSEncrypt implementation remains secure against common threats and vulnerabilities.
## Key Security Fundamentals
### Key Generation Security
**✅ Do:**
- Use OpenSSL for production key generation
- Generate keys with minimum 2048-bit size (4096-bit preferred)
- Use cryptographically secure random number generators
- Generate keys in secure environments
```bash
# Secure key generation with OpenSSL
openssl genrsa -out private.pem 4096
# Generate password-protected keys for additional security
openssl genrsa -aes256 -out private_protected.pem 4096
```
**❌ Don't:**
- Use JavaScript key generation for production (except specific use cases)
- Generate keys smaller than 2048 bits
- Reuse the same key pair across multiple applications
- Generate keys on untrusted machines
### Key Storage Security
**✅ Secure Storage Practices:**
```javascript
// Server-side (Node.js)
const fs = require('fs');
const path = require('path');
// Store keys outside web root
const KEYS_DIR = process.env.KEYS_DIR || '/secure/keys';
const privateKey = fs.readFileSync(
path.join(KEYS_DIR, 'private.pem'),
{ encoding: 'utf8', mode: 0o600 } // Restrict file permissions
);
// Use environment variables
const keyPath = process.env.PRIVATE_KEY_PATH;
if (!keyPath) {
throw new Error('PRIVATE_KEY_PATH environment variable not set');
}
```
**❌ Insecure Storage:**
```javascript
// Never do this:
const privateKey = "-----BEGIN RSA PRIVATE KEY-----..."; // Hardcoded in source
localStorage.setItem('privateKey', privateKey); // Client-side storage
const key = await fetch('/api/private-key'); // Exposing via API
```
## Data Protection
### Input Validation and Sanitization
```javascript
function secureEncrypt(data, crypt) {
// Validate input
if (typeof data !== 'string') {
throw new Error('Data must be a string');
}
// Check data length (RSA has size limits)
const keySize = crypt.getKey().n.bitLength();
const maxLength = Math.floor(keySize / 8) - 11; // PKCS#1 padding overhead
if (data.length > maxLength) {
throw new Error(`Data too long. Maximum length: ${maxLength} bytes`);
}
// Validate key is loaded
if (!crypt.getKey()) {
throw new Error('No encryption key loaded');
}
return crypt.encrypt(data);
}
```
### Secure Data Handling
```javascript
class SecureDataHandler {
constructor(privateKey) {
this.crypt = new JSEncrypt();
this.crypt.setPrivateKey(privateKey);
}
// Secure encryption with validation
encrypt(plaintext) {
if (!plaintext || typeof plaintext !== 'string') {
throw new Error('Invalid plaintext data');
}
const encrypted = this.crypt.encrypt(plaintext);
if (!encrypted) {
throw new Error('Encryption failed');
}
return encrypted;
}
// Secure decryption with validation
decrypt(ciphertext) {
if (!ciphertext || typeof ciphertext !== 'string') {
throw new Error('Invalid ciphertext data');
}
const decrypted = this.crypt.decrypt(ciphertext);
if (decrypted === false) {
throw new Error('Decryption failed - invalid ciphertext or key');
}
return decrypted;
}
// Clear sensitive data from memory
destroy() {
this.crypt = null;
}
}
```
## Authentication and Signatures
### Digital Signatures
```javascript
import { JSEncrypt } from 'jsencrypt';
import { sha256 } from 'crypto-hash'; // Or your preferred hash library
class SecureSignature {
constructor(privateKey, publicKey) {
this.signer = new JSEncrypt();
this.verifier = new JSEncrypt();
this.signer.setPrivateKey(privateKey);
this.verifier.setPublicKey(publicKey);
}
// Sign data with SHA-256 hashing
async signData(data) {
// Hash the data first
const hash = await sha256(data);
// Sign the hash
const signature = this.signer.sign(hash, 'sha256');
if (!signature) {
throw new Error('Signature generation failed');
}
return {
data: data,
signature: signature,
algorithm: 'SHA256withRSA',
timestamp: new Date().toISOString()
};
}
// Verify signature
async verifySignature(signedData) {
const { data, signature, algorithm } = signedData;
if (algorithm !== 'SHA256withRSA') {
throw new Error('Unsupported signature algorithm');
}
// Hash the data
const hash = await sha256(data);
// Verify signature
return this.verifier.verify(hash, signature, 'sha256');
}
}
```
### SHA-256 Convenience Methods
```javascript
// Using JSEncrypt's built-in SHA-256 methods (secure)
const crypt = new JSEncrypt();
crypt.setPrivateKey(privateKey);
// Sign with SHA-256
const message = "Important document content";
const signature = crypt.signSha256(message);
// Verify signature
const isValid = crypt.verifySha256(message, signature);
if (!isValid) {
throw new Error('Signature verification failed');
}
```
## Network Security
### Secure Communication
```javascript
// Example: Secure API communication
class SecureAPI {
constructor(publicKey, privateKey) {
this.encryptor = new JSEncrypt();
this.decryptor = new JSEncrypt();
this.encryptor.setPublicKey(publicKey);
this.decryptor.setPrivateKey(privateKey);
}
async sendSecureRequest(endpoint, data) {
// Encrypt sensitive data
const encryptedData = this.encryptor.encrypt(JSON.stringify(data));
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Encryption': 'RSA-OAEP'
},
body: JSON.stringify({ encrypted: encryptedData })
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
// Decrypt response if encrypted
if (result.encrypted) {
const decrypted = this.decryptor.decrypt(result.encrypted);
return JSON.parse(decrypted);
}
return result;
}
}
```
### HTTPS and Transport Security
```javascript
// Always use HTTPS in production
const secureEndpoint = 'https://api.example.com/secure';
// Never: const insecureEndpoint = 'http://api.example.com/secure';
// Validate SSL certificates
const response = await fetch(secureEndpoint, {
headers: {
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains'
}
});
```
## Error Handling and Logging
### Secure Error Handling
```
/* Detailed source-code truncated for AI context efficiency. */
```
### Safe Logging Practices
```javascript
// ✅ Safe logging
logger.info('Encryption successful', {
operation: 'encrypt',
keySize: crypt.getKey().n.bitLength(),
timestamp: new Date().toISOString()
});
// ❌ Dangerous logging
logger.info('Encrypting data', { data: sensitiveData }); // Exposes data
logger.debug('Using key', { privateKey: privateKey }); // Exposes key
```
## Memory and Resource Security
### Secure Memory Handling
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Input Validation and Sanitization
### Comprehensive Input Validation
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Production Deployment Security
### Environment Configuration
```javascript
// production-config.js
module.exports = {
// Security headers
security: {
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
},
// Key management
encryption: {
keyRotationInterval: 24 * 60 * 60 * 1000, // 24 hours
minKeySize: 2048,
preferredKeySize: 4096,
keyStoragePath: process.env.KEY_STORAGE_PATH,
backupKeyPath: process.env.BACKUP_KEY_PATH
},
// Monitoring
logging: {
level: 'info',
auditEncryption: true,
auditDecryption: true,
auditKeyAccess: true
}
};
```
### Security Monitoring
```javascript
class SecurityMonitor {
constructor(config) {
this.config = config;
this.metrics = {
encryptionCount: 0,
decryptionCount: 0,
failureCount: 0,
keyAccessCount: 0
};
}
logEncryption(success, keySize) {
this.metrics.encryptionCount++;
if (!success) {
this.metrics.failureCount++;
this.alertSecurityTeam('encryption_failure', {
timestamp: new Date().toISOString(),
keySize: keySize
});
}
}
logKeyAccess(keyId, operation) {
this.metrics.keyAccessCount++;
// Log key access for audit
console.log(JSON.stringify({
event: 'key_access',
keyId: keyId,
operation: operation,
timestamp: new Date().toISOString(),
source: this.getRequestSource()
}));
}
alertSecurityTeam(event, details) {
// Implement your security alerting system
console.error('SECURITY ALERT:', event, details);
}
getRequestSource() {
// Implement request source tracking
return process.env.NODE_ENV || 'unknown';
}
getMetrics() {
return { ...this.metrics };
}
}
```
## Security Checklist
### Pre-Production Checklist
- [ ] **Key Generation**: Using OpenSSL with 2048+ bit keys
- [ ] **Key Storage**: Keys stored securely outside web root
- [ ] **Environment Variables**: Sensitive configuration in env vars
- [ ] **Input Validation**: All inputs validated and sanitized
- [ ] **Error Handling**: No sensitive data in error messages
- [ ] **Logging**: Security events logged, sensitive data excluded
- [ ] **HTTPS**: All communication over HTTPS in production
- [ ] **Memory Management**: Sensitive data cleared from memory
- [ ] **Key Rotation**: Key rotation strategy implemented
- [ ] **Monitoring**: Security monitoring and alerting in place
### Runtime Security Monitoring
- [ ] **Failed Decryption Attempts**: Monitor and alert on failures
- [ ] **Key Access Patterns**: Log all key access attempts
- [ ] **Performance Anomalies**: Monitor for unusual patterns
- [ ] **Error Rates**: Track encryption/decryption error rates
- [ ] **Key Age**: Monitor key age and rotation schedules
---
## Common Security Pitfalls
### What NOT to Do
```javascript
// ❌ Never hardcode keys
const PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----...";
// ❌ Never log sensitive data
console.log('Decrypted data:', decryptedPassword);
// ❌ Never expose keys in client-side code
window.privateKey = getPrivateKey();
// ❌ Never ignore encryption failures
const encrypted = crypt.encrypt(data);
// No check if encryption succeeded
// ❌ Never use weak key sizes
const weakCrypt = new JSEncrypt({ default_key_size: 512 });
```
---
## Additional Resources
- [OWASP Cryptographic Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html)
- [NIST Cryptographic Standards](https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines)
- [Key Management Best Practices](../key-management/)
- [JSEncrypt API Reference](../api/)
---