Javascript SJCL CBC模式未解密

Javascript SJCL CBC模式未解密,javascript,encryption,rncryptor,sjcl,Javascript,Encryption,Rncryptor,Sjcl,使用使用SJCL的RNCryptor。我试图解密一个十六进制消息,但当使用CBC模式时,事情变得很奇怪。显然,当使用CBC时,必须声明一个当心语句,我会得到一个错误 function KeyForPassword(password, salt) { console.log("Creating key..."); var hmacSHA256 = function (password) { var hasher = new sjcl.misc.hmac(passwo

使用使用SJCL的RNCryptor。我试图解密一个十六进制消息,但当使用CBC模式时,事情变得很奇怪。显然,当使用CBC时,必须声明一个当心语句,我会得到一个错误

function KeyForPassword(password, salt) {
    console.log("Creating key...");
    var hmacSHA256 = function (password) {
        var hasher = new sjcl.misc.hmac(password, sjcl.hash.sha256);
        this.encrypt = function () {
            return hasher.encrypt.apply(hasher, arguments);
        };
    };
    return sjcl.misc.pbkdf2(password, salt, 10000, 32 * 8, hmacSHA256);
};


function decrypt(password, message, options) {

    message = sjcl.codec.hex.toBits(message);

    options = options || {};

    var version = sjcl.bitArray.extract(message, 0 * 8, 8);
    var options = sjcl.bitArray.extract(message, 1 * 8, 8);

    var encryption_salt = sjcl.bitArray.bitSlice(message, 2 * 8, 10 * 8);
    var encryption_key = _this.KeyForPassword(password, encryption_salt);

    var hmac_salt = sjcl.bitArray.bitSlice(message, 10 * 8, 18 * 8);
    var hmac_key = _this.KeyForPassword(password, hmac_salt);

    var iv = sjcl.bitArray.bitSlice(message, 18 * 8, 34 * 8);

    var ciphertext_end = sjcl.bitArray.bitLength(message) - (32 * 8);
    var ciphertext = sjcl.bitArray.bitSlice(message, 34 * 8, ciphertext_end);

    var hmac = sjcl.bitArray.bitSlice(message, ciphertext_end);
    var expected_hmac = new sjcl.misc.hmac(hmac_key).encrypt(sjcl.bitArray.bitSlice(message, 0, ciphertext_end));

    // .equal is of consistent time
    if (! sjcl.bitArray.equal(hmac, expected_hmac)) {
      throw new sjcl.exception.corrupt("HMAC mismatch or bad password.");
    }

    var aes = new sjcl.cipher.aes(encryption_key);
    sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]()
    var decrypted = sjcl.mode.cbc.decrypt(aes, ciphertext, iv);


    return decrypted.toString(CryptoJS.enc.Utf8);
};
在盐、密钥和散列方面,所有内容都与Python端的加密相匹配。但我得到了这个错误:

TypeError: Cannot read property 'CBC mode is dangerous because it doesn't protect message integrity.' of undefined
我认为该方法已被弃用,因此我尝试使用此CryptoJS方法:

var decrypted = CryptoJS.AES.decrypt(ciphertext, encryption_key, {iv:iv});
这只是返回了一个空白字符串

我觉得我真的很接近了,只是在最后一部分需要一些帮助,谢谢。

SJCL 如果您仔细研究,预构建的sjcl.js中不包括CBC。您必须在页面中单独包含CBC文件(core/CBC.js),否则您将需要操作configure文件以将CBC添加到已启用模块的列表中

CryptoJS
解密的
不是空字符串
CryptoJS..decrypt()
返回一个
WordArray
对象,其
sigBytes
为负数。此属性表示
WordArray
预期包含的字节数。负数表示出了问题。它不一定总是一个负数

可能存在许多问题:

  • 你没有正确的钥匙
  • 您没有正确切片的密文
  • ciphertext
    不是OpenSSL格式的字符串或
    CipherParams
    对象。尝试传递
    {ciphertext:ciphertext}
  • 键和IV的格式不正确:它们应该是
    WordArray
    对象
正如Artjom B.所说,它也是需要的(解密的必要部分和我缺少的东西)。原来的代码现在可以正常工作了


正如Rob Napier指出的PBKDF2迭代计数的旁白,它很慢。然而,对于这种情况(解密),10K计数很快就起作用了,但对于加密,我在1000次迭代时用CryptoJS的PBKDF2补充了kdf(使用sjcl得到了位数组错误)。

这是sjcl团队要求使用
当心
函数的大胆举动。看看代码,这应该是可行的。你确定你使用的是当前版本吗?从他们的。尽管在他们当前的文档中,
当心
是找不到的。更愿意在最后一步使用Crypto JS,但结果为空;似乎找不到它的任何编码。请注意,此处的键可能不正确。RNCryptor的JavaScript版本使用1000次PBKDF2迭代。Python版本使用10k。您需要更改其中一个以使其匹配。(JavaScript计算PKBDF2的速度非常慢,所以10k可能需要很长时间。)我正在用十六进制编码记录两侧的所有变量,所有变量都匹配。包含core/cbc.js文件后仍然无法使用sjcl进行解密。PBKDF2在两侧使用10K。是的,创建密钥时确实需要一段时间,但我只是在加密时才注意到。现在,我正在解密,由于某种原因,它几乎不需要那么长的时间。不再获得
小心
抛出的异常(现在使用便利.js
sjcl.decrypt
)。现在的问题是,
sjcl.json
中的decode函数没有传递正确的json。转换为各种编码和字符串也不起作用。