当前位置: 首页 > 知识库问答 >
问题:

用golang加密AES/CBC,用angular密码解密

子车雅珺
2023-03-14

我正在尝试在Go中加密数据,并使用带有PKCS7填充的AES CBC模式在Angular中解密。但是当我尝试在Angular中解密数据时,它没有返回任何内容

Go代码:


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());  

我从加密JS解密方法中得到一个空响应。

cryptoJS的iv值应该是多少?

共有2个答案

堵景天
2023-03-14

试试这个,确保加密和解密使用相同密钥

//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);
}
马俊
2023-03-14

Go代码生成一个随机IV,并在带有PKCS7填充的CBC模式下使用AES-256执行加密。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代码生成的:

js prettyprint-override">// 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
html lang-html prettyprint-override"><script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
 类似资料:
  • 一定有人知道,在网上没有任何一个工作的例子...

  • 我只想用这3种模式测试openSSL中的AES:128192和256密钥长度,但我解密的文本与我的输入不同,我不知道为什么。此外,当我传递一个巨大的输入长度(比如1024字节)时,我的程序显示。。。我的意见总是一样的,但这并不重要,至少现在是这样。代码如下: 编辑: 当我将输出大小更改为而不是时,我得到了结果: 那么,是否有可能存在Outpus大小和IV大小的问题?它们应该有什么尺寸(AES-CB

  • 我希望有一个用C编写的程序,可以在没有openssl这样的大型库的帮助下,用AES-CBC对字符串进行编码/解码。 目标: 使用密码短语对字符串进行编码/解码: 因此,应用程序需要接受3个输入参数。。。 输入字符串(待编码)/或已编码字符串(待解码) 用于编码/解码字符串的密码 编码或解码指示器 我对C语言不熟悉(我可以用C#编码)。 我已经找到了https://github.com/kokke/

  • 我遇到的情况是,JSON在PHP的中加密,需要在JAVA中解密。 此包含正确的数据,现在已解密。 现在,问题是当我试图做同样的事情在Java它不起作用:( 这是: 我已经访问了类似的问题,如 AES-256 CBC用php加密,用Java解密,反之亦然 openssl_在java中加密256个CBC原始_数据 无法在Java和PHP之间交换使用AES-256加密的数据 名单还在继续。。。。但是运气

  • 我做了一个简单的文件加密/解密器。它将模式和要操作的文件作为参数。加密时,它生成随机字符串并使用该字符串加密文件。解密文件时,它会提示用户输入密码,并在解密时使用该密码。 我的问题是,解密时得到的不是明文,而是胡言乱语,尽管我小心翼翼地将相同的密钥写入输入。 非常感谢James K Polk提供的加密/解密代码!