UUID Studio

RSA Encrypt

RSA-OAEP encryption with your public key.

  • 🔒 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 Encrypt

RSA encryption is asymmetric: the public key encrypts and only the matching private key can decrypt. That asymmetry is what lets you publish the encrypting key freely - anyone can send you something confidential without any prior shared secret, which symmetric ciphers like AES cannot do.

The catch, and the reason most people end up on a page like this, is size. RSA operates on numbers smaller than its modulus, so a 2048-bit key can encrypt at most 190 bytes when using OAEP with SHA-256. It is a key-transport mechanism, not a bulk cipher.

The padding scheme is not optional decoration. Textbook RSA is deterministic and trivially attackable; OAEP adds randomness and structure so that encrypting the same message twice gives different ciphertexts and chosen-ciphertext attacks are prevented. Use OAEP with SHA-256 unless an existing system forces PKCS#1 v1.5 on you.

For anything larger than the size limit, use hybrid encryption: generate a random AES key, encrypt the payload with AES-GCM, and encrypt only the AES key with RSA. That is exactly what TLS and PGP do, and there is a complete example in the code section below.

Encryption here happens in your browser via the Web Crypto API - keys and plaintext are never uploaded.

How to use the RSA Encrypt

  1. Paste the recipient's RSA public key in PEM form, beginning -----BEGIN PUBLIC KEY-----.
  2. Enter the plaintext. Keep it under the size limit for the key - 190 bytes for a 2048-bit key with OAEP/SHA-256.
  3. Encrypt. The ciphertext is exactly as long as the modulus (256 bytes for a 2048-bit key) and is shown Base64-encoded.
  4. Send the Base64 ciphertext to the holder of the private key, and tell them the padding scheme and hash you used.

Examples

  • Short message
    hello

RSA Encrypt 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

  • Encrypting a short secret - an API key, a symmetric key, a one-time token - for a recipient whose public key you have.
  • Testing that a public key you were given actually works before wiring it into a deployment.
  • Producing a test ciphertext so a counterparty can verify their decryption path.
  • Confirming whether a mismatch is caused by padding, by encoding, or by the wrong key.

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 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.
What key format?
SPKI PEM public key (BEGIN PUBLIC KEY).

Related reading