【知识点】 包含PHP的知识点:str_pad、sha1、pack、base64_encode、base64_decode、strlen、substr、openssl_decrypt、openssl_encrypt。 包含的Go知识点: s
【知识点】
包含PHP的知识点:str_pad、sha1、pack、base64_encode、base64_decode、strlen、substr、openssl_decrypt、openssl_encrypt。
包含的Go知识点:
sha1 哈希加密,要注意下返回的是字节数组
string([]byte) 字节数组转换成字符串,注意这里转换的二进制字符串,很多乱码
hex.EncodeToString 字节数组转成16进制,示例中有用到来转换sha1得到的值
strconv.ParseUint 字符串转换为无符号int类型,对应php的pack方法
base64.StdEncoding.DecodeString base64解码,对应php的base64_decode
base64.StdEncoding.EncodeString base64编码,对应php的base64_encode
strings.Replace 替换字符串,用于替换base64字符串的安全字符-和_
rand 随机字符串
crypto/cipher aes加解密模块
参考:aes-256-gcm_python3_php7_golang_mb5fe94870638be的技术博客_51CTO博客
【需求背景】
在对接美团小游戏的时候,支付成功通知,使用了【sha1】的签名还有【aes-256-GCm】的加密数据。官方只有php7.1以上的例子,但是项目使用了golang,需要转换下。
接口文档:
文档上的php-demo例子:
//PHP demo(版本使用7.1以上)function createKey($appId, $appSecret) {$aaa = base64_encode(str_pad(sha1($appId.'&'.$appSecret,true), 32,pack('V', 0)));return $aaa;}function encryptSHA1Str($secreTKEy, $encryptData) {$aaa = $encryptData.$secretKey;$sign = sha1($aaa);return $sign;}function decryptWithAESGCM256($secretKey, $encryptData) {$decodeEncrypt = urlsafe_b64decode($encryptData);$decodeSecret = base64_decode($secretKey);$data = openssl_decrypt(substr($decodeEncrypt, 16, -16), 'aes-256-gcm', $decodeSecret, 1, substr($decodeEncrypt, 0, 16), substr($decodeEncrypt, -16, 16));return $data;}function urlsafe_b64decode($string) {$data = str_replace(array('-','_'),array('+','/'),$string);$mod4 = strlen($data) % 4;if ($mod4) {$data .= substr('====', $mod4);}return base64_decode($data);}
【GO代码示例】
package mainimport ("crypto/aes""crypto/cipher""crypto/sha1""encoding/base64""errors""fmt""io""math/rand""strconv""strings")func main(){secretKey := GenSecretKey("appid12456","appsecret123456")data :="{\"bizOrderId\":\"55001151519674220220723112146446\",\"mgcId\":\"234112419424942\",\"mgcOrderId\":\"106631144674\",\"payStatus\":\"OK\",\"price\":\"100\"}\n"encryptData,_ := SetCallbackData(secretKey,data)//得到加密后的base64字符串fmt.Println(encryptData)decryptData,_ := GetCallbackData(secretKey,encryptData)//得到解密后的json字符串fmt.Println(decryptData)}//实现php的sha1()方法,返回的是byte转换的字符串,如果需要转成16进制,可以使用hex.EncodeToStringfunc GetSha1(str string) string {h := sha1.New()io.WriteString(h, str)return string(h.Sum(nil))}//右边补全字符串实现方法,主要实现php的str_pad()方法func StrPadRight(input string, padLength int, padString string) string {output := ""inputLen := len(input)if inputLen >= padLength {return input}ll := padLength - inputLenfor i := 1; i <= ll; i = i + len(padString) {output += padString}return input + output}//生成密钥func GenSecretKey(appId string, appSecret string) (secretKey string) {key := appId + "&" + appSecretsha1_str := GetSha1(key)str10 := "0"pack64, _ := strconv.ParseUint(str10, 10, 32)//对应php的pack()方法,字符串转换为uint类型fmt.Println(pack64)pack32 := uint32(pack64)str_pad := StrPadRight(sha1_str, 32, string(pack32))secretKey = base64.StdEncoding.EncodeToString([]byte(str_pad))return secretKey}func GetCallbackData(secretKey string, encryptData string) (result_str string, err error) {decodeSecretKeyByte, _ := base64.StdEncoding.DecodeString(secretKey)decodeSecretKey := string(decodeSecretKeyByte)//$data = openssl_decrypt(substr($decodeEncrypt, 16, -16), 'aes-256-gcm', $decodeSecret, 1, substr($decodeEncrypt, 0, 16), substr($decodeEncrypt, -16, 16));orderSuccessPayInfoByte, err2 := DecodeAesGcm(encryptData, decodeSecretKey,"")result_str = string(orderSuccessPayInfoByte)if err2 != nil {return result_str, errors.New("decode error")}return result_str, err}func SetCallbackData(secretKey string, data string) (result_str string, err error) {decodeSecretKeyByte, _ := base64.StdEncoding.DecodeString(secretKey)decodeSecretKey := string(decodeSecretKeyByte)orderSuccessPayInfoByte, err2 := EncodeAesGcm(data, decodeSecretKey,"")result_str = string(orderSuccessPayInfoByte)if err2 != nil {return result_str, errors.New("encode error")}return result_str, err}//url安全模式decode字符串func UrlSafeB64decode(str string) (result []byte) {str = strings.Replace(str, "-", "+", -1)str = strings.Replace(str, "_", "/", -1)mod4 := len(str) % 4if mod4 != 0 {str = str + "===="[0:mod4]}result, _ = base64.StdEncoding.DecodeString(str)return result}//base64字符串,替换转换为安全模式func UrlSafeB64encode(str string) (result string) {str = strings.Replace(str, "+", "-", -1)str = strings.Replace(str, "/", "_", -1)return str}//使用aes-256-gcm方式解密字符串,主要针对php的openssl_decrypt()方法,注意在php7.1后增加了tag和add参数func DecodeAesGcm(encryptData string, hex_key string,hex_add string) ([]byte, error) {tagSize :=16//nonceSize,tag的长度,用于open时候生成tag,默认12key := []byte(hex_key)add := []byte(hex_add)block, err := aes.NewCipher(key) //生成加解密用的blockif err != nil {return []byte(""), err}//根据不同加密算法,也有不同tag长度的方法设定和调用,比如NewGCMWithTagSize、newGCMWithNonceAndTagSizeaesgcm, err := cipher.NewGCMWithNonceSize(block, tagSize)if err != nil {return []byte(""), err}decodeEncryptStr := UrlSafeB64decode(encryptData)ciphertext := decodeEncryptStrif len(ciphertext) <= aesgcm.NonceSize() { // 长度应该>ivreturn []byte(""), errors.New("string: too short") //解密失败}iv := ciphertext[:aesgcm.NonceSize()] //分离出IVciphertext = ciphertext[aesgcm.NonceSize():] // 密文,tag是调用open方法时候通过密文和前面new时候传的size来进行截取的plaintext, err := aesgcm.Open(nil, iv, ciphertext, add)return plaintext, err}//使用aes-256-gcm加密数据,主要针对php的openssl_encrypt()方法,注意在php7.1后增加了tag和add参数func EncodeAesGcm(data string, hex_key string, hex_add string) (result string, error error) {tagSize :=16 //nonceSize,tag的长度,用于open时候生成tag,默认12key := []byte(hex_key)add := []byte(hex_add)block, err := aes.NewCipher(key) //生成加解密用的blockif err != nil {return result, err}//根据不同加密算法,也有不同tag长度的方法设定和调用,比如NewGCMWithTagSize、newGCMWithNonceAndTagSizeaesgcm, err := cipher.NewGCMWithNonceSize(block, tagSize)if err != nil {return result, err}plaintext := []byte(data)iv := make([]byte, tagSize) // NonceSize=12rand.Read(iv) //获取随机值ciphertext := aesgcm.Seal(iv, iv, plaintext, add) //加密,密文为:iv+密文+tagresult = base64.StdEncoding.EncodeToString(ciphertext)result = UrlSafeB64encode(result)return result, nil // 生成的BS64}
来源地址:https://blog.csdn.net/yjr_aaron/article/details/126015480
--结束END--
本文标题: Go 实现aes-256-gcm加解密处理过程
本文链接: https://lsjlt.com/news/394122.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0