2016-12-09 18 views
2

我嘗試從奧地利電子卡片上讀取信息以獲取名字和姓氏。如何將來自奧地利電子卡的ResponseAPDU解碼爲XML?

現在有效的是:訪問該卡,發送APDU命令並獲取字節數組的信息。

如何將接收到的字節數組轉換爲XML以提取所需的數據?

下面是代碼:

import java.util.List; 

import javax.smartcardio.Card; 
import javax.smartcardio.CardChannel; 
import javax.smartcardio.CardException; 
import javax.smartcardio.CardTerminal; 
import javax.smartcardio.CommandAPDU; 
import javax.smartcardio.ResponseAPDU; 
import javax.smartcardio.TerminalFactory; 

public class Main2 { 
    public static void main(String[] args) { 
     TerminalFactory factory = TerminalFactory.getDefault(); 
     List<CardTerminal> terminals; 
     try { 
      terminals = factory.terminals().list(); 
      CardTerminal terminal = terminals.get(0); 
      Card card = terminal.connect("*"); 
      CardChannel channel = card.getBasicChannel(); 
      // Select the MF 
      byte[] aid = { (byte) 0xD0, 0x40, 0x00, 0x00, 0x17, 0x01, 0x01, 0x01 }; 
      ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x04, 0x00, aid)); 
      System.out.println("Response: " + resp.toString()); 
      // Select the Personaladata-file 
      byte[] aid2 = { (byte) 0xEF, 0x01 }; 
      resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x02, 0x04, aid2)); 
      System.out.println("Response: " + resp.toString()); 
      // Get the data from the file 
      resp = channel.transmit(new CommandAPDU(0x00, 0xB0, 0x00, 0x00, 0xFF)); 
      System.out.println("Response: " + resp.toString()); 
      System.out.println("Response String: " + new String(resp.getData())); 
      card.disconnect(false); 
     } catch (CardException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

回答

3

我不知道如何將這些數據轉換爲XML結構(以及按照什麼模式)。但是,我從我的SV卡接收的字節數組看起來像一個ASN.1 DER編碼TLV結構:

 
30 xxxx 
SEQUENCE 
    30 18 
    SEQUENCE 
     06 08 
     OBJECT IDENTIFIER 
      2A28000A01040101 
      => OID 1.2.40.0.10.1.4.1.1 (SV number) 
     31 0C 
     SET 
      12 0A 
      NumericString 
       nnnnnnnnddddmmmmyyyy 
       => SV number: NNNN DDMMYY 
    30 0F 
    SEQUENCE 
     06 08 
     OBJECT IDENTIFIER 
      2A28000A01040103 
      => OID 1.2.40.0.10.1.4.1.3 (Card sequence number) 
     31 03 
     SET 
      02 01 
      INTEGER 
       xx 
       => Card sequence number: xx 
    30 xx 
    SEQUENCE 
     [...] 
    30 xx 
     SEQUENCE 
     06 03 
     OBJECT IDENTIFIER 
      55042A 
      => OID 2.5.4.42 ({joint-iso-itu-t(2) ds(5) attributeType(4) givenName(42)}) 
     31 xx 
     SET 
      0C xx 
      UTF8String 
       4D69636861656C 
       => Given name: "Michael" 
    30 xx 
    SEQUENCE 
     06 03 
     OBJECT IDENTIFIER 
      550404 
      => OID 2.5.4.4 ({joint-iso-itu-t(2) ds(5) attributeType(4) surname(4)}) 
     31 xx 
     SET 
      0C xx 
      UTF8String 
       526F6C616E64 
       => Surname: "Roland" 
    30 xx 
    SEQUENCE 
     [...] 
    30 1D 
    SEQUENCE 
     06 08 
     OBJECT IDENTIFIER 
      2B06010505070901 
      => OID 1.3.6.1.5.5.7.9.1 ({iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) pda(9) dateOfBirth(1)}) 
     31 11 
     SET 
      18 0F 
      GeneralizedTime 
       yyyyyyyymmmmdddd3132303030305A 
       => Date of birth: YYYY-MM-DD 12:00:00Z 
    30 0F 
    SEQUENCE 
     06 08 
     OBJECT IDENTIFIER 
      2B06010505070903 
      => OID 1.3.6.1.5.5.7.9.3 ({iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) pda(9) gender(3)}) 
     31 03 
     SET 
      13 01 
      PrintableString 
       4D 
       => Gender: M (male) 

所以這似乎遵循類似下面的ASN.1表示法:

SVPersonGrunddaten ::= SEQUENCE OF Attribute 
Attribute ::= SEQUENCE { 
    attributeName OBJECT IDENTIFIER, 
    attributeValue SET OF AttributeType } 
AttributeType ::= CHOICE { 
    numericString NumericString, 
    integer INTEGER, 
    utf8String UTF8String, 
    time GeneralizedTime, 
    printableString PrintableString } 

凡給定的名字和姓氏的屬性

givenName Attribute ::= { 
    attributeName 2.5.4.42, 
    attributeValue { utf8String "Given Name" } 
} 
surname Attribute ::= { 
    attributeName 2.5.4.4, 
    attributeValue { utf8String "Surname" } 
} 

因此,爲了獲得給定的名稱和姓,你會解析TLV結構,尋找這兩個元素的OID,並將相關值解碼爲UTF8字符串。

請注意,簡單地假設字段在確切的位置,似乎不是一個好主意。例如,在給定名稱字段之前有一個字段30 xx ...(類型爲Attribute的字段),似乎只有在卡片上打印有學術/職業頭銜(例如我的情況下爲「Dr.」)時才存在。同樣,學術後綴還有另一個可選字段(例如「M.Sc.」),只有在卡上印有這樣的後綴時才存在。雖然所有其他字段在我的卡片上總是以相同的順序排列,但我不確定這是否甚至是必需的。

1

謝謝你的提示,這裏是代碼爲DER字節數組解碼爲字符串

ASN1InputStream input = new ASN1InputStream(resp.getData()); 
      ASN1Primitive p; 
      try { 
       while ((p = input.readObject()) != null) { 
        // System.out.println("DEBUG: " + ASN1Dump.dumpAsString(p)); 
        // Sozialversicherungsnummer 
        ASN1Sequence asn1 = ASN1Sequence.getInstance(p); 
        ASN1Sequence seq = DLSequence.getInstance(asn1.getObjectAt(0)); 
        ASN1Set svn = DLSet.getInstance(seq.getObjectAt(1)); 
        DERNumericString svnObject = DERNumericString.getInstance(svn.getObjectAt(0)); 
        System.out.println("SVN: " + svnObject.getString()); 

        // Vorname 
        seq = DLSequence.getInstance(asn1.getObjectAt(2)); 
        svn = DLSet.getInstance(seq.getObjectAt(1)); 
        DERUTF8String stringObject = DERUTF8String.getInstance(svn.getObjectAt(0)); 
        System.out.println("Vorname: " + stringObject.getString()); 

        // Nachname 
        seq = DLSequence.getInstance(asn1.getObjectAt(3)); 
        svn = DLSet.getInstance(seq.getObjectAt(1)); 
        stringObject = DERUTF8String.getInstance(svn.getObjectAt(0)); 
        System.out.println("Vorname: " + stringObject.getString()); 

        // Geschlecht 
        seq = DLSequence.getInstance(asn1.getObjectAt(5)); 
        svn = DLSet.getInstance(seq.getObjectAt(1)); 
        DERPrintableString charObject = DERPrintableString.getInstance(svn.getObjectAt(0)); 
        System.out.println("Geschlecht: " + charObject.getString()); 
       } 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
+0

要知道,給定名稱的索引,姓和性別領域可能會有所不同,所以'asn1.getObjectAt (2)''不會總是給你指定的名字等等。例如,這是一個前綴的學術名稱或後綴學術學位的附加字段的情況。我只是檢查了我以前的卡片,如果沒有標題或後綴,這些字段根本不存在。 –