Android上的Mifare Ultralight C身份验证

时间:2018-06-17 22:36:43

标签: android authentication nfc mifare 3des

我有一些Mifare Ultralight C标签用于测试身份验证。

我第一次使用应用程序NXP TagInfo阅读它时,我可以看到以下信息:

(...)
Page 04 - Page 27: FULL OF 0s **(empty tag)**
Page 28: 00 00 -- --
Page 29: 00 00 -- --
Page 2A: 30 -- -- --
Page 2B: 00 -- -- --
Page 2C: 42 52 45 41
PAGE 2D: 4B 4D 45 49
PAGE 2E: 46 59 4F 55
PAGE 2F: 43 41 4E 21

页面2C - 2F表示它有默认密钥“BREAKMEIFYOUCAN!” (425245414b4d454946594f5543414e21)。

然后我运行了我的Android应用程序基本上这样做了:

  1. 从第2C页到第2F页(用于身份验证)编写49454D4B41455242214E4143554F5946

  2. 在第2A页写入0x04(42);意思是2A上的所有页面都需要认证。

  3. 在第2B页写入0x00(43);这意味着阅读和写作都需要认证。

  4. //Start authenticating
    byte[] result1 = mifare.transceive(new byte[] {
                    (byte)0xA2,  /* CMD = WRITE */
                    (byte)0x2C,  /* PAGE = 44    */
                    (byte)0x49, (byte)0x45, (byte)0x4D, (byte)0x4B  /* 49 45 4D 4B */
            });
    
    byte[] result2 = mifare.transceive(new byte[] {
                    (byte)0xA2,  /* CMD = WRITE */
                    (byte)0x2D,  /* PAGE = 45    */
                    (byte)0x41, (byte)0x45, (byte)0x52, (byte)0x42  /* 41 45 52 42 */
            });
    
    byte[] result3 = mifare.transceive(new byte[] {
                    (byte)0xA2,  /* CMD = WRITE */
                    (byte)0x2E,  /* PAGE = 46    */
                    (byte)0x21, (byte)0x4E, (byte)0X41, (byte)0X43  /* 21 4E 41 43 */
            });
    
    byte[] result4 = mifare.transceive(new byte[] {
                    (byte)0xA2,  /* CMD = WRITE */
                    (byte)0x2F,  /* PAGE = 47    */
                    (byte)0X55, (byte)0X4F, (byte)0X59, (byte)0X46  /* 55 4F 59 46 */
            });
    //Finish authenticating
    
    //Say the pages the card needs authentication
    byte[] result5 = mifare.transceive(new byte[] {
                    (byte)0xA2,  /* CMD = WRITE */
                    (byte)0x2A,  /* PAGE = 42    */
                    (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00  /* Message = All pages after 04 needs authentication */
            });
    
    byte[] result6 = mifare.transceive(new byte[] {
                    (byte)0xA2,  /* CMD = WRITE */
                    (byte)0x2B,  /* PAGE = 43    */
                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00  /* Message = authentication is required both for reading and writing */
            });
    //Finish "card activition"
    

    执行此操作后,我使用NXP TagInfo应用程序再次读取标记,并且正如预期的那样,我再也看不到标记信息了。而不是那样,它在所有字段(从04开始)上指示 .p XX XX XX XX ,这表示它需要密码才能读取数据。

    之后(这里我无法看到我的错误)我尝试再次验证标签(通过写入第2C - 2F页),但我在验证部分的开头出现此错误:

    System.err: java.io.IOException: Transceive failed
    System.err:     at android.nfc.TransceiveResult.getResponseOrThrow(TransceiveResult.java:52)
            at android.nfc.tech.BasicTagTechnology.transceive(BasicTagTechnology.java:151)
            at android.nfc.tech.MifareUltralight.transceive(MifareUltralight.java:215)**
    

    我看不出我做错了什么......

1 个答案:

答案 0 :(得分:3)

您做错了什么,是您实际上没有实现MIFARE Ultralight C身份验证。在MIFARE Ultralight C标签上,写入页面0x2C..0x2F完全符合命令的要求:它写入到这些页面,但是执行任何身份验证。

相反,MIFARE Ultralight C实现了一种三向相互质询-响应身份验证协议。通过发送AUTHENTICATE命令来启动该协议:

byte[] result1 = mifare.transceive(new byte[] {
            (byte)0xA1,  /* CMD = AUTHENTICATE */
            (byte)0x00
});

作为对该命令的响应,您将面临一个挑战,您需要使用身份验证密钥进行解密,操作,加密并发送回标签以证明您确实构成了身份验证密钥。您可以在此问答中找到一些实现MIFARE Ultralight C身份验证的代码:Android: Authenticating with NXP MiFare Ultralight C