簡體   English   中英

在Android上使用NFC軟件卡仿真來控制完整的APDU

[英]Control full APDU with NFC Software Card Emulation on Android

我正在使用一個應用程序來模擬Nexus 7(帶有CM10.1)與ACR122U102讀寫器之間的正常APDU通信。 我找到了有關軟件卡仿真的博客,並寫了一個應用程序使我的設備(鏈接)顯示為卡。 現在,我正在嘗試在此設備與ACR122u之間來回發送消息。 到目前為止,我僅通過發送D4 40 01( InDataExchange頁面127)AP​​DU來設法與nexus 7通信。 對於我正在編寫的應用程序,這應該足夠了。

問題出在我從設備發送給閱讀器的答案中。 使用transcieve函數(帶有反射的android.nfc.tech.IsoPcdA ),我可以使用長度大於0的字節數組進行答復。這將在讀取器端顯示,就像普通的InDataExchange響應一樣(例如:D5 41 00 01 02 03,其中{01 02 03}是提供給transcieve函數的字節數組)。 但是我無法控制響應中的狀態字節或SW字節(D5 41 XX和兩個SW)。 除了源代碼本身之外,沒有關於此IsoPcdA類的文檔。

我想要做的是將XX更改為我選擇的字節,並發送長度= 0的答案(例如:D5 41 01,沒有任何額外的數據)。 可能嗎?

我不確定您要在這里實現什么。 不論您使用IsoPcdA的收發方法進行收發的是什么,都是完整的APDU(如ISO / IEC 7816-4所定義,或者是ISO-DEP傳輸協議中的任何PDU)。 因此,收發的返回值為完整的C-APDU(命令APDU),收發的字節數組參數為完整的R-APDU(響應APDU),其中包括狀態字的兩個字節(SW1 | SW2)。 因此,該參數的最后兩個字節是狀態字。 在您的示例中,SW1為02,SW2為03。

您在PN532 NFC控制器的InDataExchange命令中看到的狀態字節不是APDU的狀態字,而是PN532 NFC控制器中命令執行的狀態。 此狀態字節為您提供有關緩沖區溢出,通信超時等的信息,而不是卡側返回的信息。

編輯:示例代碼+測試命令:

在Galaxy Nexus(CM 10)上運行的示例代碼:

try {
  Class isoPcdA = Class.forName("android.nfc.tech.IsoPcdA");
  Method isoPcdA_get = isoPcdA.getDeclaredMethod("get", Tag.class);

  final IsoPcdA techIsoPcdA = (IsoPcdA)isoPcdA_get.invoke(null, tag);

  if (techIsoPcdA != null) {
    if (mWorker != null) {
      mInterrupt = true;
      mWorker.interrupt();
      try {
        mWorker.join();
      } catch (Exception e) {}
    }

    mInterrupt = false;
    mWorker = new Thread(new Runnable() {
      public void run () {
        try {
          techIsoPcdA.connect();

          byte[] command = techIsoPcdA.transceive(new byte[]{ (byte)0x90, (byte)0x00 });
          Log.d(CardEmulationTest.class.getName(), "Connected.");

          while (!mInterrupt) {
            Log.d(CardEmulationTest.class.getName(), "C-APDU=" + StringUtils.convertByteArrayToHexString(command));
            command = techIsoPcdA.transceive(command);
          }
        } catch (Exception e) {
          Log.e(CardEmulationTest.class.getName(), "Exception while communicating on IsoPcdA object", e);
        } finally {
          try {
            techIsoPcdA.close();
          } catch (Exception e) {}
        }
      }
    });

    mWorker.start();
  }
} catch (Exception e) {
  Log.e(CardEmulationTest.class.getName(), "Exception while processing IsoPcdA object", e);
}

測試(使用ACR122U):

InListPassivTargets(1個目標,速率為106kbps)

> FF00000004 D44A 0100 00
< D54B 010100046004088821310578338800 9000

DATA = 0x01的InDataExchange

> FF00000004 D440 01 01 00
< D541 00 01 9000

因此,我們從讀卡器獲得了錯誤代碼0x00(InDataExchange命令的狀態;不是實際響應APDU的一部分),我們獲得了0x01作為響應(這是IsoDepA響應APDU),並且獲得了0x9000作為該設備的狀態代碼讀卡器包裝APDU(不屬於實際響應APDU的一部分)。

具有DATA的InDataExchange = 0x01 0x02

> FF00000005 D440 01 0102 00
< D541 00 0102 9000

因此,我們從讀卡器獲得了錯誤代碼0x00(InDataExchange命令的狀態;不是實際響應APDU的一部分),我們獲得了0x01 0x02作為響應(這是IsoDepA響應APDU),並且我們獲得了0x9000作為狀態代碼用於讀卡器包裝APDU(不是實際響應APDU的一部分)。

具有DATA的InDataExchange = 0x01 0x02 0x03

> FF00000006 D440 01 010203 00
< D541 00 010203 9000

因此,我們從讀卡器獲得了錯誤代碼0x00(InDataExchange命令的狀態;不是實際響應APDU的一部分),我們獲得了0x01 0x02 0x03作為響應(這是IsoDepA響應APDU),並且獲得了0x9000作為狀態讀卡器包裝APDU的代碼(不是實際響應APDU的一部分)。

具有DATA的InDataExchange = 0x01 0x02 0x03 0x04

> FF00000007 D440 01 01020304 00
< D541 00 01020304 9000

因此,我們從讀卡器得到了錯誤代碼0x00(InDataExchange命令的狀態;不是實際響應APDU的一部分),我們得到0x01 0x02 0x03 0x04作為響應(這是IsoDepA響應APDU),而我們得到0x9000作為讀卡器包裝APDU的狀態代碼(不屬於實際響應APDU的一部分)。

因此,我們確切地獲得了作為命令APDU發送的數據,作為響應APDU(請注意,這些APDU均未按照ISO 7816-4進行格式化,但這無關緊要,因為IsoPcdA卡仿真可與任何ISO 14443-4傳輸協議一起使用格式)。

狀態代碼0x9000屬於讀卡器APDU封裝( CLA = FF INS = 00 P1P2 = 0000 Lc [PN542 COMMAND] Le = 00 ),因為通過CCID(PC / SC)接口訪問ACR122U的PN532。 這些是純閱讀器命令封裝,與通過ISO-DEP進行的通信無關。

D440 01 [DATA]是通過ISO-DEP交換數據(例如APDU)的PN532命令,而D541 00 [DATA]是相關的響應。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM