javascript - 加密/解密二进制数据 crypto-js

标签 javascript cryptojs

我无法使用 Crypto-JS 成功加密二进制消息。我的数据位于数组缓冲区中。我正在 Angular 工作,并且进行了一个简短的测试,效果很好。我正在与 WiFi 设备通信。以下测试工作正常,使用简单的字符串,这证明加密和传输都正常工作。

var iv_hexString = this.buf2hex([146, 66, 191, 151, 23, 3, 113, 119, 231, 131, 133, 112, 79, 32, 114, 136]);
var key_hexString = this.buf2hex([123, 217, 20, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 115, 222, 209, 241, 24, 175, 144, 175, 53, 196, 29, 24, 23, 17, 218, 131, 226, 53, 209]);
var key = CryptoJS.enc.Hex.parse(key_hexString);
var iv = CryptoJS.enc.Hex.parse(iv_hexString);

console.log('iv  = ' + iv);
console.log('key = ' + key);

let cli_verify = CryptoJS.AES.encrypt("1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff", key, {
  mode: CryptoJS.mode.CTR,
  iv: iv,
  padding: CryptoJS.pad.NoPadding
});

console.log('Cipher Text = ', cli_verify.ciphertext.toString());



// Test by decoding some shit here. 
var decrypted = CryptoJS.AES.decrypt(cli_verify, key, {
  mode: CryptoJS.mode.CTR,
  iv: iv,
  padding: CryptoJS.pad.NoPadding
});

console.log('Decrypted Output = ', decrypted.toString(CryptoJS.enc.Utf8));

这工作正常:

[ng] [console.log]: "iv  = 9242bf9717037177e78385704f207288"
[ng] [console.log]: "key = 7bd9140b181a552d72b81ba22573ded1f118af90af35c41d181711da83e235d1"
[ng] [console.log]: "Cipher Text = " "de3cfe57c4d6fc5a8218b9eb801ebd49d3bd6cbf9ecd1b62656be424c09ba1d72b8ea3b6f304752b514ff4dc086a63a5349534e08e110f4855108a8d96804af3"
[ng] [console.log]: "Decrypted Output = " "1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff"

问题是我的数据不在字符串中。它是二进制的,因此很难作为字符串传输。我对另一端的代码没有任何控制权,它需要这种格式。我的数据可能包含 256 个代码中的任意一个:

let myMessage = new Uint8Array([0x0a, 0x11, 0x00, 0xff, 0x30, 0x53, 0x22, 0x6a, 0x8f, 0x05, 0x16, 0x15, 0x88, 0xb5]);

任何人都可以建议我如何格式化它,以便它能够被 crypto-js 接受。对于代码 0x30,这当然是“0”。出色的。这很适合串起来。 0x11 和 0x00:不太好!我尝试过以下方法:

var devPublic_hexString = this.buf2hex(this.device_Public_Key);
  let cli_verify = CryptoJS.AES.encrypt(this.hex2a(devPublic_hexString), key, {
    mode: CryptoJS.mode.CTR,
    iv: iv,
    padding: CryptoJS.pad.NoPadding
  });

 hex2a(hexx) {
    var hex = hexx.toString();//force conversion
    var str = '';
    //for (var i = 0; (i < hex.length && hex.substr(i, 2) !== '00'); i += 2)
    for (var i = 0; (i < hex.length); i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
    return str;
  }

仔细观察十六进制转储,有一些很好的线索:

对方预期结果:

5c fa 82 94 4e 79 64 08 9c 0b 9a 4d d8 8f 06 c5 39广告 c0 91 9b c7 cc 6a 0a 86 81 dd 5d ad 0b 03

对方实际结果:

5c c3 ba c2 82 c2 94 4e 79 64 08 c2 9c 0b c2 9a 4d c3 98 c2 8f 06 c3 85 39 c2 ad c3 80 c2 91 c2

等等。我厌倦了将匹配的位加粗,但你可以看到模式。问题是 c2 和 c3 代码都是关于什么的?为什么 0xfa 与 oxba 混淆? 0x98 和 0xd8 一样吗? 0xc5 & 0x85...以及 0xC0 & 0x80...是否与使用解码错误的非法字符串字符有关?我如何使用这个库来获取我的二进制数据?

最佳答案

您的问题源于以下事实:crypto-js 中的 WordArray 会将输入处理为 UTF-8 字符串,并且会发生代码点转换。您需要使用单字节编码,例如 Latin-1。以下是如何在一些表示形式之间进行转换:

    const arrayToString = arr => arr.reduce((str, code) => str + String.fromCharCode(code), '');

    const original = new Uint8Array([0x0a, 0x11, 0x00, 0xff, 0x30, 0x53, 0x22, 0x6a, 0x8f, 0x05, 0x16, 0x15, 0x88, 0xb5]);
    const originalString = arrayToString(original);

    // -> Hex 0a1100ff3053226a8f05161588b5

    const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Latin1.parse(originalString), 'secret');
    const encryptedArray32 = Uint32Array.from(encrypted.ciphertext.words);
    const encryptedArray8 = new Uint8Array(encryptedArray32.buffer);

    // -> Hex f6b58e23281ed5323e80d22e6fb94752

    const decryptedString = CryptoJS.AES.decrypt(encrypted, 'secret').toString(CryptoJS.enc.Latin1);
    const decryptedArray8 = Uint8Array.from(Buffer.from(decryptedString, 'latin1'));

    // -> Hex 0a1100ff3053226a8f05161588b5

关于javascript - 加密/解密二进制数据 crypto-js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59528472/

相关文章:

reactjs - 类型错误 : null is not an object (evaluating 'RNRandomBytes.seed' ) React Native

javascript - 使用 PHP 产生与 CryptoJS.enc.Base64 相同的结果

javascript - 为什么 HMAC sha256 在 PHP 和 Javascript 上返回不同的值

javascript - jspm 找不到 Aurelia 应用程序的 'feature' 插件的全局资源

Javascript为什么这个函数返回undefined

javascript - 如何从 r.fn.init 获取值(JQuery 选择器上下文)

typescript - 将 CryptoJS 与十六进制字符串一起使用

c# - .NET和nodejs、CryptoJS之间的AES算法值差异

javascript - 创建 javascript 弹出窗口的最优雅方法?

javascript - 如何绕过express的错误处理