有没有人设法通过使用该芯片的超轻 C 卡获得相互身份验证?我了解身份验证程序,但查看芯片手册中的命令集并尝试了一些我认为实际上不可能的事情,但我想我会在放弃芯片组并重新使用 CJS 编码器之前在这里发布确认
提前致谢
有没有人设法通过使用该芯片的超轻 C 卡获得相互身份验证?我了解身份验证程序,但查看芯片手册中的命令集并尝试了一些我认为实际上不可能的事情,但我想我会在放弃芯片组并重新使用 CJS 编码器之前在这里发布确认
提前致谢
是的,可以使用 Mifare Ultralight C 执行相互身份验证。使用以下程序:
STEP 1:发送启动认证命令。(1A 00) 到卡
第 2 步:卡生成一个 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 步:卡将身份验证状态设置为“已验证”</p>
同样可以在这个恩智浦数据表中找到
示例 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 库)。