javascript - 使用 crypto js AES ECB 算法在 JavaScript 中加密字节数组

标签 javascript arrays react-native encryption iot

我正在使用 React native 应用程序与我的 miband 3 通信,其身份验证过程的一部分是使用 AES/ECB/NoPadding 算法加密字节数组。我目前正在使用 this code as reference

由于我是物联网和加密方面的新手,我想 the lest step of its authentication是不正确的,因为在将加密的字节数组写入 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”和 'react-native-ble-manager'在代码中。

如何使用 AES 算法正确加密此字节数组以便发送?

最佳答案

对于使用 CryptoJS 的 AES 加密,必须考虑以下因素:

  • 在发布的代码中, key 和要加密的数据 (random_number) 显然指定为数组。 CryptoJS 使用 WordArray 对象,因此需要进行转换。 WordArray - 使用 these 函数和 CryptoJS- Encoders 可以轻松地将对象通过十六进制字符串转换为数组,反之亦然。另一种可能性是使用 these 函数(未测试)直接转换。

  • 由于数组包含任意字节序列(从某种意义上说,它们通常不对应任何可读字符),因此只能在此处使用合适的编码(Base64 或十六进制)。 bytesToStringstringToBytes 方法没有贴出,所以不清楚是否有问题。 CryptoJS 允许将数据作为字符串或 WordArray 传递,后者在下文中使用。

  • 如果 CryptoJS.AES.encrypt 中的第二个参数作为字符串传递,它会被解释为根据定义的算法 here 从中生成实际 key 的密码。如果第二个参数要被解释为一个键(这似乎是 reference code 中的情况),那么它必须作为 WordArray 传递。

  • AES/ECB/NoPadding 用于根据链接的 Medium-article 进行加密。只能禁用填充,因为要加密的数据(random_number 根据文章长度为 16 字节)对应于 AES block 大小(16 字节)的整数倍(如果此情况并非如此,填充必须是强制性的)。

  • 加密的结果是一个 CipherParams 对象,其 ciphertext 属性包含作为 WordArray 的加密数据,here .

考虑到这些要点,可以按如下方式进行加密:

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

结果可以验证,例如here

关于javascript - 使用 crypto js AES ECB 算法在 JavaScript 中加密字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58190380/

相关文章:

javascript - 将加密 ECDH 公钥解析为 JWK 格式以与 WebCrypto 一起使用

php - 具有动态标题的 CJuiDialog

javascript - HTML + JS 如何更改/取消更改文本 onclick

arrays - Matlab 向量查找的 Swift 版本?

c# - 在不安全模式下使用 64 位指针访问 16 位数组

javascript - 如何从我的 react-native 应用程序打开笔记本电脑上的 chrome 选项卡(就像远程调试一样)?

javascript - 获取类型错误 :this. props.getMovieTree 不是函数

android - 如何在我的 React-Native 开发环境中指定 Metro Bundler IP 地址?

javascript:IE 中的 getElementById 问题

c - 这些功能如何运作?