5.3 KiB
rsa
(no submodules)
Purpose
Provides a high-level rsa namespace object wrapping RSA cryptographic operations from crypto.subtle. Supports three algorithm variants — RSA-PSS, RSA-OAEP, and RSASSA-PKCS1-v1_5 — for signing/verification and asymmetric encryption/decryption. Keys are represented as standard DER byte arrays (SPKI for public keys, PKCS8 for private keys), which are universally portable across platforms and easy to store and transmit.
RSA is provided alongside the elliptic-curve engines for interoperability with legacy systems, PKI infrastructure, and protocols that require RSA (e.g., certain TLS cipher suites, JWT RSA algorithms, legacy JOSE). For new designs, Ed25519 and ECDH-X25519 are preferred.
Features
generateKeypair(algorithm, modulusLength?)— generates an RSA keypair; default 2048-bit modulus, configurable up to 4096 bitssign(algorithm, privateKey, message)— RSA-PSS or RSASSA-PKCS1-v1_5 signature generationverify(algorithm, publicKey, signature, message)— RSA signature verificationencrypt(publicKey, plaintext)— RSA-OAEP encryption (public-key encryption)decrypt(privateKey, ciphertext)— RSA-OAEP decryption- SHA-256 hash used for all operations
- RSA-PSS uses 32-byte salt length
- All methods guard with
assertWebCryptoAvailable() - Typed
BrowserCryptoErrorfor all failure paths
Usage: Basic Example
import { rsa } from "@suaveplan/crypto-browser/rsa/rsa";
// Generate and use RSA-PSS for signing
const { publicKey, privateKey } = await rsa.generateKeypair("RSA-PSS");
const message = new TextEncoder().encode("document to sign");
const signature = await rsa.sign("RSA-PSS", privateKey, message);
const valid = await rsa.verify("RSA-PSS", publicKey, signature, message);
console.log(valid); // true
Usage: Advanced Example
import { rsa, type RsaAlgorithm } from "@suaveplan/crypto-browser/rsa/rsa";
import { BrowserCryptoError } from "@suaveplan/crypto-browser/errors";
// RSA-OAEP for encrypting a small payload (e.g., a symmetric key)
async function wrapAesKey(
recipientPublicKey: Uint8Array,
aesKey: Uint8Array // must be <= ~190 bytes for RSA-2048
): Promise<Uint8Array> {
try {
return await rsa.encrypt(recipientPublicKey, aesKey);
} catch (err) {
if (err instanceof BrowserCryptoError) {
console.error(`Crypto failure: ${err.code}`);
}
throw err;
}
}
async function unwrapAesKey(
recipientPrivateKey: Uint8Array,
wrappedKey: Uint8Array
): Promise<Uint8Array> {
return await rsa.decrypt(recipientPrivateKey, wrappedKey);
}
// 4096-bit keypair for higher-security contexts
const { publicKey, privateKey } = await rsa.generateKeypair("RSA-OAEP", 4096);
API Reference
rsa.generateKeypair(algorithm, modulusLength?): Promise<{ publicKey, privateKey }>
Generates an RSA keypair.
| Parameter | Type | Default | Description |
|---|---|---|---|
algorithm |
RsaAlgorithm |
— | "RSA-PSS" | "RSA-OAEP" | "RSASSA-PKCS1-v1_5" |
modulusLength |
number |
2048 |
Key bit length (2048 or 4096 recommended) |
Returns: Promise<{ publicKey: Uint8Array; privateKey: Uint8Array }> — SPKI/PKCS8 DER bytes.
Throws: BrowserCryptoError — BROWSER_CRYPTO.KEY.GENERATION_FAILED.
rsa.sign(algorithm, privateKey, message): Promise<Uint8Array>
Signs a message. Use with "RSA-PSS" or "RSASSA-PKCS1-v1_5".
| Parameter | Type | Description |
|---|---|---|
algorithm |
RsaAlgorithm |
Must match keypair generation algorithm |
privateKey |
Uint8Array |
PKCS8 DER private key |
message |
Uint8Array |
Message to sign |
Returns: Promise<Uint8Array> — signature bytes.
Throws: BrowserCryptoError — BROWSER_CRYPTO.OPERATION.FAILED.
rsa.verify(algorithm, publicKey, signature, message): Promise<boolean>
| Parameter | Type | Description |
|---|---|---|
algorithm |
RsaAlgorithm |
Must match signing algorithm |
publicKey |
Uint8Array |
SPKI DER public key |
signature |
Uint8Array |
Signature bytes |
message |
Uint8Array |
Original message |
Returns: Promise<boolean>.
rsa.encrypt(publicKey, plaintext): Promise<Uint8Array>
RSA-OAEP encryption. For RSA-2048, plaintext must be ≤ 190 bytes (2048-bit modulus minus OAEP overhead).
rsa.decrypt(privateKey, ciphertext): Promise<Uint8Array>
RSA-OAEP decryption.
type RsaAlgorithm
"RSA-PSS" | "RSA-OAEP" | "RSASSA-PKCS1-v1_5"
Implementation Notes
All RSA operations use SHA-256 as the hash algorithm, which is the most widely supported and appropriate choice for 2048- and 4096-bit RSA. RSA-PSS uses a 32-byte (256-bit) salt, matching the hash output length, which is the PKCS#1v2.2 recommendation.
The encrypt() and decrypt() methods are hardcoded to RSA-OAEP — only RSA-OAEP provides semantic security for asymmetric encryption. RSA-PSS and RSASSA-PKCS1-v1_5 are signing-only algorithms and cannot be used with encrypt/decrypt.
Key generation for RSA-2048 typically takes 50–200 ms in crypto.subtle; RSA-4096 can take 500–2000 ms. This is significantly slower than elliptic-curve key generation (< 5 ms). All operations use await and do not block the main thread.