admin管理员组

文章数量:1391818

I'm using an react native app to municate with my miband 3, and part of its authentication process is encrypt a array of bytes using AES/ECB/NoPadding algorithm. I'm currently using this code as reference

Since I'm new to iot and encryption, I suppose that the lest step of its authentication is incorrect because and after writing to the miband 3 the encrypted byte array, I'm not getting authenticated properly.

Currently the last step looks like this:

const base_key = [0x01,0x23,0x45,0x67,0x89,0x01,0x22,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x90,0x02]
console.warn('Getting random number...')
const random_number = bytesToString(notification.filter((byte, index) => index > 3))

// Encrypting the key
const key = bytesToString(base_key)
const cipher = CryptoJS.AES.encrypt(random_number,key).toString()

// Step 5) Sending encrypted random number
console.warn('sending encrypted random number...')
const request_send_encrypted_key = [0x03,0x00, ...stringToBytes(cipher)]
await BleManager.writeWithoutResponse(miband3, service_uuid, characteristic_uuid, request_send_encrypted_key)

Notification is filtered because the first 3 bytes are used to tell which notification is happening, so I do not need them.

I must send the following to the miband 3 in order to authenticate properly:

const byteArrayToSend = [0x03,0x00, ...encryptedByteArray]

encryptedByteArray being my random number returned from miband notification (without the first 3 bytes) and properly encrypted .

I'm using 'crypto-js' and 'react-native-ble-manager' in the code.

How do I properly encrypt this bytearray using AES algorithm in order to send it?

I'm using an react native app to municate with my miband 3, and part of its authentication process is encrypt a array of bytes using AES/ECB/NoPadding algorithm. I'm currently using this code as reference

Since I'm new to iot and encryption, I suppose that the lest step of its authentication is incorrect because and after writing to the miband 3 the encrypted byte array, I'm not getting authenticated properly.

Currently the last step looks like this:

const base_key = [0x01,0x23,0x45,0x67,0x89,0x01,0x22,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x90,0x02]
console.warn('Getting random number...')
const random_number = bytesToString(notification.filter((byte, index) => index > 3))

// Encrypting the key
const key = bytesToString(base_key)
const cipher = CryptoJS.AES.encrypt(random_number,key).toString()

// Step 5) Sending encrypted random number
console.warn('sending encrypted random number...')
const request_send_encrypted_key = [0x03,0x00, ...stringToBytes(cipher)]
await BleManager.writeWithoutResponse(miband3, service_uuid, characteristic_uuid, request_send_encrypted_key)

Notification is filtered because the first 3 bytes are used to tell which notification is happening, so I do not need them.

I must send the following to the miband 3 in order to authenticate properly:

const byteArrayToSend = [0x03,0x00, ...encryptedByteArray]

encryptedByteArray being my random number returned from miband notification (without the first 3 bytes) and properly encrypted .

I'm using 'crypto-js' and 'react-native-ble-manager' in the code.

How do I properly encrypt this bytearray using AES algorithm in order to send it?

Share Improve this question edited Oct 2, 2019 at 13:51 Ry- 225k56 gold badges493 silver badges499 bronze badges asked Oct 1, 2019 at 18:26 Kanagawa MarcosKanagawa Marcos 1001 silver badge10 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

The following must be taken into account for AES-encryption using CryptoJS:

  • In the posted code, keys and data to be encrypted (random_number) are obviously specified as arrays. CryptoJS uses WordArray-objects, so a conversion is necessary. WordArray-objects can easily be converted over hexadecimal strings into arrays and vice versa using these functions and the CryptoJS-Encoders. Another possibility is the direct conversion using these functions (not tested).

  • Since the arrays contain arbitrary byte-sequences (in the sense that they generally do not correspond to any readable characters), only suitable encodings (Base64 or hexadecimal) may be used here. The methods bytesToString and stringToBytes were not posted, so it is unclear if there is a problem. CryptoJS allows to pass the data as string or WordArray, where the latter is used in the following.

  • If the second parameter in CryptoJS.AES.encrypt is passed as a string, it is interpreted as a passphrase from which the actual key is generated according to a defined algorithm, here. If the second parameter is to be interpreted as a key (and this seems to be the case in the reference code), then it must be passed as a WordArray.

  • AES/ECB/NoPadding is used for encryption according to the linked Medium-article. The disabling of padding is only possible because the data to be encrypted (random_number with a length of 16 bytes according to the article) corresponds to an integer multiple of the AES block size (16 bytes) (if this were not the case, padding would have to be mandatory).

  • The result of the encryption is a CipherParams-object whose ciphertext-property contains the encrypted data as a WordArray, here.

Taking these points into account, encryption can be performed as follows:

var CryptoJS = require("crypto-js");

// Key and random number as arrays, e.g.:
var random_numberBA = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f];
var keyBA = [0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x22, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x90, 0x02];

// Conversion to WordArrays
var random_numberWA = CryptoJS.enc.Hex.parse(bytesToHex(random_numberBA));
var keyWA = CryptoJS.enc.Hex.parse(bytesToHex(keyBA));

// Encryption
// - random_number as WordArray
// - Key as WordArray
// - ECB-Mode (default: CBC), No-Padding (default: Pkcs7-Padding)
var encryptedCP = CryptoJS.AES.encrypt(random_numberWA, keyWA, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });

// Encrypted data as WordArray
var encryptedWA = encryptedCP.ciphertext;

// Conversion to array
var encryptedBA = hexToBytes(CryptoJS.enc.Hex.stringify(encryptedWA));

// Consume encryptedBA 
// ...

// Helper: from https://stackoverflow./a/34356351/9014097
function hexToBytes(hex) {
    for (var bytes = [], c = 0; c < hex.length; c += 2)
        bytes.push(parseInt(hex.substr(c, 2), 16));
    return bytes;
}

function bytesToHex(bytes) {
    for (var hex = [], i = 0; i < bytes.length; i++) {
        var current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];
        hex.push((current >>> 4).toString(16));
        hex.push((current & 0xF).toString(16));
    }
    return hex.join("");
}

The result can be verified e.g. here.

本文标签: Encrypt a byte array in JavaScript using crypto js AES ECB algorithmStack Overflow