语言:中文

tools / rsa

rsa/

RSA 公钥加密、私钥解密,也能私钥加密、公钥解密。填充方式、密钥格式、输入输出格式和字符集都可以选,密钥不会离开浏览器。

明文

密钥

密文

历史记录

每次加密、解密成功后自动记一条,保留最近 20 条,只存在这台设备的浏览器里。不保存密钥,但解密出的明文会保存,在公用电脑上用完请清空记录。

AES、DES、RSA 是什么,有什么区别

AES 和 DES 是对称加密:加密和解密用同一把密钥,就像同一把钥匙锁门也开门。它们速度快,适合加密大量数据,难处在于怎么把这把密钥安全地交给对方。

DES 是上世纪 70 年代的老标准,有效密钥只有 56 位,现在用专门的硬件或计算机集群可以暴力穷举破解,只适合对接还在用它的老系统。AES 是取代 DES 的新标准,密钥 128、192 或 256 位,目前没有可行的破解方法,是现在加密数据的首选。

RSA 是非对称加密:有一对密钥,公钥可以公开给任何人,用来加密;私钥自己保管,用来解密。就像一个谁都能往里投信、只有你有钥匙的信箱。好处是不用事先约定密钥,缺点是很慢,一次只能加密几百字节。实际系统常把两者结合:先用 RSA 加密一把随机生成的 AES 密钥发给对方,再用 AES 加密真正的数据。

一次能加密多长的内容

RSA 一次只能加密一小段数据,上限由密钥长度和填充方式决定。PKCS1Padding 最多是密钥字节数减 11,2048 位密钥是 245 字节;OAEP 最多是密钥字节数减去两倍哈希长度再减 2,2048 位密钥配 SHA-256 是 190 字节。更长的数据通常先用 AES 加密,再用 RSA 加密 AES 密钥。

和 Java 的写法怎么对应

填充方式的名称与 Java 的 Cipher 一致:RSA/ECB/PKCS1Padding 选 PKCS1Padding;RSA/ECB/OAEPWithSHA-256AndMGF1Padding 选第三项,Java 默认 MGF1 用 SHA-1;用 OAEPParameterSpec 自定义哈希时选 OAEPPadding,再分别选 OAEP 哈希和 MGF1 哈希。字符集也按 Java 的规则,比如 UTF-16 编码时开头带 FE FF、按大端排列。

为什么每次加密结果都不一样

公钥加密时,PKCS1Padding 和 OAEP 都会在填充里加入随机数,同样的内容每次加密结果都不同,但都能用私钥解开,这是正常的。私钥加密的填充是固定的,结果每次都一样。OAEP 只能公钥加密、私钥解密。

支持哪些密钥

PEM 支持 BEGIN PUBLIC KEY、BEGIN RSA PUBLIC KEY、BEGIN PRIVATE KEY、BEGIN RSA PRIVATE KEY 四种,也可以只粘贴中间的 Base64;hex 是同样内容的十六进制。带密码的私钥需要先解密。密钥类型选公钥时也可以直接粘贴私钥,会使用其中的公钥部分。

常见问题

解密提示「密钥不对应、密钥类型或填充方式不对」怎么办

按三项逐个排查:一是密钥是否和加密用的公钥成对,公钥加密的内容只能用配对的私钥解开;二是密钥类型要选私钥;三是填充方式和加密端一致。选 OAEPPadding 时,OAEP 哈希和 MGF1 哈希也都要和加密端相同。最后确认输入格式没选错,hex 和 base64 选反也会解密失败。

提示密钥格式不对,或「不支持 CERTIFICATE」怎么办

先确认「密钥格式」和粘贴的内容一致:-----BEGIN 开头的选 pem,一长串十六进制的选 hex,选错时通常会提示该改成哪个。PEM 里必须是 RSA 公钥或私钥,证书(BEGIN CERTIFICATE)不能直接用,可以先用 openssl x509 -in cert.pem -pubkey -noout 取出公钥。证书和密钥贴在一起时,会自动取其中的密钥块。

私钥带密码,提示「请先解密成不带密码的私钥」怎么办

这里不支持带密码的私钥(BEGIN ENCRYPTED PRIVATE KEY,或 PEM 头里有 Proc-Type: 4,ENCRYPTED),需要先在本机去掉密码再粘贴,比如用 openssl rsa -in 原文件 -out 新文件,按提示输入密码。去掉密码后的文件等于明文私钥,用完请妥善处理。

提示「内容超过上限」,能加密多少个中文

上限按字节算,不是按字数。2048 位密钥配 PKCS1Padding 最多 245 字节,UTF-8 下一个汉字占 3 字节,约 81 个汉字;字符集选 GBK 时一个汉字占 2 字节,约 122 个。加密时粘贴密钥后,密钥栏标题旁会显示当前密钥和填充方式下「最多加密 N 字节」。超出时直接报错,这里不会自动分段加密。

前端 JSEncrypt 或 Web Crypto 加密的结果,这里怎么解

JSEncrypt 用的是 PKCS1Padding,输出是 Base64,所以这里填充选 PKCS1Padding,输入格式选 base64。浏览器 Web Crypto 的 RSA-OAEP 用同一个哈希同时做 OAEP 和 MGF1,这里要选 OAEPPadding,并把 OAEP 哈希和 MGF1 哈希设成相同的值,比如都选 SHA256。两种情况下密钥类型都选私钥。

提示「密文比密钥长度还长」或「密文数值超出密钥范围」是什么意思

RSA 密文的长度等于密钥的字节数,2048 位密钥是 256 字节,写成 hex 是 512 个字符,不会更长。解密时密钥栏标题旁会显示「密文 N 字节」,拿它和输入栏旁的字节数对一下。比密钥还长,多半是输入格式选错或多复制了内容;数值超出范围,说明这段密文不是这把密钥配对的公钥加密的,请换对密钥。

私钥加密、公钥解密能用来签名和验签吗

不能直接当签名用。这里的私钥加密只是把你输入的内容按 PKCS1Padding 用私钥运算,不做哈希;而 SHA256withRSA 这类签名是先算哈希,再把哈希按固定结构(DigestInfo)填进去。所以用这里的公钥去解一个标准签名,得到的是这个结构,不是原文。要签名或验签,请用支持 SHA256withRSA 这类算法的库或工具。

历史记录里存了什么,会上传吗

只存在这台设备浏览器的 localStorage 里,不会上传,页面代码里没有任何网络请求。每次成功加密或解密后记一条,最多保留 20 条,输入或结果超过 2 万字符的不记。记录里有参数、输入和结果,以及一个由密钥算出的 8 位指纹(模数的 SHA-256 前 8 位,在记录里 # 号后面,用来区分是不是同一把密钥),不存密钥本身,所以点「填入」后要重新贴密钥。解密出的明文会被保存,公用电脑上用完请点「清空记录」。