如何使用aes-js包解密在vuejs中加密的Go中的密文
How to decrypt a ciphertext in Go which is encrypted in vuejs using aes-js package
Vuejs 中的代码 -
var message = "Hello World"
var keyBytes = aesjs.utils.utf8.toBytes("akey123")
var iv = CryptoJS.lib.WordArray.random(8).toString()
var ivBytes = aesjs.utils.utf8.toBytes(iv)
var messageBytes = aesjs.utils.utf8.toBytes(message);
var aesCfb = new aesjs.ModeOfOperation.cfb(keyBytes, ivBytes);
var encryptedBytes = aesCfb.encrypt(messageBytes);
var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
我发送到 GO 的数据 - {"iv": iv, "cipher": encryptedHex}
GO 中的代码
func DecryptCipher(iv, cipher string) {
key := []byte("akey123")
iv := []byte(iv)
cipherText, _ := hex.DecodeString(cipher)
block, err := aes.NewCipher(key)
if err != nil {
log.Println(err)
}
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(cipherText, cipherText)
fmt.Println("data", string(cipherText))
}
预期输出:"Hello World"
实际输出:@��Sa 1����Ig{��
有人可以帮助我并告诉我上面的代码中缺少什么吗?
提前致谢!
这两个代码中都有几个缺陷阻止了执行。但是,由于两者在您的系统上都是 运行,因此这些似乎是 copy/paste 错误:
- 密钥太短。 AES 要求密钥大小为 16、24 或 32 字节。
- 关于
iv
和 cipher
的 Go 代码中存在命名冲突。
这些修复后,程序可以执行,但解密失败。问题是由不同的 CFB 变体引起的:在 aes-js 代码中,使用 CFB8,而在 Go 代码中,使用 CFB128。这里的数字表示移位寄存器中移位的位数[1]。
去只支持CFB128,至少没有更深的修改[2][3]。
aes-js默认使用CFB8。但是,CFB 变体也可以通过 cfb 构造函数的第三个参数 显式 定义。 [4]:
可以更改 CFB128
var segmentSize = 16;
var aesCfb = new aesjs.ModeOfOperation.cfb(keyBytes, ivBytes, segmentSize);
注意该值必须以字节为单位指定,即1对应CFB8,16对应CFB128。
CFB是流密码,所以任意长度的明文可以加密不带填充,密文长度等于明文 [5]. Unfortunately there seems to be a bug in aes-js [6] 要求明文的长度是段大小的整数倍,即在 CFB128 的情况下为 16 字节。否则,将显示以下错误消息:
invalid plaintext size (must be segmentSize bytes)
即,如果使用的明文还没有这个长度,则该错误需要显式填充,尽管流密码实际上不需要填充。
针对这些问题的背景,您可能希望使用不同的模式或不同的库。
此外:
- IV 不是问题的原因:在当前示例中,
CryptoJS.lib.WordArray.random(8)
随机创建一个 WordArray
8 个字节,并将其编码为长度为 16 的十六进制字符串使用 toString()
的字节数。这个十六进制字符串是 Utf8 编码的,因此在两种代码中是相同的。尽管如此,评论中关于 IV 的评论当然是正确的。
- aes-js 错误可能与过时的 Python 库 PyCrypto 中的相同错误有关,后者已在后续 PyCryptodome 中修复[7]。
- 在[8] the CFB mode is discussed, the 2nd answer focuses on the different CFB variants [9]。
Vuejs 中的代码 -
var message = "Hello World"
var keyBytes = aesjs.utils.utf8.toBytes("akey123")
var iv = CryptoJS.lib.WordArray.random(8).toString()
var ivBytes = aesjs.utils.utf8.toBytes(iv)
var messageBytes = aesjs.utils.utf8.toBytes(message);
var aesCfb = new aesjs.ModeOfOperation.cfb(keyBytes, ivBytes);
var encryptedBytes = aesCfb.encrypt(messageBytes);
var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
我发送到 GO 的数据 - {"iv": iv, "cipher": encryptedHex}
GO 中的代码
func DecryptCipher(iv, cipher string) {
key := []byte("akey123")
iv := []byte(iv)
cipherText, _ := hex.DecodeString(cipher)
block, err := aes.NewCipher(key)
if err != nil {
log.Println(err)
}
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(cipherText, cipherText)
fmt.Println("data", string(cipherText))
}
预期输出:"Hello World" 实际输出:@��Sa 1����Ig{��
有人可以帮助我并告诉我上面的代码中缺少什么吗? 提前致谢!
这两个代码中都有几个缺陷阻止了执行。但是,由于两者在您的系统上都是 运行,因此这些似乎是 copy/paste 错误:
- 密钥太短。 AES 要求密钥大小为 16、24 或 32 字节。
- 关于
iv
和cipher
的 Go 代码中存在命名冲突。
这些修复后,程序可以执行,但解密失败。问题是由不同的 CFB 变体引起的:在 aes-js 代码中,使用 CFB8,而在 Go 代码中,使用 CFB128。这里的数字表示移位寄存器中移位的位数[1]。
去只支持CFB128,至少没有更深的修改[2][3]。
aes-js默认使用CFB8。但是,CFB 变体也可以通过 cfb 构造函数的第三个参数 显式 定义。 [4]:
可以更改 CFB128var segmentSize = 16;
var aesCfb = new aesjs.ModeOfOperation.cfb(keyBytes, ivBytes, segmentSize);
注意该值必须以字节为单位指定,即1对应CFB8,16对应CFB128。
CFB是流密码,所以任意长度的明文可以加密不带填充,密文长度等于明文 [5]. Unfortunately there seems to be a bug in aes-js [6] 要求明文的长度是段大小的整数倍,即在 CFB128 的情况下为 16 字节。否则,将显示以下错误消息:
invalid plaintext size (must be segmentSize bytes)
即,如果使用的明文还没有这个长度,则该错误需要显式填充,尽管流密码实际上不需要填充。
针对这些问题的背景,您可能希望使用不同的模式或不同的库。
此外:
- IV 不是问题的原因:在当前示例中,
CryptoJS.lib.WordArray.random(8)
随机创建一个WordArray
8 个字节,并将其编码为长度为 16 的十六进制字符串使用toString()
的字节数。这个十六进制字符串是 Utf8 编码的,因此在两种代码中是相同的。尽管如此,评论中关于 IV 的评论当然是正确的。 - aes-js 错误可能与过时的 Python 库 PyCrypto 中的相同错误有关,后者已在后续 PyCryptodome 中修复[7]。
- 在[8] the CFB mode is discussed, the 2nd answer focuses on the different CFB variants [9]。