UUID Studio

RSA Key Pair Generator

Create RSA-OAEP PEM key pairs.

  • 🔒 No data stored or uploaded
  • âš¡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Hash, HMAC, AES-GCM/CBC + RSA-OAEP, codecs, JWT decoding, UUID v4, and secure random - all client-side. JWTs use Base64URL (three segments), not a single MIME Base64 block - use Decode JWT below, not raw Base64 decode.

About RSA Key Pair Generator

This generates a fresh RSA key pair in your browser: a private key you keep and a public key you can hand out. Key generation searches for two large random primes, so it is noticeably slower than other crypto operations - a few hundred milliseconds for 2048 bits, and several seconds for 4096.

2048 bits is the practical minimum today and remains appropriate for most uses. 3072 and 4096 buy a longer margin, at a cost that grows faster than the key size - RSA operations scale roughly with the cube of the modulus, so 4096-bit signing is several times slower than 2048. For new systems that are not constrained by an existing spec, elliptic-curve keys (Ed25519 or ECDSA P-256) give equivalent strength at a fraction of the size and cost.

The public exponent is 65537. It is large enough to avoid the attacks that affect e=3 and cheap to compute because it has only two set bits, and there is no good reason to change it.

Keys are emitted as PEM: the public key as SPKI (-----BEGIN PUBLIC KEY-----) and the private key as PKCS#8 (-----BEGIN PRIVATE KEY-----), which is what Web Crypto, Java and modern OpenSSL expect. If a tool demands the older PKCS#1 form (-----BEGIN RSA PRIVATE KEY-----), convert it rather than regenerating.

Generation happens locally and nothing is transmitted. Keys produced in a browser tab are ideal for development and testing; for a key that will protect production data, generate it with your own tooling in the environment where it will live.

How to use the RSA Key Pair Generator

  1. Choose a key size - 2048 for general use, 3072 or 4096 where you want a longer margin and can accept slower operations.
  2. Generate. Expect a short pause: finding two large primes is genuinely expensive work.
  3. Copy the public key to whoever needs to encrypt for you or verify your signatures.
  4. Store the private key somewhere secret. If a library rejects the format, convert between PKCS#8 and PKCS#1 with openssl rather than generating a new pair.

RSA Key Pair Generator in code

The same operation this tool performs, in the languages you are most likely to need it.

JavaScript (browser / Web Crypto)
// Generate a key pair
const kp = await crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([1, 0, 1]),   // 65537
    hash: "SHA-256",
  },
  true,
  ["encrypt", "decrypt"]
);

const ct = await crypto.subtle.encrypt(
  { name: "RSA-OAEP" }, kp.publicKey,
  new TextEncoder().encode("short secret")
);

const pt = await crypto.subtle.decrypt({ name: "RSA-OAEP" }, kp.privateKey, ct);
console.log(new TextDecoder().decode(pt));

// Export: Web Crypto uses SPKI for public keys, PKCS#8 for private.
const spki = await crypto.subtle.exportKey("spki", kp.publicKey);
Node.js
import { generateKeyPairSync, publicEncrypt, privateDecrypt, constants } from "node:crypto";

const { publicKey, privateKey } = generateKeyPairSync("rsa", {
  modulusLength: 2048,
  publicKeyEncoding: { type: "spki", format: "pem" },
  privateKeyEncoding: { type: "pkcs8", format: "pem" },
});

const opts = {
  padding: constants.RSA_PKCS1_OAEP_PADDING,
  oaepHash: "sha256",     // must match on both sides
};

const ct = publicEncrypt({ key: publicKey, ...opts }, Buffer.from("short secret"));
const pt = privateDecrypt({ key: privateKey, ...opts }, ct);
console.log(pt.toString());
Python (cryptography)
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization

private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()

pad = padding.OAEP(
    mgf=padding.MGF1(algorithm=hashes.SHA256()),
    algorithm=hashes.SHA256(),
    label=None,
)

ct = public_key.encrypt(b"short secret", pad)
print(private_key.decrypt(ct, pad))

pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption(),
)
OpenSSL
# Generate a 2048-bit key pair
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
openssl rsa -in private.pem -pubout -out public.pem

# Encrypt with OAEP + SHA-256 (defaults to SHA-1 without the pkeyopt!)
openssl pkeyutl -encrypt -pubin -inkey public.pem \
  -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
  -in plain.txt -out cipher.bin

# Decrypt
openssl pkeyutl -decrypt -inkey private.pem \
  -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
  -in cipher.bin

# Convert PKCS#1 -> PKCS#8 if a library rejects your key
openssl pkcs8 -topk8 -nocrypt -in pkcs1.pem -out pkcs8.pem
Hybrid encryption (for data of any size)
// This is how TLS, PGP and every real system encrypt large payloads:
// RSA protects a random AES key; AES protects the data.
const aesKey = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const payload = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv }, aesKey, new TextEncoder().encode(bigDocument)
);

// Wrap the 32-byte AES key with RSA - well under the size limit.
const raw = await crypto.subtle.exportKey("raw", aesKey);
const wrapped = await crypto.subtle.encrypt({ name: "RSA-OAEP" }, publicKey, raw);

// Send { wrapped, iv, payload }. The recipient unwraps with RSA,
// then decrypts the payload with AES.

When you need this

  • Creating a throwaway key pair for local development or a test suite.
  • Producing a key pair to exchange with a partner during integration work.
  • Generating a key to sign JWTs with RS256 rather than a shared HS256 secret.
  • Getting a correctly formatted PEM to test a parser or a deployment secret.

Common problems and what causes them

"Data too large for key size" / "message too long"
RSA cannot encrypt data longer than its key. With OAEP and SHA-256 the limit is the modulus size minus 66 bytes - 2048-bit key: 190 bytes; 3072-bit key: 318 bytes; 4096-bit key: 446 bytes. If you need to encrypt more than that, you do not want plain RSA; see hybrid encryption below.
Mixing OAEP and PKCS#1 v1.5 padding between the two sides
A ciphertext padded with OAEP cannot be decrypted as PKCS#1 v1.5 or vice versa - you get a decryption error or garbage. Both sides must agree on the padding scheme and, for OAEP, on the hash function. OAEP with SHA-256 is the right default; PKCS#1 v1.5 encryption is vulnerable to Bleichenbacher-style attacks and should only be used for compatibility.
PEM header mismatch: PKCS#1 vs PKCS#8 vs SPKI
A key starting "-----BEGIN RSA PRIVATE KEY-----" is PKCS#1; "-----BEGIN PRIVATE KEY-----" is PKCS#8; "-----BEGIN PUBLIC KEY-----" is SPKI. Libraries are picky: Web Crypto wants PKCS#8 and SPKI, OpenSSL will read all of them, and Java wants PKCS#8. Converting is a one-line openssl command, not a reason to regenerate the key.
Encrypting with the private key to 'sign'
Signing is a separate operation with its own padding (RSASSA-PKCS1-v1_5 or RSASSA-PSS), not 'encryption with the private key'. Use the sign/verify APIs; do not invert encrypt/decrypt.
Ciphertext encoding confusion
RSA output is exactly as many bytes as the modulus (256 bytes for a 2048-bit key), and is then usually Base64'd for transport. If your Base64 decodes to a length that is not the modulus size, the ciphertext is truncated or double-encoded.
Line endings and whitespace in a pasted PEM
PEM parsers expect the base64 body wrapped at 64 characters with the exact header and footer lines. A PEM pasted from a JSON string with literal \n sequences, or with the newlines stripped, will fail to parse - convert the escapes back to real newlines first.

FAQ

Why is generation so much slower than encrypting?
Because it has to find two large random primes, which means generating candidates and running primality tests until they pass. 2048 bits is usually a few hundred milliseconds; 4096 bits can take several seconds. Encryption afterwards is a single modular exponentiation and is fast.
Should I use RSA or an elliptic-curve key?
If nothing constrains you, prefer Ed25519 for signing or X25519 for key exchange: far smaller keys, much faster operations, and fewer ways to misuse them. Choose RSA when you need to interoperate with something that requires it - many enterprise systems, older TLS stacks, and specifications that predate EdDSA.
Why can't RSA encrypt my file or long string?
RSA can only encrypt data smaller than its key. With OAEP and SHA-256 the maximum is the modulus size minus 66 bytes - 2048-bit key: 190 bytes; 3072-bit key: 318 bytes; 4096-bit key: 446 bytes. Real systems never encrypt bulk data with RSA: they generate a random AES key, encrypt the data with AES, and use RSA only to encrypt that key. That is called hybrid encryption and there is a worked example in the code section above.
OAEP or PKCS#1 v1.5?
OAEP with SHA-256 for anything new. PKCS#1 v1.5 encryption padding is vulnerable to Bleichenbacher-style chosen-ciphertext attacks and survives only for compatibility with old systems. Whichever you pick, both sides must match exactly, including the OAEP hash.
How big should an RSA key be?
2048 bits is the practical minimum today and is fine for most purposes; 3072 or 4096 gives a longer margin. Note that RSA cost grows steeply - 4096-bit operations are several times slower than 2048 - and that modern systems increasingly prefer elliptic-curve keys (Ed25519, ECDSA P-256) for equivalent strength at far smaller sizes.
What is the public exponent 65537 and should I change it?
65537 (0x10001) is the standard public exponent: large enough to avoid the small-exponent attacks that affect e=3, and cheap to compute because it has only two set bits. Leave it alone unless a specification tells you otherwise.
Can I recover the public key from the private key?
Yes - a private key contains everything needed, and `openssl rsa -in private.pem -pubout` extracts it. The reverse is not possible, which is the entire point.
Is my private key safe to paste into this page?
The operations run in your browser through the Web Crypto API and nothing is uploaded. That said, the safest habit with a production private key is to not paste it into any web page at all - generate a throwaway key here for testing, and keep real keys in your own tooling.

Related reading