RSA 密钥与加解密

浏览器本地生成密钥对,PEM/PKCS#8 互见,OAEP 加解密与签名验签。

这里的密钥全部由浏览器 crypto.subtle.generateKey 在本机生成,PEM 文本(-----BEGIN PUBLIC KEY----- 与 -----BEGIN PRIVATE KEY-----)由本站自己按 Base64 折行加标签产出,DER 的 ASN.1 结构(SPKI、PKCS#8、RSAPublicKey、RSAPrivateKey)也是本站自己解析和包装的,因为 WebCrypto 的 importKey/exportKey 只认 DER。加解密用 RSA-OAEP,签名用 RSASSA-PKCS1-v1_5 或 RSA-PSS;你看到的公钥/私钥、JWK、模数 n 的十六进制、公钥指纹(对 SPKI DER 取 SHA-256)都只在内存里。

OAEP 单块能加密的明文长度是硬上限,超过这个长度本站直接报错,绝不做「自动分段拼接」——同一条消息用同一把 RSA 密钥反复加密不是任何标准的做法,得到的自定义格式别人解不开,还会引入可被拼接、重放的协议漏洞;长正文的正确做法是混合加密。导入框一次贴进多块 PEM(私钥与公钥并排那种)只取最前面那一段,后面的整段忽略;带口令的私钥一律拒绝并说明原因:传统 PEM(Proc-Type: 4,ENCRYPTED / DEK-Info: AES-256-CBC,……)和 BEGIN ENCRYPTED PRIVATE KEY 都需要用口令解一层加密,WebCrypto 没有这个能力,本站不会假装能解。页面不发任何请求,私钥不会被上传,覆盖后也不留历史密钥。

RSA 密钥与加解密怎么用

  • 能选哪些参数:模数可选 1024/2048/3072/4096 位,公钥指数 65537 或 3;加解密用 RSA-OAEP,摘要可选 SHA-1/256/384/512,签名用 RSASSA-PKCS1-v1_5 或 RSA-PSS。
  • 一次能加密多少字节:OAEP 单块能加密的明文长度是硬上限:模数字节数 k 减去 2 倍摘要长度再减 2,2048 位配 SHA-256 就是 256 − 64 − 2 = 190 字节,配 SHA-1 是 214 字节。
  • 三态工作区与生成:顶部一颗模式开关切「密钥 / 加密 / 签名」,切的是三个分组容器的 hidden,一屏只铺开当前这一组,顶部横幅里上一条错误会随切态清掉(各组自己的状态行跟着那一组一起藏起来,切回来还在)。密钥态里选模数(默认 2048 推荐,另有 3072/4096 与「1024 仅演示」)和公钥指数,点「生成密钥对」;4096 位要找大素数,可能花几秒,状态文字先把话说在前面再交给 crypto.subtle,界面不会被卡住。页面上已经有一把密钥时这颗按钮会变成「确认覆盖并生成」,旁边亮出「取消覆盖」,上方警示条写明旧密钥的位数、来源(本页生成还是 PEM 导入)与是否含私钥,并提醒覆盖之后当场找不回来、本站不存历史——这是一次页内确认,不是浏览器弹窗。结果摊在三个原生折叠里:「公钥 PEM(SPKI)」「私钥 PEM(PKCS#8)」「JWK 对照」,摘要行右侧始终写着当前状态。私钥那两块的文本只在各自折叠展开时才写进 DOM,收起即清空、连警示条一起撤掉,JWK 收起时这里只剩公钥部分;公钥 PEM 与公钥 JWK 则一直在。要留档就展开后自己选中带走——本页没有复制按钮,也不导出文件。
  • 加密与签名各在一格:切到「加密」:选 OAEP 摘要(SHA-256 默认,SHA-1 那项写着「历史默认,别用于新系统」),摘要右边的实时说明会按当前模数算出这次能加密多少字节;在「明文」框写不超过上限的短文本点「加密」,密文固定是模数字节数长,解密把 Base64 或 Hex 贴进「密文(Base64)」框点「解密」。切到「签名」:算法选 RSASSA-PKCS1-v1_5 或 RSA-PSS、另选摘要,saltLength 那一行只有选了 PSS 才会出现;在「待签原文」点「签名」,把签名值贴回「签名值(Base64)」点「验签」即可得到通过与不通过。两态每次都用当前选择重新导入密钥,长度超限、状态不对都写在横幅里。「密钥材料」表里那两行上限各跟各的摘要:OAEP 那行看加密态选的摘要,PSS saltLength 那行看签名态选的摘要并注明是按哪条摘要算的,两边不会互相顶替。
  • 粘贴别人的密钥:在密钥态的「导入 PEM」框贴进去点「识别并使用这把密钥」:只有公钥时可以加密和验签,解密与签名必须再导入私钥,「密钥材料」表会跟着换成导入来源那一把(来源写「粘贴导入」、私钥那行写有没有持有),提示里同时写明它取代了页上原来的那一把(位数、本页生成还是 PEM 导入、含不含私钥),旧的那把不留副本、当场找不回来;页上原本没有密钥时说的是另一句。若贴的是 BEGIN RSA PRIVATE KEY 或带口令的传统 PEM,会给出明确提示和 openssl 转换命令。

常见问题

在网页里生成 RSA 密钥安全吗?私钥会不会被上传?

私钥不会离开浏览器:本页没有任何 fetch/XHR/表单提交,也不写任何远端存储,生成、导出、加密、签名全在 crypto.subtle 里完成。真正的风险在「生成之后」:密钥只存在于页面内存,刷新即消失,所以请自己选中把需要的公钥抄走(本页不设复制按钮,也不导出文件),私钥用成熟工具加口令保存;再点一次生成之前页面会先把你挡在「确认覆盖并生成」那一步,因为旧的那把覆盖之后当场找不回来。WebCrypto 无法给私钥加口令,本站也不会替你加密它。另外不要在来历不明的 https 站点生成生产密钥——同源脚本能读走内存里的私钥,页面自己也是第三方部署;长期使用的密钥建议用 openssl、ssh-keygen 或硬件令牌生成。1024 位只适合演示(NIST 早在 2013 年就停止认可),新系统请用 2048 位以上。

为什么长文本不能自动分段加密?

技术上能拆,但拆出来的东西不是标准格式,也谈不上安全。RSA 是「一次一块」的公钥原语:2048 位 + OAEP/SHA-256 一次最多 190 字节,超过就得自定义「分块边界、序号、长度、每块是否带 OAEP」这套私有协议,别人解不开;更糟的是密文块可被重排、删除、替换,攻击者能在不解密的条件下篡改整条消息,历史上很多自造分段方案就栽在这里。业界的答案是混合加密:用 RSA-OAEP 只保护一把随机 AES 密钥(几十字节),正文交给 AES-GCM——既没有长度限制,又有完整性保护,性能还高几个数量级。本站把上限如实报出来,就是为了让这个选择是明确做出的。

导入框认识哪些 PEM 标签?

导入框认识 BEGIN PUBLIC KEY(SPKI)、BEGIN RSA PUBLIC KEY(PKCS#1 公钥,本站会自己包成 SPKI)、BEGIN PRIVATE KEY(PKCS#8)、BEGIN RSA PRIVATE KEY(PKCS#1 私钥,本站会包成 PKCS#8)。

那长文本到底该怎么加密?

正确做法是混合加密:随机会生成一把 AES-GCM 密钥加密正文,再用 RSA-OAEP 加密那 16/32 字节的 AES 密钥,TLS 与 JWE 都是这么做的(本页的 AES 工具可以直接配合)。

同一份原文两次签名结果不一样,是不是坏了?

不是。RSA-PSS 的签名里含随机盐(saltLength),每次的签名值都不同,这是它比 PKCS1v15 更安全的原因之一(选择密文攻击下可证明安全);验签用的是同一套参数,所以同一签名反复验签结果稳定。RSASSA-PKCS1-v1_5 则是确定性的,同原文同密钥永远得到同一串。验签返回 false 通常有三类原因:原文改过一个字节、签名值粘贴时缺了字符(Base64 长度不对),或者摘要/算法/saltLength 与签名时不是同一套——本站每次都按当前选择重新导入密钥,切换这几项请务必回到签名时的组合。另外别忘了 SHA-1 这个历史默认值:不少老系统仍用 OAEP/SHA-1 或 PKCS1v15/SHA-1,指纹与签名看起来「不对」常常只是摘要选错,不是密钥错。

对应功能编号 #31无需安装,手机端同样可用按 Ctrl + K 换工具