最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - EncryptDecrypt binary data crypto-js - Stack Overflow

programmeradmin7浏览0评论

I am failing to successfully encrypt a binary message using Crypto-JS. My data is in an Array Buffer. I'm working in Angular and I've run up a short test which works fine. I'm municating with a WiFi device. The following test works fine, using simple strings, which proves that the encryption and transport are all working.

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));

This works fine:

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

Problem is my data isn't in a string. It's binary, so is difficult to transmit as a string. I do not have any control over the code on the other side, which expects this format. My data may contains any of the 256 codes:

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

Can anyone advice how I can format that such that it will be accepted by crypto-js. In the case of the code 0x30, that is of course '0'. Excellent. That fits in a string nicely. 0x11 and 0x00: not so good! I've tried the following:

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;
  }

Looking closely at the hex dumps, there are some good clues:

Expected result other side:

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

Actual results other side:

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

Etc. I got bored bolding the matching bits but you can see the pattern. Question is what are all the c2 and c3 codes about? Why is 0xfa confused with oxba? Same for 0x98 and 0xd8? And 0xc5 & 0x85... And 0xC0 & 0x80... Is it something to do with using illegal string characters that are decoded wrong? How can I use this library to get my binary data across?

I am failing to successfully encrypt a binary message using Crypto-JS. My data is in an Array Buffer. I'm working in Angular and I've run up a short test which works fine. I'm municating with a WiFi device. The following test works fine, using simple strings, which proves that the encryption and transport are all working.

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));

This works fine:

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

Problem is my data isn't in a string. It's binary, so is difficult to transmit as a string. I do not have any control over the code on the other side, which expects this format. My data may contains any of the 256 codes:

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

Can anyone advice how I can format that such that it will be accepted by crypto-js. In the case of the code 0x30, that is of course '0'. Excellent. That fits in a string nicely. 0x11 and 0x00: not so good! I've tried the following:

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;
  }

Looking closely at the hex dumps, there are some good clues:

Expected result other side:

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

Actual results other side:

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

Etc. I got bored bolding the matching bits but you can see the pattern. Question is what are all the c2 and c3 codes about? Why is 0xfa confused with oxba? Same for 0x98 and 0xd8? And 0xc5 & 0x85... And 0xC0 & 0x80... Is it something to do with using illegal string characters that are decoded wrong? How can I use this library to get my binary data across?

Share Improve this question edited Dec 30, 2019 at 9:37 monkey asked Dec 30, 2019 at 9:29 monkeymonkey 1,6932 gold badges21 silver badges44 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

Your problems stem from the fact that WordArray from crypto-js will handle inputs as UTF-8 strings and codepoint conversions will occur. You'll want to use a single-byte encoding, like Latin-1. Here's how to convert between some representations:

    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

Here you go:

function hexdump(buffer, blockSize) {
    blockSize = blockSize || 16;
    var lines = [];
    var hex = "0123456789ABCDEF";
    for (var b = 0; b < buffer.length; b += blockSize) {
        var block = buffer.slice(b, Math.min(b + blockSize, buffer.length));
        var addr = ("0000" + b.toString(16)).slice(-4);
        var codes = block.split('').map(function (ch) {
            var code = ch.charCodeAt(0);
            return " " + hex[(0xF0 & code) >> 4] + hex[0x0F & code];
        }).join("");
        codes += "   ".repeat(blockSize - block.length);
        var chars = block.replace(/[\x00-\x1F\x20\x80-\x9F]/g, '.');
        chars +=  " ".repeat(blockSize - block.length);
        lines.push(addr + " " + codes + "  " + chars);
    }
    document.write("<pre>"+lines.join("\n")+"</pre>");
}
    test_data=String.fromCharCode.apply(null, Uint8Array.from({length:256},(v,k)=>k++));

    encrypted_data=CryptoJS.AES.encrypt(btoa(test_data), "secret");

    decrypted_data=atob(CryptoJS.AES.decrypt(encrypted_data, "secret").toString(CryptoJS.enc.Utf8));

    hexdump(decrypted_data)
<html> 
<head> 
       <script src="https://cdnjs.cloudflare./ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
</head> 
<body>
</body> 
</html>

发布评论

评论列表(0)

  1. 暂无评论