"Invalid AES Block Size" SJCL解密
"Invalid AES Block Size" SJCL Decryption
尝试使用 RNCryptor-js which uses SJCL. After logging all the steps on each end, (other end is RNCryptor-python) 密钥、盐、HMAC 哈希来解密 AES,一切都匹配。但是当我进行到最后一步时:
var aes = new sjcl.cipher.aes(encryption_key);
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]()
var decrypted = aes.decrypt(ciphertext, iv);
我收到错误:
sjcl.exception.invalid {toString: function, message: "invalid aes block size"}
完整代码如下:
PBKDF2:
this.KeyForPassword = function(password, salt) {
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);
};
解密(输入十六进制):
this.decrypt = function(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, "decryption");
var hmac_salt = sjcl.bitArray.bitSlice(message, 10 * 8, 18 * 8);
var hmac_key = _this.KeyForPassword(password, hmac_salt, "decryption");
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));
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 = aes.decrypt(ciphertext, iv);
return decrypted;
}
在定义 decrypted
的倒数第二个语句中抛出错误。
我查看了 sjcl 异常,看起来它正在寻找长度为 4 的输入,我猜它是一个 WordArray。我只是不知道如何获得有效输入。就像我说的,密文、iv、hmac 标签、盐都在 javascript 端被正确切割。可能只是编码问题。
这个错误似乎也只发生在 json(格式:'{"key":"value"}'),当我尝试像 "Hello, world" 我得到一个没有错误的 4 字数组。
有什么建议吗?
var decrypted = aes.decrypt(ciphertext, iv);
应该是
var decrypted = sjcl.mode.cbc.decrypt(aes, ciphertext, iv);
我在 cbc.js
(link to source) and it turned out that I hadn't included bitArray.js
(link) 中也遇到了填充问题,其中包含一个重要的 xor
函数(不要与简单的 ^
运算符混淆)。
所以:包括bitArray.js
输出也应该被编码:
return sjcl.codec.utf8String.fromBits(decrypted);
尝试使用 RNCryptor-js which uses SJCL. After logging all the steps on each end, (other end is RNCryptor-python) 密钥、盐、HMAC 哈希来解密 AES,一切都匹配。但是当我进行到最后一步时:
var aes = new sjcl.cipher.aes(encryption_key);
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]()
var decrypted = aes.decrypt(ciphertext, iv);
我收到错误:
sjcl.exception.invalid {toString: function, message: "invalid aes block size"}
完整代码如下:
PBKDF2:
this.KeyForPassword = function(password, salt) {
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);
};
解密(输入十六进制):
this.decrypt = function(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, "decryption");
var hmac_salt = sjcl.bitArray.bitSlice(message, 10 * 8, 18 * 8);
var hmac_key = _this.KeyForPassword(password, hmac_salt, "decryption");
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));
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 = aes.decrypt(ciphertext, iv);
return decrypted;
}
在定义 decrypted
的倒数第二个语句中抛出错误。
我查看了 sjcl 异常,看起来它正在寻找长度为 4 的输入,我猜它是一个 WordArray。我只是不知道如何获得有效输入。就像我说的,密文、iv、hmac 标签、盐都在 javascript 端被正确切割。可能只是编码问题。
这个错误似乎也只发生在 json(格式:'{"key":"value"}'),当我尝试像 "Hello, world" 我得到一个没有错误的 4 字数组。
有什么建议吗?
var decrypted = aes.decrypt(ciphertext, iv);
应该是
var decrypted = sjcl.mode.cbc.decrypt(aes, ciphertext, iv);
我在 cbc.js
(link to source) and it turned out that I hadn't included bitArray.js
(link) 中也遇到了填充问题,其中包含一个重要的 xor
函数(不要与简单的 ^
运算符混淆)。
所以:包括bitArray.js
输出也应该被编码:
return sjcl.codec.utf8String.fromBits(decrypted);