【发布时间】:2014-11-08 09:56:43
【问题描述】:
有没有人设法通过使用此芯片的超轻 C 卡获得相互身份验证? 我了解身份验证程序,但查看芯片手册中的命令集并尝试了一些我认为实际上不可能的事情,但我想我会在放弃芯片组并重新使用 CJS 编码器之前在这里发布验证
提前致谢
【问题讨论】:
标签: nfc mifare encoder mutual-authentication
有没有人设法通过使用此芯片的超轻 C 卡获得相互身份验证? 我了解身份验证程序,但查看芯片手册中的命令集并尝试了一些我认为实际上不可能的事情,但我想我会在放弃芯片组并重新使用 CJS 编码器之前在这里发布验证
提前致谢
【问题讨论】:
标签: nfc mifare encoder mutual-authentication
是的,可以使用 Mifare Ultralight C 执行相互身份验证。使用以下程序:
步骤 1: 发送启动认证命令。 (1A 00) 到卡
步骤 2: Card 生成一个 8 字节的随机数 RndB。这个随机数用多样化的密钥进行DES/3DES加密,记为ek(RndB),然后传送给终端。
步骤 3 终端对接收到的 ek(RndB) 进行 DES/3DES 解密操作,从而检索 RndB。然后将 RndB 左移 8 位(第一个字节移动到 RndB 的末尾),产生 RndB'。现在终端自己生成一个 8 字节的随机数 RndA。此 RndA 与 RndB' 连接并使用 DES/3DES 加密(两个块的加密使用密码块链接 (CBC) 发送模式链接)。这个令牌 ek(RndA + RndB') 被发送到卡上。
步骤 4: 卡对收到的令牌运行 DES/3DES 解密,从而获得 RndA + RndB'。卡现在可以通过将发送的 RndB'与内部将原始 RndB 左移 8 位获得的 RndB' 进行比较来验证发送的 RndB'。验证成功向卡证明卡和终端拥有相同的秘密(密钥)。如果验证失败,卡将停止验证过程并返回错误消息。由于卡片也收到了终端生成的随机数RndA,它可以对RndA进行8位左移操作得到RndA',再将其加密,得到ek(RndA')。这个令牌被发送到终端。
步骤 5: 终端对接收到的 ek(RndA') 运行 DES/3DES 解密,从而获得 RndA',用于与终端内部旋转的 RndA' 进行比较。如果比对失败,则终端退出该过程并可以暂停卡片。
第 6 步:卡将身份验证状态设置为“已验证”
同样可以在this NXP datasheet中找到
【讨论】:
RndA + RndB’ 而卡 decrypts 它。
示例 C 源代码:
typedef unsigned char byte;
int mutual_authentication( const byte *diversifiedKey )
{
byte cmd[256], response[256];
int cmdLen, responseLen;
//Send 1A00
cmd[0] = 0x1A;
cmd[1] = 0x00;
cmdLen = 2;
int ret = send_command( cmd, cmdLen, response, &responseLen );
//Get ekRndB
byte ekRndB[8], rndB[8];
memcpy(ekRndB, response, 8);
//Decrypt ekRndB with diversifiedKey
des_ISO_decrypt( diversifiedKey, ekRndB, rndB, 8 );
//PCD Generates RndA
byte randA[8] = "\x33,\x54,\x2A,\x87,\x21,\x00,\x77,\x98";//random numbers
byte rndARndBComplement[16], ekRndARndBComplement[16];
// Append RndA and RndB' ( RndB' is generated by rotating RndB one byte to the left )
// after the status byte.
memcpy(&rndARndBComplement[0],rndA,8);
memcpy(&rndARndBComplement[8],&rndB[1],7); // bytes 1 to 7
rndARndBComplement[15] = rndB[0]; // byte 0
// Apply the DES send operation to the 16 argument bytes before sending the second frame to the PICC
des_ISO_encrypt(diversifiedKey, rndARndBComplement, ekRndARndBComplement, 16);
cmd[0] = 0xAF;
memcpy(&cmd[1], ekRndARndBComplement, 16);
cmdLen = 17;
ret = send_command( cmd, cmdLen, response, &responseLen );
byte ekRndAComplement[8], rndAComplement[8], finalOutput[8];
memcpy(&ekRndAComplement[0], &response[1], 8);
des_ISO_decrypt(diversifiedKey, ekRndAComplement, rndAComplement, 8);
memcpy(&finalOutput[1], &RndAComplement[0], 7);
finalOutput[0] = rndAComplement[7];
//compare the received RndA with the one we originally had
return memcmp(&finalOutput[0], &rndA[0], 8);
}
注意:您应该有自己的 send_command()(取决于您的读卡器)、des_ISO_decrypt() 和 des_ISO_encrypt( )(取决于您的 DES 库)。
【讨论】: