2013-10-17 7 views
38

Ho provato per più di una settimana a effettuare l'autenticazione di un telefono Android con un Mifare Ultralight C. Ho confermato che posso scrivere sul tag (scrivendo su una pagina di memoria non protetta e poi leggendo ciò che ho scritto). Posso anche scrivere sulle pagine chiave (44-47) e avere scritto 0x00 per tutti i 16 byte chiave.Android: autenticazione con NXP MiFare Ultralight C

Quando si tenta di eseguire l'autenticazione, il seguente è un esempio dei dati coinvolti durante uno scambio: si tratta di un log scritto dalla mia applicazione. Qualcuno può dirmi se sto facendo qualcosa di sbagliato? I AM in caso di mancata comunicazione e accesso alle schede tecniche complete. Si noti che le stringhe esadecimali di seguito sono ovviamente versioni leggibili dall'uomo dei dati inviati e ricevuti, che nel codice sono costituiti da matrici di byte.

comando Invia autenticazione

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 

Dopo l'invio 0xAF + E36C6C46FAAC60BA45DDF5F5A0802C79 perdo immediatamente la connessione con il tag. Ho letto la scheda tecnica e ho letto tutti i post che riesco a trovare qui. Ho anche guardato il codice libfreefare e onestamente non riesco a capire cosa sto facendo male.

Il supporto tecnico NXP non rispondeva completamente.

Qualche idea? Sono in perdita.

+1

Ho trovato gli esempi in NXP Application Note AN0945 molto istruttivo e utile per il debug del mio codice. –

+0

Grande, grazie! L'ho perso perché è un documento DESFire e non ho prestato attenzione a quella cartella in DocStore. Ho appena scaricato e sembra promettente. Grazie ancora - apprezzo molto il tuo contributo. –

+1

NFCGuy - Hai (o qualcuno che conosci) eseguito con successo un'autenticazione end-to-end con un Ultralight-C utilizzando un dispositivo Android? –

risposta

1

seguito è riportato un esempio di codice Java per eseguire l'autenticazione Ultralight-C come descritto nel MF0ICU2/MIFARE Ultralight C - Contactless ticket IC document (capitolo 7.5.5 - Autenticazione 3DES, pagina 15):

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

Nota: Questo codice utilizza Apache Commons Lang.