Golang如何实现类似PHP的openssl_private_encrypt功能
Golang如何实现类似PHP的openssl_private_encrypt功能 我正在尝试将我的项目从 PHP 迁移到 Go,但我发现 Go 没有私钥加密方法。
据我所知,Go 只支持私钥解密(rsa.DecryptOAEP)。
但 PHP 有一个名为 openssl_private_encrypt 的函数 PHP: openssl_private_encrypt - Manual
有什么我可以使用的替代方法吗?
谢谢
2 回复
PHP的 openssl_private_encrypt 手册是密码学扩展的一部分。这是PHP全球范围内使用的官方密码学库。
在Golang中,有两种选择来获取使用OpenSSL私钥进行加密解密的函数:
- 选项1: 构建你自己的加密解密函数。Golang有官方的密码学包。你可以在这里查看加密解密的示例。
- 选项2: 使用Golang社区包。有很多现成的库可以进行加密解密。例如:
https://github.com/VIBHOR94/go-opensslhttps://github.com/spacemonkeygo/opensslhttps://github.com/forgoer/opensslhttps://github.com/Luzifer/go-openssl
尝试比较它们,找出最适合你的方案。
希望这能解答你的问题。
更多关于Golang如何实现类似PHP的openssl_private_encrypt功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中实现类似PHP的openssl_private_encrypt功能,可以使用RSA私钥进行加密(签名操作)。这实际上是使用私钥对数据进行签名,而不是传统意义上的加密。以下是两种实现方式:
方法1:使用PKCS#1 v1.5签名(最接近PHP默认行为)
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
"log"
)
func privateEncryptPKCS1v15(privateKeyPEM []byte, data []byte) ([]byte, error) {
// 解析PEM格式的私钥
block, _ := pem.Decode(privateKeyPEM)
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block")
}
// 解析私钥
privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
// 尝试PKCS8格式
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %v", err)
}
var ok bool
privKey, ok = key.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("not an RSA private key")
}
}
// 计算数据的哈希
hashed := sha256.Sum256(data)
// 使用私钥签名(相当于PHP的openssl_private_encrypt)
signature, err := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, hashed[:])
if err != nil {
return nil, fmt.Errorf("signing failed: %v", err)
}
return signature, nil
}
func main() {
// 示例私钥(实际使用时替换为你的私钥)
privateKeyPEM := `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwV2Bd5J...
-----END RSA PRIVATE KEY-----`
data := []byte("Hello, World!")
encrypted, err := privateEncryptPKCS1v15([]byte(privateKeyPEM), data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Encrypted/Signed data: %x\n", encrypted)
}
方法2:使用PSS签名(更安全)
func privateEncryptPSS(privateKeyPEM []byte, data []byte) ([]byte, error) {
block, _ := pem.Decode(privateKeyPEM)
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block")
}
privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %v", err)
}
var ok bool
privKey, ok = key.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("not an RSA private key")
}
}
hashed := sha256.Sum256(data)
// 使用PSS签名
signature, err := rsa.SignPSS(rand.Reader, privKey, crypto.SHA256, hashed[:], nil)
if err != nil {
return nil, fmt.Errorf("PSS signing failed: %v", err)
}
return signature, nil
}
方法3:直接使用私钥加密(不推荐,仅用于兼容)
func privateEncryptRaw(privateKeyPEM []byte, data []byte) ([]byte, error) {
block, _ := pem.Decode(privateKeyPEM)
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block")
}
privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %v", err)
}
var ok bool
privKey, ok = key.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("not an RSA private key")
}
}
// 注意:RSA私钥加密有长度限制
// 数据长度必须小于密钥长度-11字节(PKCS#1 v1.5填充)
maxLen := (privKey.N.BitLen() / 8) - 11
if len(data) > maxLen {
return nil, fmt.Errorf("data too large for RSA key size")
}
// 使用私钥直接加密(不推荐用于生产)
encrypted, err := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.Hash(0), data)
if err != nil {
return nil, fmt.Errorf("encryption failed: %v", err)
}
return encrypted, nil
}
验证示例(对应PHP的openssl_public_decrypt)
func publicDecrypt(publicKeyPEM []byte, encryptedData []byte) ([]byte, error) {
block, _ := pem.Decode(publicKeyPEM)
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block")
}
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse public key: %v", err)
}
rsaPubKey, ok := pubKey.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("not an RSA public key")
}
// 验证签名/解密
return rsaPubKey.N.Bytes()[:len(encryptedData)], nil
}
注意:PHP的openssl_private_encrypt实际上执行的是私钥签名操作。在Go中,你应该根据具体用途选择:
- 如果用于签名验证:使用方法1或2
- 如果确实需要私钥加密:使用方法3(但通常不推荐)
实际迁移时,需要确认PHP代码中openssl_private_encrypt的具体用途,以选择正确的Go实现方式。

