【问题标题】:SJCL CBC Mode not decryptingSJCL CBC 模式不解密
【发布时间】:2015-11-18 11:46:03
【问题描述】:

使用使用 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 团队的一个大胆举措,要求使用 beware 函数。查看代码,这应该可以工作。您确定您使用的是当前版本吗?
  • 从他们的github 获得。尽管在他们当前的文档中,beware 是找不到的。更愿意在最后一步使用 Crypto-JS,但结果为空白;似乎找不到任何编码。

标签: javascript encryption rncryptor sjcl


【解决方案1】:

SJCL

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

CryptoJS

decrypted 不是空字符串。 CryptoJS.<cipher>.decrypt() 返回一个带有负数 sigBytesWordArray 对象。此属性表示WordArray 预期包含的字节数。负数表示出现问题。它不一定是负数。

可能会有很多问题:

  • 您没有正确的密钥。
  • 您没有正确分割的密文。
  • ciphertext 不是 OpenSSL 格式的字符串,也不是 CipherParams 对象。尝试改为传递{ciphertext: ciphertext}
  • 密钥和 IV 格式不正确:它们应该是 WordArray 对象。

【讨论】:

  • 注意这里的key可能不正确。 RNCryptor 的 JavaScript 版本使用 1000 次 PBKDF2 迭代。 Python 版本使用 10k。您需要更改其中一个以使它们匹配。 (JavaScript 计算 PKBDF2 的速度非常慢,因此 10k 可能需要很长时间。)
  • 我在两边都以十六进制编码记录所有变量,一切都匹配。包含 core/cbc.js 文件后仍然无法使用 sjcl 解密。 PBKDF2 两边都使用 10K。是的,创建密钥确实需要一段时间,但我只在加密时才注意到。现在我正在解密,由于某种原因,它几乎不需要那么长时间。
  • 不再抛出beware 异常(现在使用convenience.js sjcl.decrypt)。现在的问题是sjcl.json 中的解码函数没有被正确传递json。转换为各种编码和字符串也没有工作。
【解决方案2】:

正如 Artjom B. 所说,cbc.jsbitArray.js 是必需的(解密的必要部分和我遗漏的一些东西)。原始代码现在可以正常工作了。

正如 Rob Napier 所指出的,顺便说一下 PBKDF2 迭代计数,它很慢。然而,对于这种情况(解密),10K 计数工作得很快,但对于加密,我在 1000 次迭代时用 CryptoJS 的 PBKDF2 补充了 kdf(sjcl 出现 bitArray 错误)。

【讨论】:

    猜你喜欢
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-09-25
    • 2016-07-28
    • 2013-04-06
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多