首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有无效密钥的“aes-256-cbc”算法的Crypto.decipher.final在解密错误时失败。

具有无效密钥的“aes-256-cbc”算法的Crypto.decipher.final在解密错误时失败。
EN

Stack Overflow用户
提问于 2020-02-05 17:18:21
回答 2查看 1.7K关注 0票数 2

我能够使用node.js密码模块使用“aes-256-cbc”算法使用密码和解密类加密和解密消息,如下所示:

代码语言:javascript
运行
复制
var crypto = require('crypto');

var cipherKey = crypto.randomBytes(32); // aes-256 => key length is 256 bits => 32 bytes
var cipherIV = crypto.randomBytes(16); // aes block size = initialization vector size = 128 bits => 16 bytes
var cipher = crypto.createCipheriv('aes-256-cbc', cipherKey, cipherIV);

var message = 'Hello world';
var encrypted = cipher.update(message, 'utf8', 'hex') + cipher.final('hex');
console.log('Encrypted \'' + message + '\' as \'' + encrypted + '\' with key \''+ cipherKey.toString('hex') + '\' and IV \'' + cipherIV.toString('hex') + '\'');
// Outputs: Encrypted 'Hello world' as '2b8559ce4227c3c3c200ea126cb50957' with key '50f7a656cfa3c4f90796a972b2f6eedf41b589da705fdec95b9d25c180c16cf0' and IV '6b28c13d63af14cf05059a2a2caf370c'

var decipher = crypto.createDecipheriv('aes-256-cbc', cipherKey, cipherIV);
var decrypted = decipher.update(encrypted, 'hex', 'utf8') + decipher.final('utf8');
console.log('Decrypted \'' + encrypted + '\' as \'' + decrypted + '\' with key \''+ cipherKey.toString('hex') + '\' and IV \'' + cipherIV.toString('hex') + '\'');
// Outputs: Decrypted '2b8559ce4227c3c3c200ea126cb50957' as 'Hello world' with key '50f7a656cfa3c4f90796a972b2f6eedf41b589da705fdec95b9d25c180c16cf0' and IV '6b28c13d63af14cf05059a2a2caf370c'

但是,当我试图使用错误的密钥解密消息时,可能是天真的,说明攻击者将无法解密消息,除非密钥是已知的,否则我将得到Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt at Decipheriv.final (internal/crypto/cipher.js:164:28)

代码语言:javascript
运行
复制
var differentCipherKey = crypto.randomBytes(32);
var decipherDifferentKey = crypto.createDecipheriv('aes-256-cbc', differentCipherKey, cipherIV);
decrypted = decipherDifferentKey.update(encrypted, 'hex', 'utf8') + decipherDifferentKey.final('utf8');

我希望得到的是难以理解的文字。bad decrypt在其他方面也有特色,所以无论是关于openssl版本在加密和解密之间的不匹配,还是在同一种情况下过短的初始化向量,我相信我的情况是不同的。AES是否知道加密文本是用不同的密钥生成的?

在节点v12.13.0上进行测试,在Windows10上测试,在运行v10.16.0的repl.it中也进行测试。

编辑:,如答案中所建议的,问题是默认填充,为了查看无法理解的输出,需要手动禁用密码、解密和衬垫上的自动填充:

代码语言:javascript
运行
复制
var requirePadding = 16 - Buffer.byteLength(message, 'utf8');
var paddedMessage = Buffer.alloc(requirePadding, 0).toString('utf8') + message;
cipher.setAutoPadding(false)

这里是完整的例子

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-05 18:19:48

另一个答案正确地指出了这个问题是一个填充问题。我可以这样总结这个问题:

  • 块密码只能对长度为密码块大小的倍数的数据进行操作。(AES的块大小为128位。)
  • 为了使不同大小的输入符合块大小,库添加了填充。此填充具有特定的格式(例如,当添加长度为N的填充时,对输入的最后N个字节重复值N )。
  • 解密时,库检查是否存在正确的填充。由于你的坏解密数据是任意噪音,它是非常不可能有一个有效的垫。

在执行decipher.setAutoPadding(false)之前,您可以使用update关闭此检查。但是,请注意,这将包括您的解密输出中的填充。下面是一个使用修改的repl.it实例setAutoPadding

票数 2
EN

Stack Overflow用户

发布于 2020-02-05 17:43:40

CBC模式需要填充,您没有定义填充模式,但是库为您应用了一个默认模式。默认的是PKCS7Padding,它支持块大小从1到256字节不等。

每个填充有一个特定的格式,这样就可以从解密文本中唯一地删除它,而不会有歧义。例如,如果明文缺少两个字符来匹配AES中的块大小(16字节),那么PKCS7填充将添加0202 (十六进制),表示添加了2个字符,每个字符都具有添加字符数的值。如果5缺少0505050505等,在下面的xy是一个字节。

代码语言:javascript
运行
复制
xyxyxyxyxyxyxyxyxyxyxyxyxyxyxy01
xyxyxyxyxyxyxyxyxyxyxyxyxyxy0202
xyxyxyxyxyxyxyxyxyxyxyxyxy030303
...
xyxy0E0E0E0E0E0E0E0E0E0E0E0E0E0E
xy0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F

如果最后一个块是一个完整的块,则一个完全填充的新块。

代码语言:javascript
运行
复制
xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxy 10101010101010101010101010101010

解密后,首先检查填充。如果填充没有rfc 2315中指定的正确格式,则可以说存在填充错误。

在本例中,库解密时检查填充,并警告您这一点。为了防止填充oracle攻击,您不会收到不正确的填充警告。你的解密效果很差。

库知道关键结果是否有效的填充,仅此而已。即使在完整性有用的情况下,也可能有一个以上的键产生有效的填充。

在现代密码学中,我们不再使用CBC模式。我们更喜欢认证加密(AE)模式,如AES-GCM或ChaCha20-Poly1305。AE模式在一个包中提供机密性、完整性和身份验证。

Galois计数器模式(GCM),内部使用CTR模式,其中没有填充,因此它们不受填充甲骨文攻击。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60080965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档