首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android:使用NXP MiFare超光速C进行身份验证

Android:使用NXP MiFare超光速C进行身份验证
EN

Stack Overflow用户
提问于 2013-10-17 22:41:37
回答 1查看 4.7K关注 0票数 39

一个多星期以来,我一直在尝试用Mifare Ultralight C来验证Android手机的身份。我已经确认我可以写到标签上(写到一个不安全的内存页面,然后读取我写的内容)。我还可以写入键页(44-47),并为所有16个键字节编写了0x00。

当我试图进行身份验证时,下面是一个在一个交换过程中涉及的数据示例--它来自我的应用程序编写的日志。有人能告诉我我是否做错了什么吗?I AM在不公开的情况下,可以访问完整的数据表.注意,下面的十六进制字符串显然是正在发送和接收的数据的人类可读的版本,在代码中它由字节数组组成。

发送验证命令

代码语言:javascript
复制
Received rndB: 8A5735694D9D7542

Key: 00000000000000000000000000000000

IV: 0000000000000000

Decrypted rndB: EF340C62E1B866D4

rndB': 340C62E1B866D4EF

rndA: 6E262630E299F94F

rndA+rndB': 6E262630E299F94F340C62E1B866D4EF

Key: 00000000000000000000000000000000

IV: 8A5735694D9D7542

ek(RndA+rndB'): E36C6C46FAAC60BA45DDF5F5A0802C79

发送0xAF + E36C6C46FAAC60BA45DDF5F5A0802C79后,我立即失去与标记的连接。我已经翻阅了数据表,阅读了我在这里找到的每一篇文章。我也看过libfreefare代码,我真的不知道我做错了什么。

NXP技术支持完全没有反应。

有什么想法吗?我不知所措。

EN

回答 1

Stack Overflow用户

发布于 2017-06-19 21:49:16

下面是执行MF0ICU2 / MIFARE超光速C-非接触式票证IC文档中描述的Ultralight身份验证的示例java代码(第7.5.5--3 3DES身份验证,第15页):

代码语言:javascript
复制
public void authenticate(byte[] key) throws CardException {
    System.out.println("AUTHENTICATE");
    byte[] encRndB = transmitRaw(new byte[] { 0x1A, 0x00 });
    if((encRndB.length!=9)||(encRndB[0]!=AF)) {
        throw new RuntimeException("Invalid response!");
    }
    encRndB=Arrays.copyOfRange(encRndB, 1, 9);
    System.out.println(" - EncRndB: " + toHex(encRndB));
    byte[] rndB = desDecrypt(key, encRndB);
    System.out.println(" - RndB: " + toHex(rndB));
    byte[] rndBrot = rotateLeft(rndB);
    System.out.println(" - RndBrot: " + toHex(rndBrot));
    byte[] rndA = new byte[8];
    generateRandom(rndA);
    System.out.println(" - RndA: " + toHex(rndA));
    byte[] encRndArotPrime = transmitRaw(ArrayUtils.addAll(new byte[] {AF}, desEncrypt(key, ArrayUtils.addAll(rndA, rndBrot))));
    if((encRndArotPrime.length!=9)||(encRndArotPrime[0]!=0x00)) {
        throw new RuntimeException("Invalid response!");
    }
    encRndArotPrime=Arrays.copyOfRange(encRndArotPrime, 1, 9);
    System.out.println(" - EncRndArot': " + toHex(encRndArotPrime));
    byte[] rndArotPrime = desDecrypt(key, encRndArotPrime);
    System.out.println(" - RndArot': " + toHex(rndArotPrime));
    if(!Arrays.equals(rotateLeft(rndA), rndArotPrime)) {
        throw new RuntimeException("Card authentication failed");
    }
}

protected static SecureRandom rnd = new SecureRandom();
protected static void generateRandom(byte[] rndA) {
    rnd.nextBytes(rndA);
}

protected byte[] desEncrypt(byte[] key, byte[] data) {
    return performDes(Cipher.ENCRYPT_MODE, key, data);
}
protected byte[] desDecrypt(byte[] key, byte[] data) {
    return performDes(Cipher.DECRYPT_MODE, key, data);
}
private byte[] iv = new byte[8];
protected byte[] performDes(int opMode, byte[] key, byte[] data) {
    try {
        Cipher des = Cipher.getInstance("DESede/CBC/NoPadding");
        SecretKeyFactory desKeyFactory = SecretKeyFactory.getInstance("DESede");
        Key desKey = desKeyFactory.generateSecret(new DESedeKeySpec(ArrayUtils.addAll(key, Arrays.copyOf(key, 8))));
        des.init(opMode, desKey, new IvParameterSpec(iv));
        byte[] ret = des.doFinal(data);
        if(opMode==Cipher.ENCRYPT_MODE) {
            iv=Arrays.copyOfRange(ret, ret.length-8, ret.length);
        } else {
            iv=Arrays.copyOfRange(data, data.length-8, data.length);
        }
        return ret;
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidKeySpecException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
        throw new RuntimeException(e);
    }
}

protected static byte[] rotateLeft(byte[] in) {
    return ArrayUtils.add(Arrays.copyOfRange(in, 1, 8), in[0]);
}

注意:此代码使用阿帕奇公域朗

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19438554

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档