gpt4 book ai didi

php - 将PHP AES加密移植到Golang

转载 作者:行者123 更新时间:2023-12-03 10:10:18 25 4
gpt4 key购买 nike

我的电子商务提供商使用PHP,Java,JavaScript,C#和Python拥有此库来加密我的请求,因为我的API是使用Go编写的,所以我自然认为,为什么不使用Go呢?
哦,男孩...我不知道我要怎么做。
这是原始的PHP代码:

class AesCrypto {
/**
* Encrypt string with a given key
* @param strToEncrypt
* @param key
* @return String encrypted string
*/
public static function encrypt($plaintext, $key128) {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-128-cbc'));
$cipherText = openssl_encrypt($plaintext, 'AES-128-CBC', hex2bin($key128), 1, $iv);
return base64_encode($iv.$cipherText);
}
}
我用Go尝试了几种稍有不同的方式,我想最起码的是:
func encrypt(text string, key string) string {
data := []byte(text)
block, _ := aes.NewCipher([]byte(key))
gcm, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
panic(err.Error())
}
ciphertext := gcm.Seal(nonce, nonce, data, nil)
encoded := base64.StdEncoding.EncodeToString([]byte(ciphertext))
return encoded
}
我已经创建了用于加密和解密的函数,它们可以正常工作,但是当我将其发送给提供程序时,它将无法正常工作。 key是由电子商务提供商分配的,它是32个长度的字节,我知道选择AES-256的长度是“告诉” newCipher,对吧?则它永远不会对应于AES-128(如PHP函数中所示)。
除了检查我的电子商务提供商的服务或尝试使用PHP代码进行解密之外,我该如何移植此PHP代码?
这是另一种尝试(来自Go加密文档):
func encrypt4(text string, keyString string) string {
key, _ := hex.DecodeString(keyString)
plaintext := []byte(text)
if len(plaintext)%aes.BlockSize != 0 {
panic("plaintext is not a multiple of the block size")
}

block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}

ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}

mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
final := base64.StdEncoding.EncodeToString(ciphertext)
return final
}

最佳答案

GCM与CBC模式不同。该 key 是十六进制编码的,因此32字节的字符串表示16字节(或128位)的 key 。
在CBC模式下,必须填充明文,以便它是块大小的倍数。 PHP的openssl_encrypt自动执行此操作(使用PKCS#5/7),但在Go中必须显式完成。
放在一起,我们最终得到CBC encryption example in the docs的微小变化:

package main

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"io"
)

func encrypt(plaintext, key16 string) string {
padded := pkcs7pad([]byte(plaintext), aes.BlockSize)

key, err := hex.DecodeString(key16)
if err != nil {
panic(err)
}

block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}

buffer := make([]byte, aes.BlockSize+len(padded)) // IV followed by ciphertext
iv, ciphertext := buffer[:aes.BlockSize], buffer[aes.BlockSize:]

if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}

mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, padded)

return base64.StdEncoding.EncodeToString(buffer)
}

func pkcs7pad(plaintext []byte, blockSize int) []byte {
padding := blockSize - len(plaintext)%blockSize

return append(plaintext, bytes.Repeat([]byte{byte(padding)}, padding)...)
}

关于php - 将PHP AES加密移植到Golang,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64129499/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com