【问题标题】:AES-256-CBC Bad DecryptAES-256-CBC 错误解密
【发布时间】:2016-05-13 01:08:20
【问题描述】:

第 1 步:使用 pbkdf2 创建密钥

var key = crypto.pbkdf2Sync('prancypoodle', 'sherylcrowe', 10000, 32, 'sha512');

使用密码 prancy poodle 创建一个密钥,用 sherylcrowe 对其进行加盐,迭代 10,000 次,输出一个 32 字节长的密钥(AES-256-CBC 需要该长度)。

第 2 步:加密一些东西

var cipher = crypto.createCipheriv('aes-256-cbc', key, 'dogsarefun'.toString("binary"));

var crypted = cipher.update('wherearemysocks?');
crypted = Buffer.concat([crypted, cipher.final()]);

第 3 步:解密和失败

var decipher = crypto.createDecipheriv('aes-256-cbc', key, 'dogsarefun'.toString('binary'));

var decrypted = decipher.update(crypted);
decrypted = Buffer.concat([decrypted, decipher.final()]);
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
    at Error (native)
    at Decipher.Cipher.final (crypto.js:150:26)
    at repl:1:48
    at REPLServer.defaultEval (repl.js:272:27)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:441:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:188:7)
    at REPLServer.Interface._onLine (readline.js:219:10)

我做错了什么?看起来是对的,其实是错的。

【问题讨论】:

    标签: node.js cryptography


    【解决方案1】:

    您需要为 CBC 模式提供 IV,并且它需要是块大小(AES 为 16 字节)。 'dogsarefun' 只有 10 个字节,所以其余字节未指定,可能(可能是)垃圾。

    由于 PKCS 填充是默认值,并且使用了 CBC 模式,因此不正确的 IV 将导致解密时填充不正确,可能会出现以下错误:routines:EVP_DecryptFinal_ex:bad decrypt

    附:当心:这是由猫控制的互联网。 ?

    【讨论】:

    • 对于不同算法需要什么长度的keys和ivs有很好的参考吗?
    • 好点,Wikipedia 提供了密钥大小和块大小,但没有提到 IV 大小与块大小相同,假设很多。有几本好书,例如 Handbook of Applied Cryptography 参见免费下载 Bruce Schneier 的 Applied Cryptography Niels Ferguson 和 Bruce Schneier 的Practical Cryptography Cryptography Decrypted H. X. Mel 和 Doris M. Baker(我非常喜欢的好开胃菜)。
    【解决方案2】:

    您需要使用createDecipheriv函数解密,并且您的IV必须是16个字符。

    例子:

    var crypto = require('crypto');
    var buffer = require('buffer');
    
    var key = crypto.pbkdf2Sync('prancypoodle', 'sherylcrowe', 10000, 32, 'sha512');
    
    // Initialization vector must be 16 characters.
    var cipher = crypto.createCipheriv('aes-256-cbc', key,
      new Buffer('1234567812345678', 'binary'));
    
    var crypted = cipher.update('wherearemysocks?');
    console.log('Encrypted: %s', crypted);
    crypted = Buffer.concat([crypted, cipher.final()]);
    // Again, IV must be 16 characters.
    var decipher = crypto.createDecipheriv('aes-256-cbc', key,
      new Buffer('1234567812345678', 'binary'));
    
    var decrypted = decipher.update(crypted);
    console.log('Decrypted: %s', decrypted);
    

    输出:

    Encrypted: #�j���(����
    Decrypted: wherearemysocks?
    

    【讨论】:

    • 最好以十六进制显示加密数据,因为许多(大多数)字节不是可打印的字符。诸如“#�j���(����”之类的东西相当没有意义,因为丢失了这么多字节。
    • 啊,我这样做主要是为了证明它曾经被遮蔽(因为它被加密了!)而现在不是了。 :P
    猜你喜欢
    • 1970-01-01
    • 2013-08-11
    • 2018-09-09
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2019-04-14
    相关资源
    最近更新 更多