如何在Go语言中复刻OpenSSL的RSA加密功能?
用Go复刻OpenSSL的RSA加密行为
OpenSSL的openssl rsautl -encrypt命令默认使用PKCS#1 v1.5填充模式,要在Go里实现完全一致的行为,只需对应使用crypto/rsa包的EncryptPKCS1v15方法,同时正确加载PEM格式的公钥即可。
核心匹配要点
- OpenSSL默认不启用OAEP填充,需指定
-oaep参数才会切换,因此Go代码必须选择PKCS#1 v1.5而非OAEP相关加密方法 - 公钥文件兼容两种常见格式:
- 标注为
RSA PUBLIC KEY的PKCS#1格式 - 标注为
PUBLIC KEY的PKCS#8格式
代码需同时支持这两种解析逻辑
- 标注为
完整实现代码
package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "fmt" "io/ioutil" "os" ) func main() { // 加载公钥文件(对应OpenSSL的-inkey public.pem -pubin参数) pubKeyBytes, err := ioutil.ReadFile("public.pem") if err != nil { fmt.Printf("读取公钥失败: %v\n", err) os.Exit(1) } // 解析PEM块 block, _ := pem.Decode(pubKeyBytes) if block == nil { fmt.Println("无效的PEM格式公钥") os.Exit(1) } var pubKey *rsa.PublicKey switch block.Type { case "RSA PUBLIC KEY": // 解析PKCS#1格式公钥 pubKey, err = x509.ParsePKCS1PublicKey(block.Bytes) case "PUBLIC KEY": // 解析PKCS#8格式公钥 pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err == nil { var ok bool pubKey, ok = pubInterface.(*rsa.PublicKey) if !ok { err = fmt.Errorf("非RSA类型公钥") } } default: err = fmt.Errorf("不支持的公钥类型: %s", block.Type) } if err != nil { fmt.Printf("解析公钥失败: %v\n", err) os.Exit(1) } // 读取明文数据(对应OpenSSL的-in data.txt参数) plaintext, err := ioutil.ReadFile("data.txt") if err != nil { fmt.Printf("读取明文失败: %v\n", err) os.Exit(1) } // 执行加密(对应OpenSSL的-encrypt参数,默认PKCS#1 v1.5填充) ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, plaintext) if err != nil { fmt.Printf("加密失败: %v\n", err) os.Exit(1) } // 输出加密后的数据(对应OpenSSL的-out encrypted_data.bin参数) err = ioutil.WriteFile("encrypted_data.bin", ciphertext, 0644) if err != nil { fmt.Printf("写入加密数据失败: %v\n", err) os.Exit(1) } fmt.Println("加密完成,结果已写入encrypted_data.bin") }
一致性验证
你可以用OpenSSL命令解密Go生成的加密文件,验证是否能还原原明文:
openssl rsautl -decrypt -inkey private.pem -in encrypted_data.bin -out decrypted.txt
对比decrypted.txt和原data.txt的内容,完全一致即说明实现与OpenSSL行为匹配。
内容的提问来源于stack exchange,提问作者Fábio Almeida
相关产品推荐
相关产品推荐

