为了账号安全,请及时绑定邮箱和手机立即绑定

在golang中编码字符串aes-128 ecb并在js中解密

在golang中编码字符串aes-128 ecb并在js中解密

Go
皈依舞 2022-12-26 11:17:21
我正在尝试在 golang 服务器上加密字符串,我有一个 aes-128 加密实用程序func EncryptAES(key []byte, plaintext string) (string, error) {    // create cipher    c, err := aes.NewCipher(key)    if err != nil {        return "", err    }    // allocate space for ciphered data    out := make([]byte, len(plaintext))    for i := 1; i <= len(plaintext)/16; i++ {        tempBuf := make([]byte, 16)        offset := (i - 1) * 16        limit := offset + 16        // encrypt        c.Encrypt(tempBuf, []byte(plaintext[offset:limit]))        for j := 0; j < len(tempBuf); j++ {            out[offset+j] = tempBuf[j]        }    }    // return hex string    return hex.EncodeToString(out), nil}在那之后我正在尝试做类似的事情    hasher := sha256.New()    hasher.Write([]byte(word))    sha := hasher.Sum(nil)    cypherText := word + userSessionKey    for len([]byte(cypherText))%16 != 0 {        cypherText += "0"    }    sha128 := sha[:len(sha)/2]    captchaKey, err := utils.EncryptAES([]byte(hex.EncodeToString(sha128)), cypherText)    if err != nil {        SendErrorResponse(ctx, fasthttp.StatusInternalServerError, []byte("error generating aes session key "+err.Error()))        return    }但是对于这个密钥和密文,我在加密/解密 aes 网站上收到这个错误用于解码的 js func 也不起作用async function decryptAES128(key, cipherText){    let hash = CryptoJS.SHA256(key).toString();    hash = hash.substring(0, hash.length/2);    console.log(hash);    console.log(cipherText)    const bytes = await CryptoJS.AES.decrypt(CryptoJS.enc.Hex.parse(cipherText), CryptoJS.enc.Hex.parse(hash), { mode: CryptoJS.mode.ECB });    return CryptoJS.enc.Utf8.stringify(bytes.words)}什么都不打印
查看完整描述

1 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

cypherText如果明文的大小(顺便说一下,这是一个误导性术语)不是块大小(AES 为 16 字节)的整数倍,则Go 代码会填充 0x30 值。使用密码 ( ) 的 SHA256 值的前 16 个字节的十六进制编码的 UTF-8 编码作为密钥word。密文是十六进制编码的。

在线工具解密失败,因为在线工具使用PKCS#7 padding,密文是Base64解码的。为了能够解密,必须禁用默认的 PKCS#7 填充并且必须对密文进行十六进制解码,请参见CyberChef

使用 JavaScript 代码解密失败,因为 CryptoJS 默认使用 PKCS#7 填充,密钥被十六进制解码,并且密文未作为CipherParams对象传递。为了能够解密,必须禁用默认的 PKCS#7 填充,密钥必须采用 UTF-8 编码,并且密文必须作为CipherParams对象传递:

var password = 'день';

var key = CryptoJS.SHA256(password).toString();

key = key.substring(0, key.length/2);


var ciphertext = '46ef70c1193fa29024595964a0eb0157c4e6602da6c1429f8a2b81146f79e798'

var decrypted = CryptoJS.AES.decrypt(

    {ciphertext: CryptoJS.enc.Hex.parse(ciphertext)}, // Fix 1: pass a CipherParams object

    CryptoJS.enc.Utf8.parse(key), // Fix2: UTF-8 encode the key

    { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding }); // Fix 3: disable padding

console.log(decrypted.toString(CryptoJS.enc.Utf8));

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

给出解密后的 UTF-8 解码数据:деньBvFGlrXeWCnPTwFC00000000


安全性:ECB 不使用 IV,因此不安全。如今,应用了经过身份验证的加密(例如 GCM),但至少是一种带有 IV 的模式(例如 CBC)。
此外,使用摘要作为密钥派生函数 (KDF) 是不安全的。为此有专门的功能(例如 Argon2 或 PBKDF2)。另外,应该直接使用KDF的字节串,而不是hex编码的UTF-8编码,这样会降低安全性。
应用的 0x30 填充通常是不可靠的。更可靠的是例如 PKCS#7 填充。


查看完整回答
反对 回复 2022-12-26
  • 1 回答
  • 0 关注
  • 415 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号