如何从奥地利电子卡解码ResponseAPDU到XML?

时间:2016-12-09 18:35:42

标签: java xml smartcard apdu asn.1

我尝试从奥地利电子贺卡中读取信息以获得名字和姓氏。

现在有用的是:访问卡,发送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();
        }
    }
}

2 个答案:

答案 0 :(得分: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的字段),如果存在学术/职业标题,则该字段似乎仅存在(例如&#34; Dr。 &#34;在我的情况下)印在卡上。类似地,还有另一个学术后缀的可选字段(例如&#34; M.Sc。&#34;)只有在卡片上印有这样的后缀时才会出现。虽然我的卡片上的所有其他字段总是按照相同的顺序排列,但我不确定是否需要这样做。

答案 1 :(得分:1)

感谢提示,这里是将DER字节数组解码为String

的代码
main