簡體   English   中英

AES/CBC 在 golang 中加密,在有角度的 CryptoJS 中解密

[英]AES/CBC encrypt in golang,decrypt in angular CryptoJS

我正在嘗試使用帶有 PKCS7 填充的 AES CBC 模式在 Go 中加密數據並在 Angular 中解密它。 但是當我嘗試在 Angular 中解密數據時,它沒有返回任何內容

去代碼:


package main

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

func main() {
    secret := []byte("28cEVB4BUE7GKNwjuRhN3szK5E3!&q*y")
    data := []byte("Test")
    encResult, err := Encrypt(data, secret)
    fmt.Println("encResult", encResult)
    fmt.Println("enc err", err)
    //  encrypted := "U2FsdGVkX1+LU7rE47VtIDwGIOsJa05BzOmAzQfdbVk="

    result, err := Dncrypt(encResult, secret)
    fmt.Println("decrypted result", result)
    fmt.Println("decryption err", err)

}

/*CBC encryption Follow the example code of the golang standard library
But there is no padding inside, so make up
*/

// Use PKCS7 to fill, IOS is also 7
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}

func PKCS7UnPadding(origData []byte) []byte {
    length := len(origData)
    unpadding := int(origData[length-1])
    return origData[:(length - unpadding)]
}

//aes encryption, filling the 16 bits of the key key, 24, 32 respectively corresponding to AES-128, AES-192, or AES-256.
func AesCBCEncrypt(rawData, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    //fill the original
    blockSize := block.BlockSize()
    rawData = PKCS7Padding(rawData, blockSize)
    // Initial vector IV must be unique, but does not need to be kept secret
    cipherText := make([]byte, blockSize+len(rawData))
    //block size 16
    iv := cipherText[:blockSize]
    fmt.Println("iv", iv)

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

    //block size and initial vector size must be the same
    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(cipherText[blockSize:], rawData)

    return cipherText, nil
}

func AesCBCDncrypt(encryptData, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    blockSize := block.BlockSize()

    if len(encryptData) < blockSize {
        panic("ciphertext too short")
    }
    iv := encryptData[:blockSize]
    encryptData = encryptData[blockSize:]

    // CBC mode always works in whole blocks.
    if len(encryptData)%blockSize != 0 {
        panic("ciphertext is not a multiple of the block size")
    }

    mode := cipher.NewCBCDecrypter(block, iv)

    // CryptBlocks can work in-place if the two arguments are the same.
    mode.CryptBlocks(encryptData, encryptData)
    // Unfill
    encryptData = PKCS7UnPadding(encryptData)
    return encryptData, nil
}

func Encrypt(rawData, key []byte) (string, error) {
    data, err := AesCBCEncrypt(rawData, key)
    if err != nil {
        return "", err
    }
    return base64.StdEncoding.EncodeToString(data), nil
}

func Dncrypt(rawData string, key []byte) (string, error) {
    data, err := base64.StdEncoding.DecodeString(rawData)
    if err != nil {
        return "", err
    }
    dnData, err := AesCBCDncrypt(data, key)
    if err != nil {
        return "", err
    }
    return string(dnData), nil
}

Angular/CryptoJs 代碼:

var CryptoJS = require("crypto-js");
var iv   = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var decrypted= CryptoJS.AES.decrypt("hKZ8CZgDopjCthfVZf7VmkSlX00nAJXpzNPRIUhGsO8=","28cEVB4BUE7GKNwjuRhN3szK5E3!&q*y",{iv:iv, padding: CryptoJS.pad.Pkcs7})
console.log("decrypted",decrypted.toString());  

我從 cryptoJS 解密方法得到一個空響應。

iv 對於cryptoJS 的值應該是多少?

Go 代碼生成一個隨機 IV 並在 CBC 模式下使用 AES-256 和 PKCS7 填充執行加密。 IV 與密文IV|ciphertext ,結果是 Base64 編碼的。 密鑰是通過 Utf8 編碼從給定字符串生成的。

注意 Go 代碼

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

用隨機值初始化 IV。 所以IV的輸出應該在那之后。 由於它是在發布的代碼中之前打印的,因此顯示了一個零 IV,但這與使用的 IV 不對應。
順便說一下,對於解密,不需要顯式輸出,因為如前所述,代碼連接了 IV 和密文。


在 CryptoJS 代碼中,使用了零 IV,可能是因為 Go 代碼中的輸出不正確。 相反,IV 和密文必須分開。
此外,密鑰作為字符串傳遞。 這是不正確的,因為 CryptoJS 將字符串解釋為密碼並執行基於密碼的密鑰派生。 相反,鍵必須作為WordArray傳遞。
由於密鑰在 Go 代碼中是 Utf8 編碼的,因此必須應用 Utf8 編碼器(另請參閱其他答案)。

CBC 和 PKCS7 填充是默認值,可以但不需要指定。


以下 CryptoJS 代碼中的密文是使用 Go 代碼生成的:

 // Separate IV and ciphertext var data = CryptoJS.enc.Base64.parse("WL7oDghTeEbjZ6QPeb/TGuDGijktQ4PZS7+wd0Ayu8Y="); // from Go code var iv = CryptoJS.lib.WordArray.create(data.words.slice(0, 4)); // first 4 words = 16 bytes var ct = CryptoJS.lib.WordArray.create(data.words.slice(4)); // rest // Decrypt var decrypted = CryptoJS.AES.decrypt( {ciphertext: ct}, // alternatively as Base64 encoded string CryptoJS.enc.Utf8.parse("28cEVB4BUE7GKNwjuRhN3szK5E3!&q*y"), // Utf8 encode key string {iv:iv} ); console.log("Decrypted: ", decrypted.toString(CryptoJS.enc.Utf8)); // Decrypted: Test
 <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

並將密文正確解密為Test

試試這個,確保您使用相同的密鑰進行加密和解密

//The get method is use for decrypt the value.
get(keys, value){
    var key = CryptoJS.enc.Utf8.parse(keys);
    var iv = CryptoJS.enc.Utf8.parse(keys);
    var decrypted = CryptoJS.AES.decrypt(value, key, {
        keySize: 128 / 8,
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    
    return decrypted.toString(CryptoJS.enc.Utf8);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM