Go crypto生成PKCS1公钥与openssl rsa输出的差异及修复
问题原因
- 公钥编码格式不匹配:
openssl rsa -pubout默认输出X.509 SubjectPublicKeyInfo(PKIX)格式公钥,PEM块类型为PUBLIC KEY,编码内容包含外层算法标识结构。你当前代码调用x509.MarshalPKCS1PublicKey生成的是裸PKCS#1格式RSA公钥,缺失外层算法标识头,openssl输出多出来的前缀MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A就是RSA算法的X.509标识段。 - 私钥PEM块类型错误:你使用
x509.MarshalPKCS8PrivateKey生成的是PKCS#8格式私钥,对应PEM块类型应为PRIVATE KEY,当前写的RSA PRIVATE KEY是PKCS#1格式私钥专用标识,不符合PKCS#8格式规范。
修复方案
修改两处编码逻辑:
- 私钥编码:将PEM块的
Type字段从RSA PRIVATE KEY改为PRIVATE KEY,匹配PKCS#8编码内容。 - 公钥编码:将
x509.MarshalPKCS1PublicKey替换为x509.MarshalPKIXPublicKey,生成带标准算法标识的X.509格式公钥,和openssl输出完全对齐;同时补充公钥编码的错误返回逻辑。
修正后的完整代码:
package xyz import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" ) func GeneratePrivateKey(bitSize int) (*rsa.PrivateKey, error) { privateKey, err := rsa.GenerateKey(rand.Reader, bitSize) if err != nil { return nil, err } if err = privateKey.Validate(); err != nil { return nil, err } return privateKey, nil } func EncodePrivateKeyToPEM(privateKey *rsa.PrivateKey) (string, error) { privateDER, err := x509.MarshalPKCS8PrivateKey(privateKey) if err != nil { return "", err } privateBlock := pem.Block{ Type: "PRIVATE KEY", Headers: nil, Bytes: privateDER, } return string(pem.EncodeToMemory(&privateBlock)), nil } func EncodePublicKeyToPEM(privateKey *rsa.PrivateKey) (string, error) { publicDER, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey) if err != nil { return "", err } publicBlock := pem.Block{ Type: "PUBLIC KEY", Bytes: publicDER, } return string(pem.EncodeToMemory(&publicBlock)), nil }
修改后生成的私钥、公钥和给出的两条openssl命令输出完全一致,公钥会携带正确的算法标识前缀,可直接被所有标准RSA工具兼容解析。
内容的提问来源于stack exchange,提问作者anekdoti
相关产品推荐
相关产品推荐

