【发布时间】:2020-05-17 14:28:06
【问题描述】:
为了与 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 阅读器(关键部分以粗体显示)收到的信息: 83001500000021E1000045005ff58680541c5a5903f4833dfaa428bf1c0a
decrypt('5ff58680541c5a5903f4833dfaa428bf', '41435231323535552d4a312041757468')
=> Result is 6064a82b7edf62986b0a2ec79e922aad
在第 2 步:根据文档,我必须发送以下内容。
abAuthData[0:15] – 我生成的 16 个字节的随机数
abAuthData[16:31] – 从 ACR1255U-J1 接收到的 16 个字节的解密随机数(我猜这将是第一步 6064a82b7edf62986b0a2ec79e922aad 的结果)
总体32 字节随机数将使用客户主密钥解密并返回给 ACR1255U-J1 阅读器。
根据 Wireshark 的说法,这是演示应用程序现在发送到 ACR1255 阅读器的内容(关键部分以粗体显示):
6B0025000000EAE0000046007088e66af57bf04e66a8b2e83614f288 c8ed5005b914b51e50285a93408e14922c0a
当然,这是已经解密的密钥。为了证明我对工作流程的理解,我对其进行了加密,并希望将步骤 1 的结果作为密钥的第二部分。但事实并非如此。
encrypt('7088e66af57bf04e66a8b2e83614f288c8ed5005b914b51e50285a93408e1492', '41435231323535552d4a312041757468')
=> Result is 493aa0c5476f551d3b2bce664cfe4305*3b61bce6e4c0837be30453ddad165180*
我对文档中描述的工作流程有什么误解?是否能够以与文档不同的方式描述它?
文档也可以在here 找到。第 32 至 35 页。
附言。我知道,文档说 AES CBC 模式。但是没有使用IV,据我所知ECB模式的用法是一样的。
【问题讨论】:
-
CBC 与
0-IV 和 ECB 的等价仅适用于密文的 first 块(AES 为 16 个字节)。第二步中使用的明文长度为 2 个块(AES 为 32 个字节),并生成一个 2 块密文(假设没有填充)。在这种情况下,带有0-IV 的 CBC 因此必须不被 ECB 替换,因为第二个块的加密方式不同。顺便说一句,NoPadding而不是ZeroPadding应该在encrypt中使用,不是吗(尽管这对长度是块大小整数倍的明文没有影响)? -
@Topaco 视情况而定,一些基于零的填充实现(例如 Java 的 Bouncy Castle)总是 填充,就像 PKCS#5/7 一样。我不希望这是一般默认值,大多数只会在必要时填充(也是因为加密文本的通用用例,对于 C 环境,它本身已经是零填充)。虽然这里似乎不是这种情况,但值得关注。
-
@MaartenBodewes - 没错,有不同的零填充变体,必须小心。在我的评论中(
CryptoJS.pad.)ZeroPadding表示 CryptoJS 实现,如果明文的长度已经是块大小的整数倍,则 not 填充。
标签: authentication encryption acr