1

为了与 ACR1255U-J1 NFC 阅读器进行通信,需要进行身份验证。使用十六进制字符串通过蓝牙连接。

这是我的两种加密和解密方法:

encrypt(valueStringHex, keyStringHex) {
    const CryptoJS = require('crypto-js');
    const value =  CryptoJS.enc.Hex.parse(valueStringHex);
    const key  = CryptoJS.enc.Hex.parse(keyStringHex);
    const encryptedStringHex = CryptoJS.AES.encrypt(value, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.ZeroPadding}).ciphertext.toString();
    return encryptedStringHex;
    }

decrypt(valueStringHex, keyStringHex) {
    const CryptoJS = require('crypto-js');
    const value = CryptoJS.enc.Hex.parse(valueStringHex);
    const key = CryptoJS.enc.Hex.parse(keyStringHex);
    const decryptedStringHex = CryptoJS.AES.decrypt({ciphertext: value}, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding});
    return decryptedStringHex.toString();
    }

阅读器附带了一个演示应用程序,我在该应用程序中记录了身份验证期间的蓝牙流量。我用 Wireshark 检查了这个。基于在 Wireshark 中看到的通信,我试图证明我在我的应用程序中对身份验证过程的编码。

ACR1255 文档说:
第 1 步我从 ACR 阅读器接收到使用客户主密钥加密的 16 字节随机数序列。我应该使用正确的客户主密钥(41435231323535552d4a312041757468)对其进行解密。

根据 Wireshark,这是我在第一步从 ACR1255 阅读器(关键部分以粗体显示)收到的信息:83001500000021E100004500 5ff58680541c5a5903f4833dfaa428bf 1c0a

decrypt('5ff58680541c5a5903f4833dfaa428bf', '41435231323535552d4a312041757468')
=> Result is 6064a82b7edf62986b0a2ec79e922aad

第 2 步:根据文档,我必须发送以下内容。
abAuthData[0:15] – 我生成的 16 个字节的随机数
abAuthData[16:31] – 从 ACR1255U-J1 收到的 16 个字节的解密随机数(这将是第一步 6064a82b7edf62986b0a2ec79e922aad 的结果,我猜)
总体 32 -byte 随机数将使用客户主密钥解密并返回给 ACR1255U-J1 读卡器。

根据 Wireshark,这是演示应用程序现在发送给 ACR1255 阅读器的内容(关键部分以粗体显示):
6B0025000000EAE000004600 7088e66af57bf04e66a8b2e83614f288 c8ed5005b914b51e50285a93408e1492 2c0a

当然,这是已经解密的密钥。为了证明我对工作流程的理解,我对其进行了加密,并希望将步骤 1 的结果作为密钥的第二部分。但事实并非如此。

encrypt('7088e66af57bf04e66a8b2e83614f288c8ed5005b914b51e50285a93408e1492', '41435231323535552d4a312041757468')
=> Result is 493aa0c5476f551d3b2bce664cfe4305*3b61bce6e4c0837be30453ddad165180*

我对文档中描述的工作流程有什么误解?是否能够以与文档不同的方式描述它?

文档也可以在这里找到。第 32 至 35 页。

附言。我知道,文档说 AES CBC 模式。但是没有使用 IV,据我所知,ECB 模式的用法是一样的。

4

1 回答 1

0

为了完整起见,我想添加解决方案。
根据@Topaco 的评论,我对欧洲央行模式有误。我将其更改为 CBC 并添加了 0-IV,它现在正在工作。

decrypt(valueStringHex, keyStringHex) {
    const CryptoJS = require('crypto-js');
    const value = CryptoJS.enc.Hex.parse(valueStringHex);
    const key = CryptoJS.enc.Hex.parse(keyStringHex);
    const ivvar   = CryptoJS.enc.Hex.parse('00000000000000000000000000000000');
    const decryptedStringHex = CryptoJS.AES.decrypt({ciphertext: value}, key, {iv: ivvar, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.NoPadding});
    return decryptedStringHex.toString();
    }

// in Step 1: 
// decrypt('5ff58680541c5a5903f4833dfaa428bf', '41435231323535552d4a312041757468')
// returns 6064a82b7edf62986b0a2ec79e922aad
encrypt(valueStringHex, keyStringHex) {
    const CryptoJS = require('crypto-js');
    const value =  CryptoJS.enc.Hex.parse(valueStringHex);
    const key  = CryptoJS.enc.Hex.parse(keyStringHex);
    const ivvar   = CryptoJS.enc.Hex.parse('00000000000000000000000000000000');
    const encryptedStringHex = CryptoJS.AES.encrypt(value, key, {iv: ivvar, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.NoPadding}).ciphertext.toString();
    return encryptedStringHex;
    }

// in Step 2:
// encrypt('7088e66af57bf04e66a8b2e83614f288c8ed5005b914b51e50285a93408e1492', '41435231323535552d4a312041757468')
// this is the decrypted string sent to the reader, which has to be encrypted here to proof that the key contains the result of step 1 in second 16 Byte block
// returns => 493aa0c5476f551d3b2bce664cfe43056064a82b7edf62986b0a2ec79e922aad (which is the return of Step 1 (in the second half))
于 2020-05-18T20:02:44.777 回答