2013-10-17 40 views
38

我一直在嘗試超過一個星期才能使Android手機通過Mifare Ultralight C進行身份驗證。我已確認可以寫入標記(通過寫入不安全的內存頁面和然後閱讀我寫的)。我還可以寫入關鍵頁面(44-47),併爲所有16個關鍵字節寫入0x00。Android:使用NXP進行身份驗證MiFare Ultralight C

當我嘗試進行身份驗證時,以下是一個交換過程中涉及的數據示例 - 它來自我的應用程序編寫的日誌。任何人都可以告訴我,如果我做錯了什麼? I AM未披露,並有權訪問完整數據表。請注意,下面的十六進制字符串顯然是人們可讀的數據發送和接收版本,其中代碼由字節數組組成。

發送身份驗證命令

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的代碼,我真的不知道我做錯了什麼。

恩智浦技術支持完全沒有響應。

任何想法?我很茫然。

+1

我在恩智浦應用筆記AN0945中找到了非常有益的實例,可用於調試我自己的代碼。 –

+0

太好了,謝謝!我錯過了,因爲它是DESFire文檔,我沒有注意到DocStore中的文件夾。我剛下載,看起來很有希望。再次感謝 - 我非常感謝您的意見。 –

+1

NFCGuy - 您(或您認識的任何人)是否使用Android設備成功地通過Ultralight-C進行了端到端身份驗證? –

回答

1

下面是一個例子的java代碼作爲MF0ICU2/MIFARE Ultralight C - Contactless ticket IC document(章節7.5.5 - 3DES認證,第15頁)中所描述來執行超輕-C認證:

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

注意:此代碼使用Apache Commons Lang