2

PC/SC 非接触リーダーと javax.smartcardio API を介して Mifare DESFire カードと通信する Java アプリケーションを作成しています。通常の ISO 7816 APDU (CLA、INS、P1-P2、Lc、コマンド データ、Le) を送信することができました。

Ridrix のブログで、DESFire カード (少なくとも私が使用している EV1 バージョン) は APDU とネイティブ コマンドの両方をサポートし、コマンドのほとんどが 1 バイト長しかないことを読みました。

たとえば、「バージョンの取得」コマンド:

Command: 60
Response: af 04 01 01 00 02 18 05

このコマンドを SpringCard のPC /SC Diagプログラム(ここから入手可能) でテストしたところ、正しい応答が得られました。

しかし、javax.smartcardio でこのコマンドを送信することはできません。この API は実際のAPDU 用に作成されたようで、1 バイト長のコマンドは許可されません。

これが私がしたことです:

public static void main(String[] args){
    TerminalFactory factory = TerminalFactory.getDefault();
    CardTerminals terminalList = factory.terminals();

    try {
        CardTerminal ct = terminalList.list().get(0);       
        ct.waitForCardPresent(0);
        Card card = ct.connect("*");
        CardChannel channel = card.getBasicChannel();

        byte[] command = { 0x60 };

        channel.transmit(new CommandAPDU(command));
    } catch (CardException e) {
        e.printStackTrace();
    }
}

次のエラーが表示されます。

Exception in thread "main" java.lang.IllegalArgumentException: apdu must be at least 4 bytes long
    at javax.smartcardio.CommandAPDU.parse(Unknown Source)
    at javax.smartcardio.CommandAPDU.<init>(Unknown Source)

コマンドを送信する唯一の(AFAIK)他の方法を試しました:

        ByteBuffer command = ByteBuffer.allocate(1);
        command.put((byte) 0x60);

        ByteBuffer response = ByteBuffer.allocate(512);

        channel.transmit(command, response);

同様のエラーが発生します。

Exception in thread "main" java.lang.IllegalArgumentException: Command APDU must be at least 4 bytes long
    at sun.security.smartcardio.ChannelImpl.checkManageChannel(Unknown Source)
    at sun.security.smartcardio.ChannelImpl.doTransmit(Unknown Source)
    at sun.security.smartcardio.ChannelImpl.transmit(Unknown Source)

javax.smartcardio などを使用してこの種のコマンドを送信する方法を知っていますか?

これらのコマンドをラップできることはわかっていますが、(より単純な) ネイティブ コマンドを使用することをお勧めします。

ありがとう。

4

3 に答える 3

3

javax.smartcardioISO 7816-4 コマンドを使用するために作成された API です。したがって、「ネイティブ」コマンドを送信することはできません。基本的にネイティブコマンドはなんでもいいので対応は難しいです。

JNI に戻すか、または を使用するものを探してみてくださいtransmitControlCommand。しかし、追加のライブラリーなしに DESFire を実際に使用する方法はありません。

個人的には、ラッピングレイヤーを使用する方がはるかに簡単だと思います.

于 2012-07-28T00:10:42.717 に答える
3

ほぼ4年後ですが、誰かがこの質問に無精ひげを生やした場合に備えて、私はこれに対する答えを見つけました. 現在、多くの読者は、ISO 7816-4 コマンドでの Desfire APDU フレームのラッピングをサポートしています。データが 55 バイトを超えることができないという制限を発見しました。

詳細については、このドキュメントの 23 ページを参照してください: http://neteril.org/files/M075031_desfire.pdf

これは、APDU フレームをラップするために次を指定できることを意味します。

CLA = 0x90
INC = {Your Desfire Command e.g. 0x60 - Get Version}
P1 = 0
P2 = 0
Data = 1st byte = length of data followed by byte data. Terminate data with a 0x00 byte

応答も次のようにラップされます。

SW1 = 0x91
SW2 = Result Status
Data = Response Data

したがって、次のコードを使用できます

public static byte CMD_WRAP_START = (byte)0x90;
public static byte CMD_WRAP_END = (byte)0x00;

private CommandAPDU wrapAPDUFrameUsingISO7816_4(byte[] apdu) throws CardException {
    if (apdu.length > 55){
        throw new CardException("The length of the wrapped DESFire command must not be longer than 55 bytes, checksum included.");
    }
    boolean hasData = apdu.length > 1;
    byte[] result;
    if (hasData) {
        result = new byte[apdu.length + 5];
    } else {
        result = new byte[apdu.length + 4];
    }
    result[0] = CMD_WRAP_START; // CLA
    result[1] = apdu[0];        // DESFIRE CMD CODE
    result[2] = 0;              // P1
    result[3] = 0;              // P2
    if (hasData) {
        result[4] = (byte) (apdu.length - 1);  // Length of wrapped data, ONLY IF DATA EXISTS
        System.arraycopy(apdu,1,result,5,apdu.length-1); // DESFIRE Command data
    }
    result[result.length-1] = CMD_WRAP_END;
    return new CommandAPDU(result);
}

private static byte [] unwrapFromISO7816_4(byte[] wrapped) throws CardException {
    if (wrapped.length<2){
        throw new CardException("Expected at least 2 bytes for ISO 7816-4 wrapped response: " + String.valueOf(Hex.encodeHex(wrapped, false)));
    }
    if (wrapped[wrapped.length-2]!=(byte)0x91){
        throw new CardException("Expected 0x91 in SW1 for ISO 7816-4 wrapped response: " + String.valueOf(Hex.encodeHex(wrapped, false)));
    }
    byte[] result = new byte[wrapped.length-1];
    System.arraycopy(wrapped,0,result,1,wrapped.length-2);  // The DESFIRE response
    result[0] = wrapped[wrapped.length-1];  // The DESFIRE Status
    return result;
}
于 2017-01-18T21:14:14.613 に答える
1

ここに答えがあります。コマンド APDU は少なくとも 4 バイトである必要があります。

     * case 1 : |CLA|INS|P1 |P2 |                    len = 4 
     * case 2s: |CLA|INS|P1 |P2 |LE |                len = 5 
     * case 3s: |CLA|INS|P1 |P2 |LC |...BODY...|     len = 6..260 
     * case 4s: |CLA|INS|P1 |P2 |LC |...BODY...|LE | len = 7..261
     *
     * (Extended length is not currently supported) 
     * case 2e: |CLA|INS|P1 |P2|00 |LE1|LE2|                    len = 7 
     * case 3e: |CLA|INS|P1 |P2 |00|LC1|LC2|...BODY...|         len = 8..65542 
     * case 4e: |CLA|INS|P1 |P2 |00|LC1|LC2|...BODY...|LE1|LE2| len =10..65544
     *
     * EMV 
于 2013-02-13T19:11:36.470 に答える