在线 RSA 加解密工具:非对称加密和数字签名
什么是 RSA 加密
RSA 是最广泛使用的非对称加密算法,由 Rivest、Shamir、Adleman 三人于 1977 年提出。它使用一对密钥:公钥加密,私钥解密。
RSA 工作原理
密钥对生成:
选择两个大质数 p, q
计算 n = p × q
计算 φ(n) = (p-1)(q-1)
选择 e 使得 gcd(e, φ(n)) = 1
计算 d 使得 e×d ≡ 1 (mod φ(n))
公钥: (e, n) ← 可以公开
私钥: (d, n) ← 必须保密
加密: C = M^e mod n
解密: M = C^d mod n
RSA vs AES
| 特性 | RSA(非对称) | AES(对称) |
|---|---|---|
| 密钥数量 | 一对(公钥+私钥) | 一个共享密钥 |
| 加密速度 | 慢(1000x) | 快 |
| 数据大小 | 有限制(< 密钥长度) | 无限制 |
| 典型用途 | 密钥交换、数字签名 | 数据加密 |
| 密钥长度 | 2048-4096 位 | 128-256 位 |
为什么需要 RSA 加密
- 安全通信:HTTPS/TLS 握手中的密钥交换
- 数字签名:验证数据完整性和来源
- API 认证:JWT RS256 签名验证
- 密钥交换:安全传输 AES 会话密钥
- 代码签名:验证软件发布者身份
如何使用在线工具
使用 ToolVault 工具匣 的 RSA 加解密工具:
- 生成 RSA 密钥对(2048/4096 位)
- 使用公钥加密数据
- 使用私钥解密数据
- 创建和验证数字签名
- 支持 PEM 格式导入/导出
代码中的 RSA
JavaScript:Web Crypto API
// 生成 RSA 密钥对
async function generateRSAKeyPair() {
const keyPair = await crypto.subtle.generateKey(
{
name: 'RSA-OAEP',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: 'SHA-256',
},
true,
['encrypt', 'decrypt']
);
return keyPair;
}
// 加密
async function rsaEncrypt(publicKey, data) {
const encoder = new TextEncoder();
const encrypted = await crypto.subtle.encrypt(
{ name: 'RSA-OAEP' },
publicKey,
encoder.encode(data)
);
return new Uint8Array(encrypted);
}
// 解密
async function rsaDecrypt(privateKey, encryptedData) {
const decrypted = await crypto.subtle.decrypt(
{ name: 'RSA-OAEP' },
privateKey,
encryptedData
);
return new TextDecoder().decode(decrypted);
}
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()
# 加密
ciphertext = public_key.encrypt(
b"Hello, RSA!",
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 解密
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
填充模式不是细节,是安全本身
教科书 RSA(对消息做幂运算)在确定性地不安全:同一明文永远得同一密文,短消息直接被开根号提取。所有真实部署都用填充方案,而选择是兼容性雷区:PKCS#1 v1.5 是到处可用的遗留默认,但在解密方泄露失败细节时暴露于 Bleichenbacher 填充预言攻击;OAEP 是现代答案——但 Java 默认 OAEP 参数与 OpenSSL 的 MGF1 摘要不同,产出彼此打不开的密文。规则:一方加密、另一方解不开时,先比对 OAEP 参数字节再怪密钥。
密钥尺寸:2048 的由来与 4096 的误用
分解记录一路推高门槛:512 位 1999 年破、768 位 2009 年破、1024 位在国家力量预算内。2048 位约 112 bit 安全强度,满足当前所有 CA 与标准。跳到 4096 位让解密成本翻四倍只换约 20 bit——正确动作是换算法:新混合设计用 EC(P-256)或 SM2,以零头密钥尺寸拿 128 bit。4096 只留给被对方标准冻结在 RSA 里的场景。
混合信封的现实
RSA 一次最多加密一个块(2048 位下按填充 190-245 字节)——没人直接用 RSA 加密文档。真实系统全是信封结构:随机 AES/SM4 会话密钥加密数据本体,RSA 只加密会话密钥。TLS、PGP、我们的混合工具都是这个形状。调试「RSA payload too long」报错,八成是有人跳过了信封这步。
PEM 格式与导入导出:SPKI 与 PKCS#8
工具的「生成密钥」页签输出的是 PEM 文本块,但 PEM 只是外壳——外壳里面装哪种 DER 结构才决定能不能被别的程序打开:
| 外观 | 内部结构 | 用途 | 兼容性 |
|---|---|---|---|
BEGIN PUBLIC KEY | SPKI(X.509 SubjectPublicKeyInfo) | 公钥 | 所有现代栈通用 |
BEGIN RSA PUBLIC KEY | PKCS#1 RSAPublicKey | 公钥 | 遗留格式,Web Crypto 不支持 |
BEGIN PRIVATE KEY | PKCS#8 PrivateKeyInfo | 私钥 | 所有现代栈通用 |
BEGIN RSA PRIVATE KEY | PKCS#1 RSAPrivateKey | 私钥 | 遗留格式,Web Crypto 不支持 |
BEGIN ENCRYPTED PRIVATE KEY | PKCS#8 + 密码包裹 | 加密私钥 | 需先解密 |
换算只在 OpenSSL 一侧:openssl rsa -in rsa.pem -pubout 就能把 PKCS#1 私钥换成 PKCS#8(-in 读进来,-pubout 对应导出公钥;私钥格式转换用 openssl pkcs8 -topk8 -nocrypt)。反过来,Java/Python 导出的 BEGIN PUBLIC KEY / BEGIN PRIVATE KEY 可以直接粘进工具的输入框——粘贴时带有的换行、CRLF 空白会被自动剥掉。
常见报错排查清单
「DataError」/ 解密失败(浏览器):密文不是这把私钥对应的公钥加密的,或密文被截断/改写。Base64 密文丢一个字符都会触发——先检查复制是否完整。
明文太长(payload too long):OAEP/SHA-256 下单块上限是 密钥字节数 - 66。2048 位只能装 190 字节 UTF-8(约 63 个汉字),4096 位 446 字节。工具加密页签现在会实时显示字节数/上限,超限会禁用加密按钮——这是提示你走混合加密,不是 bug。
「BEGIN RSA PRIVATE KEY」导入失败:这是 PKCS#1 私钥,Web Crypto 只吃 PKCS#8(BEGIN PRIVATE KEY)。用 openssl pkcs8 -topk8 -nocrypt -in rsa.pem -out pkcs8.pem 转换后再导入。
跨语言对不上(Java 加密、浏览器解不开):九成是 OAEP 参数不一致。Java 写 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 时 MGF1 默认还是 SHA-1,而 Web Crypto 的 hash: 'SHA-256' 会把 MGF1 也锁成 SHA-256。Java 侧必须显式 new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT)。
FAQ
RSA 密钥长度如何选择?
- 2048 位:当前标准,足够安全
- 3072 位:更高安全要求
- 4096 位:最高安全级别(性能较低) NIST 建议至少 2048 位,2030 年后建议 3072 位以上。
RSA 和 ECC 哪个更好?
ECC(椭圆曲线)在相同安全级别下密钥更短(256 位 ECC ≈ 3072 位 RSA),性能也更好。但 RSA 更成熟、兼容性更好。新项目推荐 ECC,现有系统保持 RSA。
为什么 RSA 不能直接加密大文件?
RSA 加密有长度限制(密钥长度 - 填充开销),且速度慢。实际使用中,RSA 用于加密 AES 密钥,再用 AES 加密文件(混合加密)。对称的 AES 部分可以用我们的 AES 加解密工具来完成。
PEM 公钥能直接贴进工具吗?换行会弄坏密钥吗?
不会。PEM 按 64 字符换行只是排版约定,工具导入前会把所有空白剥掉再按 base64 解码。但要确认头行:公钥必须是 BEGIN PUBLIC KEY,私钥必须是 BEGIN PRIVATE KEY——带 RSA 字样的是 PKCS#1 遗留格式,浏览器 Web Crypto 不支持。
2048 位 RSA 一次能加密多少汉字?
OAEP/SHA-256 上限 190 字节,UTF-8 下约 63 个汉字。工具加密页签会实时显示「字节数/上限」,超限自动禁用按钮。需要加密更长内容时,正确姿势是混合加密而不是换更大的 RSA 密钥。
排查注记
报错清单按互操作场景排:跨语言对不上单列并断言「九成是 OAEP 参数不一致」,依据是 Java 的 OAEPWithSHA-256AndMGF1Padding 里 MGF1 默认还是 SHA-1、而 Web Crypto 会把 MGF1 也锁成 SHA-256——两边摘要参数差一个字段,密文就互相打不开。PEM 那张表按头行区分 SPKI/PKCS#8 与 PKCS#1 遗留格式,因为带 RSA 字样的头 Web Crypto 不吃,是导入失败里最好认的一类。「payload too long」的注解也是同一逻辑:八成是有人跳过了信封这步,正确姿势是混合加密而不是换更大的密钥。
这篇实战笔记来自 ToolVault 工具匣。其他在线工具可在 首页 找到。
相关工具
相关文章
后量子迁移自查清单:从算法盘点到 hybrid TLS,2026 年该做完的 12 件事
后量子密码(PQC)迁移的实操自查框架:三张监管时刻表为什么让 2026 成为起点、算法盘点(CBOM)怎么做、按 HNDL 暴露度排优先级、X25519+ML-KEM 混合 TLS 怎么开,以及 crypto-agility 的工程落地。附 12 项可勾选 checklist。
Passkeys 完全指南:为什么服务器再也存不了你的密码副本
Passkey(WebAuthn/FIDO2)加深:注册与断言仪式、平台认证器与漫游密钥、同步通行密钥取舍、与密码/TOTP/JWT 的关系,以及 origin 绑定如何结构性抗钓鱼。服务器只存公钥;站内无独立 Passkey 工具页的说明。
ML-KEM 入门:Kyber 是怎么进到你的 TLS 握手里的
后量子密钥封装 ML-KEM(FIPS 203,前身 Kyber)的工程向解读:Kyber 到标准名的变迁、封装/解封装语义与 IND-CCA、三档参数尺寸、X25519+ML-KEM 与 TLS 1.3 HKDF 密钥调度的混合方式、ClientHello 膨胀中间盒坑、OpenSSL 3.5 / nginx 开法,以及浏览器侧实现边界。