go语言rsa加密应使用标准库crypto/rsa而非forgoer/openssl;密钥须pem编码且类型严格匹配:私钥为"rsa private key"(pkcs#1),公钥为"public key"(pkix);加密用encryptpkcs1v15,签名用signpkcs1v15,注意明文长度限制与哈希一致性。

Go 语言做 RSA 加密,**别直接用 forgoer/openssl 包**——它不维护、不兼容 Go 1.20+ 的模块机制,且底层调用 OpenSSL C 库,在 macOS ARM64 或容器环境容易 panic;标准库 crypto/rsa 完全够用,安全、稳定、无 CGO 依赖。
用标准库生成 PEM 格式密钥对(rsa.GenerateKey + pem.Encode)
密钥必须是 PEM 编码的 ASN.1 DER 结构,否则 crypto/rsa 后续读取会报 x509: failed to parse private key 或 invalid public key。
- 私钥必须用
"RSA PRIVATE KEY"类型封装(PKCS#1),不能用"PRIVATE KEY"(PKCS#8)——后者ParsePKCS1PrivateKey无法识别 - 公钥必须用
"PUBLIC KEY"类型(PKIX,即 PKCS#8 公钥格式),不能用"RSA PUBLIC KEY"(PKCS#1 公钥)——后者ParsePKIXPublicKey会失败 - 生成时务必用
rand.Reader,别传nil或自定义弱随机源,否则密钥可被预测 - 位数选 2048 起步,1024 已被 NIST 禁用;若需 FIPS 合规,必须 3072+
示例关键片段:
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
privBytes := x509.MarshalPKCS1PrivateKey(privateKey)
pem.Encode(privFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: privBytes})
pubBytes, _ := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
pem.Encode(pubFile, &pem.Block{Type: "PUBLIC KEY", Bytes: pubBytes})
公钥加密 / 私钥解密(EncryptPKCS1v15 和 DecryptPKCS1v15)
这是最常用场景,比如客户端用服务端公钥加密 token,服务端用私钥解密。注意:RSA 本身不能加密长数据,明文长度上限 ≈ 密钥字节数 − 11(PKCS#1 v1.5 填充)。
- 2048 位密钥 → 最大明文约 245 字节;超长必须分块或改用混合加密(RSA 封装 AES 密钥)
- 加密必须用
rsa.EncryptPKCS1v15,别误用EncryptOAEP—— 两者不兼容,服务端用 OAEP 加密,客户端用 PKCS1 解密会直接 panic - 解密失败常见原因是私钥格式错误(见上一条)或密文被截断/损坏(base64 decode 后长度不对)
- 不要在生产中对原始密码、银行卡号等直接 RSA 加密 —— 应先哈希或加盐,或走标准协议如 JWE
私钥签名 / 公钥验签(SignPKCS1v15 和 VerifyPKCS1v15)
签名不是“加密”,而是对摘要(如 SHA256)做数学运算;验签是验证该运算结果是否匹配原文摘要。错误理解会导致用错函数(比如拿 EncryptPKCS1v15 当签名用)。
- 签名前必须自己算好哈希值,传给
SignPKCS1v15的是hash.Hash.Sum(nil)结果,不是原文 - 验签时要传原文重新计算哈希,再喂给
VerifyPKCS1v15—— 不是把原文直接丢进去 - 哈希算法必须和签名时严格一致,
crypto.SHA256和crypto.SHA512混用会返回crypto/rsa: verification error - 签名输出是原始字节,通常要 base64 编码传输;验签前记得 base64 decode 回原始字节
读取密钥文件的典型错误(ParsePKCS1PrivateKey vs ParsePKIXPublicKey)
这两个函数名字像,但行为和输入要求完全不同,搞混就卡死在第一步。
-
ParsePKCS1PrivateKey只认"RSA PRIVATE KEY"PEM 块,且输入必须是 *pem.Block.Bytes(即 DER 数据),不能是整个 PEM 字符串 -
ParsePKIXPublicKey只认"PUBLIC KEY"PEM 块,同样只接受 DER 字节,且必须是 PKIX 格式(MarshalPKIXPublicKey产出的) - 常见错误:
ioutil.ReadFile读出来的是带 PEM 头尾的完整字节,得先用pem.Decode提取出.Bytes字段再传给解析函数 - 别用
ParsePKCS1PublicKey—— 它对应旧版"RSA PUBLIC KEY",现代系统基本不用,且 Go 1.22+ 已标记为 deprecated
最易被忽略的一点:所有 crypto/rsa 操作都要求密钥未被密码保护(即无 PEM encryption header)。如果私钥是 openssl genrsa -aes256 生成的,必须先用 openssl rsa -in private.key -out private_unencrypted.key 去密,否则 ParsePKCS1PrivateKey 会静默返回 nil。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











