2013-10-17 13 views
38

Ich habe seit mehr als einer Woche versucht, ein Android-Handy authentifizieren mit einem Mifare Ultralight C. Ich habe bestätigt, dass ich auf das Tag schreiben kann (durch Schreiben auf eine ungesicherte Speicherseite und dann lesen, was ich geschrieben habe). Ich kann auch auf die Schlüsselseiten schreiben (44-47) und habe 0x00 für alle 16 Schlüsselbytes geschrieben.Android: Authentifizierung mit NXP MiFare Ultralight C

Wenn ich versuche, mich zu authentifizieren, ist das folgende ein Beispiel für die Daten, die während eines Austauschs beteiligt sind - es stammt aus einem Protokoll, das von meiner Anwendung geschrieben wurde. Kann mir jemand sagen, ob ich etwas falsch mache? I AM unter Geheimhaltung und haben Zugriff auf die vollen Datenblätter. Beachten Sie, dass die folgenden hexadezimalen Zeichenfolgen für den Benutzer lesbare Versionen der gesendeten und empfangenen Daten sind, die im Code aus Bytearrays bestehen.

Senden Authentifizieren Befehl

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 

Nach 0xAF + E36C6C46FAAC60BA45DDF5F5A0802C79 Senden verliere ich sofort die Verbindung mit dem Tag. Ich habe das Datenblatt durchgelesen und lese jeden Beitrag, den ich hier finden kann. Ich habe mir auch den libfreefare-Code angeschaut und kann ehrlich nicht herausfinden, was ich falsch mache.

Der technische Support von NXP reagierte nicht mehr.

Irgendwelche Ideen? Ich bin ratlos.

+1

Ich fand die Beispiele in NXP Application Note AN0945 sehr lehrreich und nützlich für die Fehlersuche in meinem eigenen Code. –

+0

Großartig, danke! Ich habe das vermisst, weil es ein DESFire-Dokument ist und ich habe diesen Ordner im DocStore nicht beachtet. Ich habe gerade heruntergeladen und es sieht vielversprechend aus. Nochmals vielen Dank - ich schätze Ihre Eingabe sehr. –

+1

NFCGuy - Haben Sie (oder hat jemand, den Sie kennen) erfolgreich eine End-to-End-Authentifizierung mit einem Ultralight-C mit einem Android-Gerät durchgeführt? –

Antwort

1

Unten ist ein Beispiel Java-Code Ultralight-C-Authentifizierung durchzuführen, wie in MF0ICU2/MIFARE Ultralight C - Contactless ticket IC document (Kapitel 7.5.5 - 3DES Authentifizierung, Seite 15) beschrieben:

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

Anmerkung: Dieser Code verwendet Apache Commons Lang.