我正在尝试使用使用SJCL的RNCryptor-JS,但出于某种原因,SJCL位数组连接似乎不起作用。
var SALT_SIZE = 64/8;
var plaintext = "Hello, World!";
var password = "myPassword";
function keyForPassword(password, salt){
// Using CryptoJS for pbkdf2, aes, sha256, and random word arrays
var pbkdf2_key = CryptoJS.PBKDF2(
password,
salt,
{
keySize: 256/32,
iterations: 1000,
hasher: CryptoJS.algo.SHA256
}
);
return pbkdf2_key;
}
var encryption_salt = CryptoJS.lib.WordArray.random(SALT_SIZE);
var encryption_key = keyForPassword(password, encryption_salt);
var hmac_salt = CryptoJS.lib.WordArray.random(SALT_SIZE);
var hmac_key = keyForPassword(password, hmac_salt);
var iv = CryptoJS.lib.WordArray.random(128/8);
var version = sjcl.codec.hex.toBits("03");
var options = sjcl.codec.hex.toBits("01");
var message = sjcl.bitArray.concat(version, iv);
message = sjcl.bitArray.concat(message, encryption_salt);
message = sjcl.bitArray.concat(message, hmac_salt);
message = sjcl.bitArray.concat(message, iv);
// Progressive cipher
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(encryption_key, {iv: iv});
var ciphertext = aesEncryptor.process(plaintext);
message = sjcl.bitArray.concat(message, ciphertext);
var hmac = new sjcl.misc.hmac(hmac_key).encrypt(message);
var encrypted_data = sjcl.bitArray.concat(message, hmac);
var output = sjcl.codec.hex.fromBits(encrypted_data);
console.log(output);
当我在第一组message
完成后记录sjcl.bitArray.concat
的输出时,所有返回的内容都是version
和iv
的第一个连接。最后的十六进制输出只是第一次连接和hmac
连接。这加强了我的怀疑,它可能是CryptoJS的错,因为输出连接起作用并且在两个sjcl变量之间。
我尝试使用SJCL随机位数组,但遇到了一些麻烦。使用
时,SJCL的生成器prng
无法正常工作
new sjcl.prng.randomWords(32/4);
或
new sjcl.prng(32/4);
而且sjcl.random.randomWords
似乎不再起作用了。
答案 0 :(得分:2)
CryptoJS(WordArray
)和SJCL(bitArray
)具有不同的数据内部表示。你不能简单地连接它们。
最简单的方法可能是将其编码为中间格式(如Hex),让另一方解码为其内部格式:
message = sjcl.bitArray.concat(version, sjcl.codec.hex.toBits(iv.toString()));
WordArray#toString()
会自动使用十六进制编码。您必须为所有行执行此操作,但这有点过分,因为您可以将Hex字符串连接为字符串:
message = sjcl.codec.hex.toBits("03" + iv + encryption_salt + hmac_salt + iv);
这应该按预期工作,因为向字符串添加WordArray
(例如iv
会自动调用其toString()
函数,而该函数又生成一个大端十六进制编码字符串。< / p>
我想知道你为什么要两次使用iv
。也许你的意思是options
。
需要改变什么:
function convert(wordArray){
return sjcl.codec.hex.toBits(wordArray.toString());
}
var message = "0301" + encryption_salt + hmac_salt + iv;
var ciphertext = CryptoJS.AES.encrypt(plaintext, encryption_key, {iv: iv}).ciphertext;
message += ciphertext;
message = sjcl.codec.hex.toBits(message);
var hmac = new sjcl.misc.hmac(convert(hmac_key)).encrypt(message);
var encrypted_data = sjcl.bitArray.concat(message, hmac);
var output = sjcl.codec.hex.fromBits(encrypted_data);
console.log(output);