Golang中如何使用Openssl_encrypt进行加密和解密?
Golang中如何使用Openssl_encrypt进行加密和解密? 大家好,
我是论坛的新成员,这是我的第一个主题。
很抱歉需要翻译。
我需要使用与 openssl_encrypt (PHP) 相同的方法进行加密,但我没有找到解决方案。我尝试解密一个用 openssl_decrypt 加密的数据,以便之后反过来操作,但这并不奏效。
我需要在 Go 中重现以下代码:
$crypted = openssl_encrypt(
serialize($unencrypted_data),
'AES-256-CTR',
$key,
0,
$iv
);
我尝试了相反的操作(解密一个用 openssl_encrypt 加密的数据):
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func main() {
iv, _ := base64.StdEncoding.DecodeString("NjIxNDM4MTFjODFhODRkYw==")
fmt.Println(string(iv))
key := []byte("key")
fmt.Println(string(key))
text, _ := base64.StdEncoding.DecodeString("TktXS3hKWnFZY3YwTXVpR0JKR0pYMkU4SlJ5aWFSZC9DZDJFaW1xdHNxVmZMT2JGUFI0YnRzakxMVkJsS1YyWEpYUEo0R2k4UDhGSERkQkRRTWtxUWcrbnhkU2NtTXlBTHJaM2M4cSs=")
fmt.Println(text)
cipherBlock, _ := aes.NewCipher(key)
fmt.Println(cipherBlock)
mode := cipher.NewCBCDecrypter(cipherBlock, iv)
mode.CryptBlocks(text[0:64], text[0:64])
fmt.Println(string(text))
}
结果(不正确):�Zf�^��7jZ��X}lM�ܿ/�:��w�kt5�����Z��|�pM�+/�?J��ʍ�_e��JXPJ4Gi8P8FHDdBDQMkqQg+nxdScmMyALrZ3c8q+
谢谢
更多关于Golang中如何使用Openssl_encrypt进行加密和解密?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang中如何使用Openssl_encrypt进行加密和解密?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中实现与PHP的openssl_encrypt兼容的AES-256-CTR加密解密,需要注意以下几点:
- 密钥长度:AES-256需要32字节密钥
- IV长度:CTR模式需要16字节IV
- 序列化:PHP的
serialize()需要对应Go的序列化处理 - 编码:PHP默认使用base64输出
以下是完整的示例代码:
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"io"
)
// 加密函数,兼容PHP openssl_encrypt
func opensslEncrypt(data interface{}, key []byte) (string, error) {
// 序列化数据(这里使用JSON替代PHP serialize)
serialized, err := json.Marshal(data)
if err != nil {
return "", err
}
// 确保密钥长度为32字节(AES-256)
if len(key) < 32 {
paddedKey := make([]byte, 32)
copy(paddedKey, key)
key = paddedKey
} else {
key = key[:32]
}
// 生成16字节IV
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
// 创建AES cipher
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
// 创建CTR模式加密器
stream := cipher.NewCTR(block, iv)
ciphertext := make([]byte, len(serialized))
stream.XORKeyStream(ciphertext, serialized)
// 组合IV和密文,然后base64编码
encrypted := append(iv, ciphertext...)
return base64.StdEncoding.EncodeToString(encrypted), nil
}
// 解密函数,兼容PHP openssl_decrypt
func opensslDecrypt(encrypted string, key []byte, result interface{}) error {
// base64解码
data, err := base64.StdEncoding.DecodeString(encrypted)
if err != nil {
return err
}
// 确保密钥长度为32字节
if len(key) < 32 {
paddedKey := make([]byte, 32)
copy(paddedKey, key)
key = paddedKey
} else {
key = key[:32]
}
// 分离IV和密文(前16字节是IV)
if len(data) < aes.BlockSize {
return fmt.Errorf("ciphertext too short")
}
iv := data[:aes.BlockSize]
ciphertext := data[aes.BlockSize:]
// 创建AES cipher
block, err := aes.NewCipher(key)
if err != nil {
return err
}
// 创建CTR模式解密器
stream := cipher.NewCTR(block, iv)
plaintext := make([]byte, len(ciphertext))
stream.XORKeyStream(plaintext, ciphertext)
// 反序列化数据
return json.Unmarshal(plaintext, result)
}
func main() {
// 示例数据
data := map[string]interface{}{
"name": "John Doe",
"email": "john@example.com",
"age": 30,
}
key := []byte("my-32-byte-long-secret-key-1234567890")
// 加密
encrypted, err := opensslEncrypt(data, key)
if err != nil {
fmt.Println("加密错误:", err)
return
}
fmt.Println("加密结果:", encrypted)
// 解密
var decrypted map[string]interface{}
err = opensslDecrypt(encrypted, key, &decrypted)
if err != nil {
fmt.Println("解密错误:", err)
return
}
fmt.Println("解密结果:", decrypted)
}
对于你提供的具体解密问题,这里是一个修复版本:
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func main() {
// 注意:你的IV是base64编码的,但看起来长度不对
// CTR模式需要16字节IV
iv, _ := base64.StdEncoding.DecodeString("NjIxNDM4MTFjODFhODRkYw==")
fmt.Printf("IV长度: %d字节\n", len(iv))
// AES-256需要32字节密钥
key := []byte("32-byte-long-key-for-aes-256-ctr")
if len(key) < 32 {
// 填充密钥到32字节
paddedKey := make([]byte, 32)
copy(paddedKey, key)
key = paddedKey
}
// 密文
ciphertext, _ := base64.StdEncoding.DecodeString("TktXS3hKWnFZY3YwTXVpR0JKR0pYMkU4SlJ5aWFSZC9DZDJFaW1xdHNxVmZMT2JGUFI0YnRzakxMVkJsS1YyWEpYUEo0R2k4UDhGSERkQkRRTWtxUWcrbnhkU2NtTXlBTHJaM2M4cSs=")
// 创建cipher
block, err := aes.NewCipher(key[:32])
if err != nil {
fmt.Println("创建cipher错误:", err)
return
}
// 使用CTR模式(不是CBC)
stream := cipher.NewCTR(block, iv)
// 解密
plaintext := make([]byte, len(ciphertext))
stream.XORKeyStream(plaintext, ciphertext)
fmt.Println("解密结果:", string(plaintext))
}
关键点:
- 使用
cipher.NewCTR而不是cipher.NewCBCDecrypter - 确保密钥长度为32字节(AES-256)
- IV长度必须为16字节
- CTR模式不需要填充,直接XOR操作
如果你的PHP代码使用了不同的序列化方式,可能需要调整序列化/反序列化部分。对于PHP的serialize(),可以考虑使用第三方库如github.com/techoner/gophp/serialize来处理。

