AES-256-CBC 加密 Golang 和 PHP
AES-256-CBC encryption Golang and PHP
我正在尝试在 golang 中实现 AES-256-CBC 加密。我有一个已经使用多年的工作 PHP 代码。我正在 Golang 中获取加密值,但对于相同的 payload/key/iv 组合,这些值与 PHP 的输出不匹配。
为了简化,我在下面的代码中对 payload/key/iv 进行了硬编码。我还从我的 go 代码中删除了详细的错误消息。
这是我的GO代码
func encryption() {
plaintext := []byte("12345678912345678912345678900000")
key, _ := base64.StdEncoding.DecodeString("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=")
iv, _ := hex.DecodeString("162578ddce177a4a7cb2f7c738fa052d")
/*php seem to use PKCS7 padding to make the source string match the blocksize
requirement for AES-256-CBC.
From what I understand, I need to do padding manually in Golang.
Correct me if wrong */
plaintext, _ = Pkcs7Pad(plaintext, aes.BlockSize)
block, _ := aes.NewCipher(key)
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
fmt.Printf("EncryptedText %v\n", string(ciphertext))
fmt.Printf("EncryptedText as hex %v\n", hex.EncodeToString(ciphertext))
}
func Pkcs7Pad(b []byte, blocksize int) ([]byte, error) {
if blocksize <= 0 {
return nil, errors.New("Invalid block size")
}
if b == nil || len(b) == 0 {
return nil, errors.New("Invalid block size")
}
n := blocksize - (len(b) % blocksize)
pb := make([]byte, len(b)+n)
copy(pb, b)
copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
return pb, nil
}
我的 Go 输出是
EncryptedText |8??X?z??F ?0ĺe?,??G?V?
Gce??dM????z?,*ȁҼ
EncryptedText as hex 7c38bad658907a81d14620c930c4ba658c1f022cdb1392479856cc0a471d6365dfc5644db6b28cef7ac02c2ac881d2bc
我有一个 PHP 代码来完成同样的任务,它给了我不同的输出。
function encryption() {
$plaintext = "12345678912345678912345678900000";
$key = base64_decode("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=");
$iv = hex2bin("162578ddce177a4a7cb2f7c738fa052d");
//php openssl_encrypt function seem to use pkcs7pad to make the source string match the blocksize requirement for AES-256-CBC
$ciphertext = openssl_encrypt($plaintext, 'AES-256-CBC', $key, 0, $iv );
print $ciphertext;
}
并且 PHP 输出是
fDi61liQeoHRRiDJMMS6ZYwfAizbE5JHmFbMCkcdY2XfxWRNtrKM73rALCrIgdK8
显然,我想让我的 Golang 实现获得与 PHP 相同的输出。由于我需要与我的 Golang 代码和现有 PHP 代码进行通信,因此我希望在 PHP 和 Golang 中进行相同的加密和解密工作。
有什么想法吗?
您的方法存在一些问题:
openssl_encrypt
,默认情况下,输出 base 64 编码的字符串(非十六进制)
- 我怀疑你的
pkcs7Pad
(你没有包括)正在做一些意想不到的事情(因为你跳过了 mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
[=30 中 ciphertext
的开始=]
注意:我无法复制你的结果,因为你没有包含你的 pkcs7Pad
(link 到 playground 是一个很好的想法,因为它确保其他人能够复制您的问题)。
我相信下面的代码会给出你正在寻找的东西(结果匹配 php - 我没有做任何进一步的测试):
func main() {
plaintext := []byte("12345678912345678912345678900000")
key, err := base64.StdEncoding.DecodeString("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=")
if err != nil {
panic(err)
}
iv, err := hex.DecodeString("162578ddce177a4a7cb2f7c738fa052d")
if err != nil {
panic(err)
}
plaintext = pkcs7Pad(plaintext, aes.BlockSize)
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, plaintext)
fmt.Printf("EncryptedText %v\n", string(ciphertext))
fmt.Printf("EncryptedText as hex %v\n", hex.EncodeToString(ciphertext))
fmt.Printf("EncryptedText as base 64 %v\n", base64.StdEncoding.EncodeToString(ciphertext))
}
func pkcs7Pad(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
试试
我正在尝试在 golang 中实现 AES-256-CBC 加密。我有一个已经使用多年的工作 PHP 代码。我正在 Golang 中获取加密值,但对于相同的 payload/key/iv 组合,这些值与 PHP 的输出不匹配。
为了简化,我在下面的代码中对 payload/key/iv 进行了硬编码。我还从我的 go 代码中删除了详细的错误消息。
这是我的GO代码
func encryption() {
plaintext := []byte("12345678912345678912345678900000")
key, _ := base64.StdEncoding.DecodeString("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=")
iv, _ := hex.DecodeString("162578ddce177a4a7cb2f7c738fa052d")
/*php seem to use PKCS7 padding to make the source string match the blocksize
requirement for AES-256-CBC.
From what I understand, I need to do padding manually in Golang.
Correct me if wrong */
plaintext, _ = Pkcs7Pad(plaintext, aes.BlockSize)
block, _ := aes.NewCipher(key)
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
fmt.Printf("EncryptedText %v\n", string(ciphertext))
fmt.Printf("EncryptedText as hex %v\n", hex.EncodeToString(ciphertext))
}
func Pkcs7Pad(b []byte, blocksize int) ([]byte, error) {
if blocksize <= 0 {
return nil, errors.New("Invalid block size")
}
if b == nil || len(b) == 0 {
return nil, errors.New("Invalid block size")
}
n := blocksize - (len(b) % blocksize)
pb := make([]byte, len(b)+n)
copy(pb, b)
copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
return pb, nil
}
我的 Go 输出是
EncryptedText |8??X?z??F ?0ĺe?,??G?V?
Gce??dM????z?,*ȁҼ
EncryptedText as hex 7c38bad658907a81d14620c930c4ba658c1f022cdb1392479856cc0a471d6365dfc5644db6b28cef7ac02c2ac881d2bc
我有一个 PHP 代码来完成同样的任务,它给了我不同的输出。
function encryption() {
$plaintext = "12345678912345678912345678900000";
$key = base64_decode("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=");
$iv = hex2bin("162578ddce177a4a7cb2f7c738fa052d");
//php openssl_encrypt function seem to use pkcs7pad to make the source string match the blocksize requirement for AES-256-CBC
$ciphertext = openssl_encrypt($plaintext, 'AES-256-CBC', $key, 0, $iv );
print $ciphertext;
}
并且 PHP 输出是
fDi61liQeoHRRiDJMMS6ZYwfAizbE5JHmFbMCkcdY2XfxWRNtrKM73rALCrIgdK8
显然,我想让我的 Golang 实现获得与 PHP 相同的输出。由于我需要与我的 Golang 代码和现有 PHP 代码进行通信,因此我希望在 PHP 和 Golang 中进行相同的加密和解密工作。
有什么想法吗?
您的方法存在一些问题:
openssl_encrypt
,默认情况下,输出 base 64 编码的字符串(非十六进制)- 我怀疑你的
pkcs7Pad
(你没有包括)正在做一些意想不到的事情(因为你跳过了mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
[=30 中ciphertext
的开始=]
注意:我无法复制你的结果,因为你没有包含你的 pkcs7Pad
(link 到 playground 是一个很好的想法,因为它确保其他人能够复制您的问题)。
我相信下面的代码会给出你正在寻找的东西(结果匹配 php - 我没有做任何进一步的测试):
func main() {
plaintext := []byte("12345678912345678912345678900000")
key, err := base64.StdEncoding.DecodeString("cidRgzwfcgztwae/mccalIeedOAmA/CbU3HEqWz1Ejk=")
if err != nil {
panic(err)
}
iv, err := hex.DecodeString("162578ddce177a4a7cb2f7c738fa052d")
if err != nil {
panic(err)
}
plaintext = pkcs7Pad(plaintext, aes.BlockSize)
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, plaintext)
fmt.Printf("EncryptedText %v\n", string(ciphertext))
fmt.Printf("EncryptedText as hex %v\n", hex.EncodeToString(ciphertext))
fmt.Printf("EncryptedText as base 64 %v\n", base64.StdEncoding.EncodeToString(ciphertext))
}
func pkcs7Pad(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
试试