go、JS AES(CBC模式)加密解密兼容

本文展示了如何使用JavaScript和Go进行AES-CBC模式的加密和解密,并确保两者之间的兼容性。JavaScript代码使用CryptoJS库进行加密和解密,而Go代码则使用了内置的crypto/aes包。加密和解密过程中,均采用了相同的密钥和填充方式(PKCS7)。示例中展示了明文字符串'hello world'在两种语言中加密和解密的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

js 代码:
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
  
</head>  
<script src="aes/aes.js"></script>  
<!--
<script src="components/pad-zeropadding.js"></script>  
-->
<body>  
<script> 
    var key = CryptoJS.enc.Utf8.parse("7971267812365mn8");
    var plaintText = 'hello world'; // 明文
    var iv=key;  //16位字符串
    var encryptedData = CryptoJS.AES.encrypt(plaintText, key, {
        iv:  key,
        mode: CryptoJS.mode.CBC,  
        padding: CryptoJS.pad.Pkcs7
    });  
  
    console.log("加密前:"+plaintText);  
    console.log("加密后:"+encryptedData);    //Pkcs7:   WoCzvm6eZiM4/bx5o/CzGw==
                                              //ZeroPadding :   cUYmaJktt7P+dqv+Ijds9g==

    console.log("加密后 base64:"+encryptedData.ciphertext.toString(CryptoJS.enc.Base64));

    encryptedData = encryptedData.ciphertext.toString();  
    console.log("解密前-no-hex:"+encryptedData); 
    var encryptedHexStr = CryptoJS.enc.Hex.parse(encryptedData);  
    console.log("解密前hex:"+encryptedHexStr); 
    var encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr);  
    console.log("解密前:"+encryptedBase64Str);  
    var decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, key, {
        iv:  key,
        mode: CryptoJS.mode.CBC,  
        padding: CryptoJS.pad.Pkcs7  
    });  
  
    var decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8);  
    console.log("解密后:"+decryptedStr);  
</script>  
</body>  
</html>

go代码:

package main

import (
    "bytes"
    "crypto/aes"
    "crypto/cipher"
    "en_de/cryption"
    "encoding/base64"
    "fmt"
)

////////////////////////////////////////////////////////////////////////////////
func testAes111() {
    // AES-128。key长度:16, 24, 32 bytes 对应 AES-128, AES-192, AES-256
    key := []byte("7971267812365mn8")
    result, err := AesEncrypt([]byte("hello world"), key)
    if err != nil {
        panic(err)
    }
    fmt.Println("加密后:",base64.StdEncoding.EncodeToString(result))    //zero UR5c4C1iW5mIdxrv5rxo4w==,pkcs jE7BUAKWpdJWb2ulcFWd/g==  和pthon,js相同
    origData, err := AesDecrypt(result, key)
    if err != nil {
        panic(err)
    }
    fmt.Println("解密后:",string(origData))
}

func AesEncrypt(origData, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize()
    origData = PKCS5Padding(origData, blockSize)
    //origData = ZeroPadding(origData, block.BlockSize())
    blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])  //iv=key
    crypted := make([]byte, len(origData))
    // 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
    // crypted := origData
    blockMode.CryptBlocks(crypted, origData)
    return crypted, nil
}

func AesDecrypt(crypted, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize()
    blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
    origData := make([]byte, len(crypted))
    // origData := crypted
    blockMode.CryptBlocks(origData, crypted)
    origData = PKCS5UnPadding(origData)
    // origData = ZeroUnPadding(origData)
    return origData, nil
}

func ZeroPadding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{0}, padding)
    return append(ciphertext, padtext...)
}

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

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}

func PKCS5UnPadding(origData []byte) []byte {
    length := len(origData)
    // 去掉最后一个字节 unpadding 次
    unpadding := int(origData[length-1])
    return origData[:(length - unpadding)]
}
////////////////////////////////////////////////////
func main() {
    testAes111()
    return
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值