Encryption / Hash

RSA Encrypt / Decrypt

Generate RSA key pairs and encrypt with public key, decrypt with private key.

Keys are exported in JWK (JSON Web Key) format for use in encryption/decryption.

What is RSA Encryption?

RSA is an asymmetric encryption algorithm using public/private key pairs for secure data encryption and digital signatures.

Features

  • Key Generation: Generate RSA key pairs
  • Encrypt/Decrypt: Public key encryption, private key decryption
  • Sign/Verify: Digital signature support

Use Cases

  • Secure data transmission
  • Digital signatures
  • Key exchange

Generates a 2048- or 4096-bit RSA key pair as JWK JSON, encrypts short UTF-8 text with the public key under RSA-OAEP and SHA-256, then decrypts the Base64 result with the private key, all inside the browser. Useful for proving that a Java, Node or OpenSSL backend opens the same ciphertext, since OAEP here carries keys and tokens rather than files.

n and e set the payload budget, not the dropdown

The exported key is JSON with six fields: kty, n, e, alg (RSA-OAEP-256), key_ops and ext. n is the modulus as an unpadded Base64URL big-endian integer: 342 characters at 2048 bits, decoding to 256 bytes, and 683 characters at 4096 bits, 512 bytes. e is AQAB, the bytes 01 00 01, which is the 65537 the generator hardcodes. Before encrypting, the tool decodes n and subtracts 66 from its byte length, so the ceiling follows the key you paste rather than the dropdown: 190 bytes at 2048 bits, 446 at 4096, and 318 for a 3072-bit JWK brought from elsewhere. A private JWK pasted into the encrypt tab is refused, because it carries d and is imported with the encrypt usage, which Web Crypto rejects.

The hash inside OAEP is why other tools fail

Keys are imported as RSA-OAEP with SHA-256, and Web Crypto runs MGF1 with that same hash. OAEP padding costs 2 x 32 + 2 = 66 bytes, which is why 190 of the 256 bytes survive at 2048 bits; PKCS#1 v1.5 spends 11 bytes and SHA-1 OAEP 42, so ciphertexts from those schemes are never interchangeable with this one. OpenSSL defaults rsa_oaep_md to SHA-1 and answers a ciphertext made here with oaep decoding error until you pass -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256. Libraries that pair SHA-256 OAEP with an SHA-1 MGF1 need the same alignment. On failure the decrypt tab shows one generic message, identical for a wrong key, a truncated paste and a padding mismatch, so check the parameters before blaming the key.

One block, one Base64 string, and no signature tab

OAEP encrypts a single block. The output is exactly the modulus width, 256 bytes at 2048 bits or 512 at 4096, whatever the text length, so its Base64 is always 344 characters ending == or 684 ending =; shortening the plaintext only touches that padding. Decryption strips whitespace first, so re-wrapped lines are fine, but it decodes with atob, which rejects the - and _ of Base64URL that JWTs and the JWK fields themselves use. The page has three tabs and none of them signs: RSA-OAEP cannot produce a signature, so RS256 or PS256 tokens need RSASSA-PKCS1-v1_5 or RSA-PSS elsewhere, and a ciphertext from here is not a JWT segment.

Worked example

Encrypting 19 bytes under a 2048-bit key

Input
DevToolbox RSA demo
Output
DM+BBxC+QKvf7g6xVwqfN+LMoSmBF9Glkvgqc/6DHbyHnnSePYtZEir9u1qbUkBANJxqRa80pmQC/LeB++OS8h72D+gqYg9udZzAmezxbt/X2iFWlRAMpgpy77/KMbS753PZIoXlqP/id31q5AnPC3SCd3i8OiZGmvpEsM7RrdQW4ZVpzzU/GJFvCRXO0x236adM6OyrjRsVwajdal5BdroAYeceqUrUTt/42ZfCrsecyP70z1dkiXnLeXEHPuKTvn7ksDNC1pB188aXTWwf7E57x50kBrH9kbQzcFDpQthYBXRTk9KJXGtP0aMRXgvmA0+P06jMYBjYBXf7JaOwjw==

At 2048 bits every OAEP ciphertext is 256 bytes, so this Base64 is 344 characters ending in == no matter how short the text is; 66 of those bytes are padding, and a 191-byte input throws instead. OAEP also draws a fresh random seed, so a second click returns a different string of exactly the same length that decrypts to the same sentence.

Limits and pitfalls

  • Key generation offers 2048 and 4096 bits only, with no 3072 option, and the key boxes accept JWK JSON exclusively: a PEM block, an OpenSSH line or a DER file fails at JSON.parse and shows the invalid-key message.
  • A 2048-bit key carries at most 190 bytes of plaintext and a 4096-bit key 446; the check counts UTF-8 bytes, so 63 Chinese characters (189 bytes) encrypt while 64 (192 bytes) are refused.
  • Only RSA-OAEP with SHA-256 is wired up: PKCS#1 v1.5, OAEP-SHA1 and RSA-PSS or RSASSA keys cannot be used here, and there is no sign or verify tab despite older feature lists.
  • Ciphertext must be standard Base64; hyphens and underscores from Base64URL are rejected by atob, while spaces and line breaks inside the string are stripped before decoding.
  • When the JWK has no usable n, the ceiling falls back to a hardcoded 190 bytes, so an unusual key can be refused with a budget that does not match its real modulus.

Related tools

When this page is the right instrument, and when it stalls

The situationThis RSA pageThe route to take instead
The secret is longer than modulus bytes minus 66It refuses rather than truncates: the check reads n before encrypting, so even the 4096-bit option stops at 446 bytes and there is no chunking control anywhere on the page.Wrap, do not enlarge. Seal the body with the AES tool and let this page encrypt only the 32-odd character passphrase, or move to a script that prepends the RSA-encrypted key to the AES ciphertext so ordering is not left to the recipient.
You need an RS256 or PS256 signature, or a key that can verify oneThe three tabs are generate, encrypt and decrypt, and the pair is created with encrypt and decrypt usages only, so the exported JWK carries no sign usage and a JWT library rejects it while importing.jsonwebtoken or node:crypto with a PEM key, or openssl dgst -sha256 -sign. To read or check a token someone else signed, the JWT decoder page is the correct stop, not this one.
The key you were handed is a .pem file, an OpenSSH line, or genrsa outputEvery key box parses JSON first, so a PEM header fails at the parse step with the invalid-key toast; there is no PEM, DER or OpenSSH import path on this page at all.Convert once and paste: crypto.createPrivateKey(pem).export({format:"jwk"}) in Node prints the JSON this page wants. If converting is the whole job, run the encryption in openssl pkeyutl and skip the browser round trip.
You want a keypair to keep for years in CI or a repo secretWrong place to mint one: the generate tab writes an extractable private JWK into the DOM in cleartext, with no passphrase and no file download, so the key exists wherever the page was cast or screenshotted.openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -aes256 -out key.pem, or keep the private half in KMS and paste only the public JWK into the encrypt tab.
One short secret has to reach one person, and both sides are already hereA good fit: a 32-byte API key, 44 Base64 characters, fits under either modulus, and the recipient only needs the private JWK plus one line of ciphertext.A share link from a password manager or age -r <recipient> secrets.env beats it whenever the secret is a file, since those carry expiry with the blob and this page leaves you to ferry the private key through a second channel yourself.

One concrete scenario

Wrapping a 700-byte token under a 4096-bit key

A partner sends a 4096-bit public JWK and asks for a 700-character access token by email. Paste both into the encrypt tab and it halts before touching the key: a 512-byte modulus minus 66 bytes of OAEP padding leaves 446, and 700 bytes of UTF-8 is past it. Splitting the token into two runs of 350 does not rescue the plan either, because one OAEP block yields one ciphertext; each half would arrive as its own 684-character Base64 string for the partner to reassemble by hand. Wrap instead: seal the token in the AES tool under a 32-character passphrase, then RSA-encrypt only the passphrase. Thirty-two bytes cross the RSA boundary, so the 2048-bit key at 190 bytes is plenty and its ciphertext is 256 bytes rather than 512. Decide first how many bytes the RSA step must actually carry.

Frequently Asked Questions

Are RSA encryption and signing in opposite directions?
Yes, and it trips everyone up once: encryption uses the recipient’s public key (their private key decrypts — confidentiality); signing uses your own private key (others verify with your public key — authenticity and non-repudiation). What a public key encrypts only the private key can open; what a private key signs, anyone with the public key can verify but none can forge.
Can RSA encrypt data of any length?
No. One RSA operation encrypts at most a few hundred bytes (about 190 bytes with OAEP and a 2048-bit key) and is slow. Real systems use hybrid encryption: RSA wraps a random AES key, and AES encrypts the actual data — the structure behind TLS and RSA-mode JWTs.
Is 2048-bit RSA still safe? Should I jump to 4096?
2048 remains acceptable (NIST-approved beyond 2030); 4096 adds margin but signs and verifies 5–10× slower with larger ciphertexts. New keys: 3072 or 4096. The urgent risks are legacy 1024-bit keys and outdated signature algorithms like RSA-SHA1, not key size on modern deployments.

Content reviewed: