2016-12-09 12 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, искать Идентификаторы этих двух элементов, и декодировать связанные значения как строку UTF8.

Обратите внимание, что просто считая, что поля находятся там, на точном месте, кажется, не очень хорошая идея. Например, есть поле 30 xx ... (поле типа Attribute) перед полем имени, которое, кажется, присутствует только в том случае, если на карте напечатано академическое/профессиональное название (например, «Доктор» в моем случае). Аналогичным образом, есть еще одно необязательное поле для академических суффиксов (например, «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) 'не всегда даст вам данное имя и т. Д. Это, например, случай, когда есть дополнительные поля для префикса академического звания или суффикс академической степени. Я только что проверил мои предыдущие карточки, и эти поля просто отсутствуют, если нет названия или суффикса. –