2015-12-22 3 views
0

Я попытался выполнить процесс аутентификации на карте DESFire (резидентной карте) с использованием APDU ISO 7816-4. Но это всегда терпит неудачу. Я скучаю по любому?Внешняя аутентификация в карточке DESFire с ISO 7816-4 APDUs

>>>00 84 00 00 00 (запрос вызова - 5 байт)

< < < 15 29 84 E3 6A AA A6 B7 90 00 (ответ вызова 10 байт - OK)

>>>00 82 00 00 10 B5 02 0B 80 4F 95 CB E7 8C A6 4D E9 C1 B1 23 A7 00 (запрос внешней аутентификации - 22 байта)

< < < 67 00 (отклик внешней аутентификации - Ошибка проверки: Неверная длина)

Код:

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

Crypto:

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; 
} 

ответ

0

Команда внешней Аутентифицировать не должен содержать поле Le. Поскольку вы включили поле Le (последний байт, закодированный как 0x00), вы получаете ошибку неправильной длины. Таким образом, ваша команда должна выглядеть следующим образом:

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

АОЛО убедитесь, что вы выбрали мастер-файл (мастер-приложения), прежде чем начать проверку подлинности с помощью мастер-ключа PICC (P2 = 0). В частности, поскольку Android, возможно, ранее выбрал другое приложение.

+0

Спасибо, сэр. Как выбрать главный ключ PICC (p2 = 0)? Я не понимаю, я новый bie в среде nfc. – sams

+0

P2 - это то, что вы пишете в 'reqCipher [3]'. В настоящее время вы используете 0x00 и, следовательно, используете главный ключ PICC. –

+0

Я выбираю основное приложение перед процессом аутентификации с 00 A4 04 00 07 D2 76 00 00 85 01 00. Я получаю ошибку 6B00 – sams