スマート カード リーダーで Maestro/Mastercard から口座番号を読み取る必要があります。Java 1.6 とその javax.smartcardio パッケージを使用しています。カードのチップに保存されている EMV アプリケーションに PAN 番号を要求する APDU コマンドを送信する必要があります。問題は、必要なデータをどこにでも返す APDU コマンドを構築するための通常のバイト配列が見つからないことです...
6 に答える
APDU をさらにラップする必要はありません。APIレイヤーがそれを処理する必要があります。
0x6D00 応答は、アプリケーションが INS をサポートしていなかったことを意味しているようです。
今、トラブルシューティングを行っていますが、MasterCard アプリケーションを選択することから始めましたよね?
つまり、次のようなものです。
void selectApplication(CardChannel channel) throws CardException {
byte[] masterCardRid = new byte[]{0xA0, 0x00, 0x00, 0x00, 0x04};
CommandAPDU command = new CommandAPDU(0x00, 0xA4, 0x04, 0x00, masterCardRid);
ResponseAPDU response = channel.transmit(command);
return response.getData();
}
ここにいくつかの実例があります:
CardChannel channel = card.getBasicChannel();
byte[] selectMaestro={(byte)0x00, (byte)0xA4,(byte)0x04,(byte)0x00 ,(byte)0x07 ,(byte)0xA0 ,(byte)0x00 ,(byte)0x00 ,(byte)0x00 ,(byte)0x04 ,(byte)0x30 ,(byte)0x60 ,(byte)0x00};
byte[] getProcessingOptions={(byte)0x80,(byte)0xA8,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x83,(byte)0x00,(byte)0x00};
byte[] readRecord={(byte)0x00,(byte)0xB2,(byte)0x02,(byte)0x0C,(byte)0x00};
ResponseAPDU r=null;
try {
ATR atr = card.getATR(); //reset kartice
CommandAPDU capdu=new CommandAPDU( selectMaestro );
r=card.getBasicChannel().transmit( capdu );
capdu=new CommandAPDU(getProcessingOptions);
r=card.getBasicChannel().transmit( capdu );
capdu=new CommandAPDU(readRecord);
r=card.getBasicChannel().transmit( capdu );
これは Maestro カードで動作し、PAN 番号を読み取ることができますが、MasterCard の PAN 番号を読み取る必要があります。読み取りレコード APDU を変更するか、アプリケーション APDU を選択する必要があるかわかりません。APDU に詳しい人はいますか?
atr = open();
prints(atr);
prints("[Step 1] Select 1PAY.SYS.DDF01 to get the PSE directory");
cmd = new ISOSelect(ISOSelect.SELECT_AID, EMV4_1.AID_1PAY_SYS_DDF01);
card_response = execute(cmd);
prints(card_response);
SFI = NumUtil.hex2String((byte)((1 < < 3) | 4));
// try SFI 1 record 1
prints("[Step 2] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord(SFI, "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());
prints("[Step 3] Send READ RECORD with 1C to get the PSE data");
read = new EMVReadRecord(SFI, "01", byte_size);
card_response = execute(read);
prints(card_response);
// the AID is A0000000031010
prints("[Step 4] Now that we know the AID, select the application");
cmd = new ISOSelect(ISOSelect.SELECT_AID, "A0000000031010");
card_response = execute(cmd);
prints(card_response);
prints("[Step 5] Send GET PROCESSING OPTIONS command");
cmd = new EMVGetProcessingOptions();
card_response = execute(cmd);
prints(card_response);
// SFI for the first group of AFL is 0C
prints("[Step 6] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord("0C", "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());
prints("[Step 7] Use READ RECORD with the given number of bytes to retrieve the data");
read = new EMVReadRecord("0C", "01", byte_size);
card_response = execute(read);
prints(card_response);
data = new TLV(card_response.getData());
close();
ドキュメントで 0x6D00 の意味を調べてみましたか? ENVELOPE コマンドがサポートされていないことを意味しているようです。T=1 の代わりに T=0 プロトコルを使用してみましたか?
私の例があなたのカードでうまくいくとは思いません。Maestro/MasterCard がサポートする APDU がわからないので、実際の例を示すことができませんでした。
次のように、コマンドに明示的な期待される長さを与えてみてください。
byte[] readPan(CardChannel channel) throws CardException {
CommandAPDU command = new CommandAPDU(0x00, 0xB2, 0x5a, 0x14, 250);
ResponseAPDU response = channel.transmit(command);
return response.getData();
}
CommandAPDU オブジェクトを作成し、それを transmit() コマンドに渡す必要があります。
スマートカードのドキュメントで正確なコマンドを見つけることができるはずですが、一例を次に示します。
byte[] readFile(CardChannel channel) throws CardException {
CommandAPDU command = new CommandAPDU(0xB0, 0x60, 0x10, 0x00);
ResponseAPDU response = channel.transmit(command);
return response.getData();
}
スキャナーを使用してカードの写真を取得し、優れた Java ocr ライブラリ (たとえばhttp://ocr4j.sourceforge.net/など) を使用して写真の内容をスキャンし、(通常は) 16 桁のシーケンスを検索します。 XXXX-XXXX-XXXX-XXXX の場合、Java を使用して任意の EMV カードから PAN を取得します。