開発環境構築
こちらを参照 smartcardguy.hatenablog.jp
Java Card Service
Serviceアプリ
- javacard.framework.service (Class BaseService)の使い方
- BasicServiceにはhelper method (getCLA, get INS等)が多数用意されているので、Codeの書き方が簡単
- 仕様
- INS = 0x10の場合、data "0xAB"とstatus word 6617を返す。
- INS = 0x20の場合、status word 6618を返す。
- INS = 0x30の場合、status word 9000を返す。
File構成
- Main.java
- TestService.java
- PreProcess.java
- PostProcess.java
Source code
Main.java
package com.sun.jcclassic.samples.service; import javacard.framework.APDU; import javacard.framework.ISOException; import javacard.framework.service.Dispatcher; import javacard.framework.service.Service; /** * */ public class Main extends javacard.framework.Applet { private Dispatcher disp; private Service serv; public Main() { disp = new Dispatcher((short) 1); serv = new TestService(); disp.addService(serv, Dispatcher.PROCESS_COMMAND); register(); } public static void install(byte[] aid, short s, byte b) { new Main(); } @Override public void process(APDU apdu) throws ISOException { if(!selectingApplet()){ disp.process(apdu); } } }
TestService.java
/** * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * */ package com.sun.jcclassic.samples.service; import javacard.framework.APDU; import javacard.framework.service.BasicService; /** * */ public class TestService extends BasicService { @Override public boolean processCommand(APDU command) { if (getINS(command) == (byte) 0x10) { setOutputLength(command, (short) 1); command.getBuffer()[5] = (byte) 0xAB; succeedWithStatusWord(command, (short) 0x6617); return true; } if (getINS(command) == (byte) 0x20) { setOutputLength(command, (short) 0); succeedWithStatusWord(command, (short) 0x6618); return true; } if (getINS(command) == (byte) 0x30) { setOutputLength(command, (short) 0); succeed(command); return true; } return false; } }
PreProcess.java
/** * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * */ package com.sun.jcclassic.samples.service; /** * */ public class PreProcess { /** Creates new PreProcess */ public PreProcess() { } }
PostProcess.java
package com.sun.jcclassic.samples.service; /** * */ public class PostProcess { /** Creates new PostProcess */ public PostProcess() { } }
service.scr
//Test script for Applet 'Service' output on; //create Service 0x80 0xB8 0x00 0x00 0x0C 0x0A 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x0c 0x09 0x01 0x00 0x7F; // Select Service //aid/A000000062/03010C0901 0x00 0xA4 0x04 0x00 0x0a 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x0c 0x09 0x01 0x7F; //Send the APDU here 0x80 0x10 0x00 0x00 0x00 0x7F; 0x80 0x20 0x00 0x00 0x00 0x7F; 0x80 0x30 0x00 0x00 0x00 0x7F;
実行
- 「Run Configuration」機能を利用した実行の仕方はここを参照。https://docs.oracle.com/en/java/javacard/3.1/guide/running-service-sample-eclipse.html
- ここでは、HelloWorldサンプルと同じく手っ取り早く下記の3つのスクリプトを実行
- cap-com.sun.jcclassic...service.script実行 : service.capをインストール
- create-com.sun.jcclassic...Main.script : Main appletのInstance作成
- service.scr : Service作成、Select, Send APDU
実行結果
CMD>//Test script for Applet 'Service' output on; APDU|OUTPUT ON; //create Service 0x80 0xB8 0x00 0x00 0x0C 0x0A 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x0c 0x09 0x01 0x00 0x7F; APDU|CLA: 80, INS: b8, P1: 00, P2: 00, Lc: 0c, 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 09, 01, 00, Le: 00, SW1: 64, SW2: 44 // Select Service //aid/A000000062/03010C0901 0x00 0xA4 0x04 0x00 0x0a 0xa0 0x00 0x00 0x00 0x62 0x03 0x01 0x0c 0x09 0x01 0x7F; APDU|CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 09, 01, Le: 00, SW1: 90, SW2: 00 //Send the APDU here 0x80 0x10 0x00 0x00 0x00 0x7F; APDU|CLA: 80, INS: 10, P1: 00, P2: 00, Lc: 00, Le: 01, ab, SW1: 66, SW2: 17 0x80 0x20 0x00 0x00 0x00 0x7F; APDU|CLA: 80, INS: 20, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 66, SW2: 18 0x80 0x30 0x00 0x00 0x00 0x7F; APDU|CLA: 80, INS: 30, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 90, SW2: 00 CMD>
OUTPUTの解析
//Send the APDU here 0x80 0x10 0x00 0x00 0x00 0x7F; <= INS : 10 APDU|CLA: 80, INS: 10, P1: 00, P2: 00, Lc: 00, Le: 01, ab, SW1: 66, SW2: 17 <= Le (Response data length) : 0x01, data : 0xab 0x80 0x20 0x00 0x00 0x00 0x7F; <= INS : 20 APDU|CLA: 80, INS: 20, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 66, SW2: 18 0x80 0x30 0x00 0x00 0x00 0x7F; <= INS : 30 APDU|CLA: 80, INS: 30, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 90, SW2: 00