【问题标题】:PN532 MiFare Ultralight C Mutual AuthenticationPN532 MiFare Ultralight C 相互认证
【发布时间】:2014-11-08 09:56:43
【问题描述】:

有没有人设法通过使用此芯片的超轻 C 卡获得相互身份验证? 我了解身份验证程序,但查看芯片手册中的命令集并尝试了一些我认为实际上不可能的事情,但我想我会在放弃芯片组并重新使用 CJS 编码器之前在这里发布验证

提前致谢

【问题讨论】:

    标签: nfc mifare encoder mutual-authentication


    【解决方案1】:

    是的,可以使用 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中找到

    【讨论】:

    • 感谢您的回复,我在其他地方读到它是可能的,并在数小时检查代码后解决了它,当我意识到我将在我的一个读取响应中设置字节数时错误的值,因此将数据留在缓冲区中。一个简单的错误导致了巨大的头痛。
    • 如果这个线程死灵术不是太让人头疼的话,你能把你的代码发布给新手吗?
    • @Motes,请参阅下面的答案。
    • 非常感谢!小问题:根据您在另一个答案中的示例,NXP's MF0ICU2 data sheet 和我自己的实验,在步骤 3-4 终端 encrypts RndA + RndB’ 而卡 decrypts 它。
    • 当然。在我的回答中更正这一点。不知道为什么我这样写,但你说的是对的
    【解决方案2】:

    示例 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 库)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多