亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將 PHP AES 加密移植到 Golang

將 PHP AES 加密移植到 Golang

Go
BIG陽 2022-07-04 16:46:46
我的電子商務提供商在 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 個字節,我知道長度“告訴”newCipher選擇 AES-256,對嗎?那么它永遠不會對應于 AES-128,如 PHP func 中所示。除了檢查我的電子商務提供商的服務或嘗試使用 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}
查看完整描述

1 回答

?
白板的微信

TA貢獻1883條經驗 獲得超3個贊

GCM 與 CBC 模式不同。密鑰是十六進制編碼的,所以一個 32 字節的字符串代表一個 16 字節(或 128 位)的密鑰。

在 CBC 模式下,明文必須被填充,以便它是塊大小的倍數。PHP 的 openssl_encrypt 自動執行此操作(使用PKCS#5/7),但在 Go 中必須明確完成。

綜上所述,我們最終得到了文檔中 CBC 加密示例的輕微變化:

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)...)

}


查看完整回答
反對 回復 2022-07-04
  • 1 回答
  • 0 關注
  • 260 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號