Шифрование байтового массива в JavaScript с использованием алгоритма crypto js AES ECB - PullRequest
2 голосов
/ 01 октября 2019

Я использую собственное приложение реагирования для связи с моим miband 3, и частью процесса аутентификации является шифрование массива байтов с использованием алгоритма AES / ECB / NoPadding. В настоящее время я использую этот код в качестве ссылки

Поскольку я новичок в iot и шифровании, я полагаю, что последний шаг его аутентификации неверен, потому что ипосле записи в miband 3 зашифрованного байтового массива я не получаю аутентификацию должным образом.

В настоящее время последний шаг выглядит следующим образом:

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)

Уведомление отфильтровано, поскольку первые 3 байта используются, чтобы сообщить, какое уведомление происходит, поэтому они мне не нужны.

Я должен отправить следующее в miband 3 для правильной аутентификации:

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

encryptedByteArray - мое случайное число, возвращенное из уведомления miband (без первых 3в байтах) и должным образом зашифрованы.

Я использую 'crypto-js' и 'response-native-ble-manager' в коде.

Как мнеправильно зашифровать этот bytearray, используя алгоритм AES для его отправки?

1 Ответ

1 голос
/ 02 октября 2019

При AES-шифровании необходимо учитывать следующее: CryptoJS:

  • В размещенном коде явно указываются ключи и данные для шифрования (random_number)как массивы. CryptoJS использует WordArray -объекты, поэтому необходимо преобразование. WordArray -объекты могут быть легко преобразованы через шестнадцатеричные строки в массивы и наоборот, используя эти функции и CryptoJS - Кодеры . Другая возможность - прямое преобразование с использованием этих функций (не тестировалось).

  • Поскольку массивы содержат произвольные последовательности байтов (в том смысле, что они обычно не соответствуют каким-либо читаемым символам), здесь могут использоваться только подходящие кодировки (Base64 или шестнадцатеричные). Методы bytesToString и stringToBytes не были опубликованы, поэтому неясно, есть ли проблема. CryptoJS позволяет передавать данные в виде строки или WordArray, где последний используется в следующем.

  • Если второй параметр в CryptoJS.AES.encrypt передается в виде строки,он интерпретируется как фраза-пароль, из которой генерируется фактический ключ в соответствии с определенным алгоритмом, здесь . Если второй параметр должен интерпретироваться как ключ (и это, кажется, имеет место в ссылочный код ), то он должен быть передан как WordArray.

  • AES/ECB/NoPadding используется для шифрования в соответствии со ссылкой Medium-article . Отключение заполнения возможно только потому, что зашифрованные данные (random_number длиной 16 байт согласно статье) соответствуют целому числу, кратному размеру блока AES (16 байт) (если это не так,обивка должна быть обязательной).

  • Результатом шифрования является CipherParams -объект, чье свойство ciphertext содержит зашифрованные данные в виде WordArray, здесь .

С учетом этих моментов шифрование может быть выполнено следующим образом:

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.com/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("");
}

Результат может быть проверен, например, здесь .

...