Android上的Mifare Ultralight C身份验证 [英] Mifare Ultralight C Authentication on Android

查看:265
本文介绍了Android上的Mifare Ultralight C身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些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. 49454D4B41455242214E4143554F5946从第2C页开始直到第2F页(用于身份验证).

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

  3. 在第2B页上写入0x00(43);意味着读和写都需要身份验证.

//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)**

我看不到我在做什么...

解决方案

您做错了什么,是您实际上没有实现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:使用NXP MiFare Ultralight C进行身份验证.

I have some Mifare Ultralight C tags for testing authentication.

The first time I read it with the app NXP TagInfo, I could see the following info:

(...)
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

The page 2C - 2F means that it had the default key "BREAKMEIFYOUCAN!" (425245414b4d454946594f5543414e21).

Then I ran my Android app which basically did this:

  1. Write 49454D4B41455242214E4143554F5946 starting from page 2C till page 2F (for authenticating).

  2. Write 0x04 at page 2A (42); meaning all the pages from 2A on need authentication.

  3. Write 0x00 at page 2B (43); meaning authentication is needed both for reading and writing.

//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"

After doing this, I read the tag again using the NXP TagInfo app, and as expected, I couldn't see the tag info anymore. Instead of that, it indicated .p XX XX XX XX on all fields (from 04 on), which indicates it needs password for reading the data.

After that (and here is where I can't see my mistake) I tried to authenticate the tag again (by writing to pages 2C - 2F), but I get this error at the beginning of the authentication part:

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)**

I can't see what I'm doing wrong...

解决方案

What you are doing wrong is that you did not actually implement the MIFARE Ultralight C authentication. On MIFARE Ultralight C tags, writing to pages 0x2C..0x2F does exactly what the command says: It writes to that pages, but it does not perform any authentication.

Instead, MIFARE Ultralight C implements a three-way mutual challenge-response authentication protocol. This protocol is started by sending an AUTHENTICATE command:

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

In response to that command, you will get a challenge that you need to decrypt using the authentication key, manipulate, encrypt and send back to the tag to proof that you actually posess the authentication key. You can find some code that implements MIFARE Ultralight C authentication in this Q/A: Android: Authenticating with NXP MiFare Ultralight C.

这篇关于Android上的Mifare Ultralight C身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆