带有ISO 7816-4 APDU的DESFire卡中的外部身份验证 [英] External authentication in DESFire card with ISO 7816-4 APDUs

查看:107
本文介绍了带有ISO 7816-4 APDU的DESFire卡中的外部身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用ISO 7816-4 APDU在DESFire卡(居民卡)上进行身份验证过程.但是它总是失败.我会想念吗?

I tried to do the authentication process on a DESFire card (resident card) using ISO 7816-4 APDUs. But it always fails. Do I miss anyithing?

>>> 00 84 00 00 00 (挑战请求-5个字节)

>>> 00 84 00 00 00 (challenge request - 5 bytes)

<<< 15 29 84 E3 6A AA A6 B7 90 00 (挑战10字节的响应-确定)

<<< 15 29 84 E3 6A AA A6 B7 90 00 (response of challenge 10 bytes - OK)

>>> 00 82 00 00 10 B5 02 0B 80 4F 95 CB E7 8C A6 4D E9 C1 B1 23 A7 00 (外部身份验证请求-22字节)

>>> 00 82 00 00 10 B5 02 0B 80 4F 95 CB E7 8C A6 4D E9 C1 B1 23 A7 00 (external auth request - 22 bytes)

<<< 67 00 (外部身份验证的响应-检查错误:长度错误)

<<< 67 00 (response of external auth - Checking error: Wrong length)

代码:

// STEP Authentication
// send initial authentication request
byte[] reqRnbEnc = new byte[]{
        (byte) 0x00,
        (byte) 0x84,
        (byte) 0x00, (byte) 0x00,
        (byte) 0x00};

// get encrypted RndB
byte[] resRnbEnc = _isoDep.transceive(reqRnbEnc);
_responseTextView.append(String.format("reqRnbEnc: %s length:%d\n", BytesToHexStr(reqRnbEnc), reqRnbEnc.length));
_responseTextView.append(String.format("resRnbEnc: %s length:%d\n", BytesToHexStr(resRnbEnc), resRnbEnc.length));

// remove 2 last characters
byte[] resRnbEncT = new byte[8];
System.arraycopy(resRnbEnc, 0, resRnbEncT, 0, 8);
_responseTextView.append(String.format("-resRnbEncT: %s length:%d\n", BytesToHexStr(resRnbEncT), resRnbEncT.length));

// decrypt RndB
byte[] resRnbDec = MyDES.decrypt(resRnbEncT);
_responseTextView.append(String.format("-resRnbDec: %s length:%d\n", BytesToHexStr(resRnbDec), resRnbDec.length));

// generate RndA
byte[] Rna = new byte[8];
new SecureRandom().nextBytes(Rna);
_responseTextView.append(String.format("-Rna: %s length:%d\n", BytesToHexStr(Rna), Rna.length));

// plain = concate RndA with resRnbDec
byte[] plain = new byte[16];
System.arraycopy(Rna, 0, plain, 0, 8);
System.arraycopy(resRnbDec, 0, plain, 8, 8);
_responseTextView.append(String.format("-plain: %s length:%d\n", BytesToHexStr(plain), plain.length));

//  cipher = encrypt plain
byte[] cipher = MyDES.encrypt(plain);
_responseTextView.append(String.format("-cipher: %s length:%d\n", BytesToHexStr(cipher), cipher.length));

// send cipher request
byte[] reqCipher = new byte[22];
reqCipher[0] = (byte) 0x00;
reqCipher[1] = (byte) 0x82;
reqCipher[2] = (byte) 0x00;
reqCipher[3] = (byte) 0x00;
reqCipher[4] = (byte) cipher.length;
System.arraycopy(cipher, 0, reqCipher, 5, cipher.length);
reqCipher[21] = (byte) 0x00;

// get response
byte[] resCipher = _isoDep.transceive(reqCipher);
_responseTextView.append(String.format("reqCipher: %s length:%d\n", BytesToHexStr(reqCipher), reqCipher.length));
_responseTextView.append(String.format("resCipher: %s length:%d\n", BytesToHexStr(resCipher), resCipher.length));

加密:

public class MyDES {
private static String ENCRYPTION_KEY_TYPE = "DESede";
private static String ENCRYPTION_ALGORITHM = "DESede/CBC/NoPadding";

private static byte[] key = new byte[]{
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

private static byte[] iv = new byte[]{
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

public static byte[] encrypt(byte[] plainText) {
    try {
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        SecretKey secretKey = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE);
        Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        byte[] encrypted = cipher.doFinal(plainText);
        return encrypted;
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    }
    return null;
}

public static byte[] decrypt(byte[] cipherText) {
    try {
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        SecretKey secretKey = new SecretKeySpec(key, ENCRYPTION_KEY_TYPE);
        Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        byte[] decrypted = cipher.doFinal(cipherText);
        return decrypted;
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    }
    return null;
}

推荐答案

外部身份验证命令不得包含Le字段.当您包含一个Le字段(最后一个字节编码为 0x00 )时,您会收到错误的长度错误.因此,您的命令应如下所示:

The external authenticate command must not contain an Le field. As you included an Le field (last byte encoded as 0x00), you receive a wrong length error. So your command should look like:

00 82 00 00 10 B5 02 0B 80 4F 95 CB E7 8C A6 4D E9 C1 B1 23 A7

在代码中:

byte[] reqCipher = new byte[5 + cipher.length];
reqCipher[0] = (byte) 0x00;
reqCipher[1] = (byte) 0x82;
reqCipher[2] = (byte) 0x00;
reqCipher[3] = (byte) 0x00;
reqCipher[4] = (byte) (cipher.length & 0x0ff);
System.arraycopy(cipher, 0, reqCipher, 5, cipher.length);

Aslo在开始使用PICC主密钥(P2 = 0)进行身份验证之前,请确保已选择主文件(主应用程序).尤其是因为Android可能已预先选择了另一个应用程序.

Aslo make sure that you selected the master file (master application) before starting to authenticate with the PICC master key (P2=0). Particularly as Android may have previosuly selected another application.

这篇关于带有ISO 7816-4 APDU的DESFire卡中的外部身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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