Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1561623
  • 博文数量: 3500
  • 博客积分: 6000
  • 博客等级: 准将
  • 技术积分: 43870
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-03 20:31
文章分类

全部博文(3500)

文章存档

2008年(3500)

我的朋友

分类:

2008-05-04 19:17:21

一起学习
最近在开发一个基于CPU卡应用的J2EE项目,应用服务器用的是Weblogic,数据库是oracle, 开发工具jbuilder2005.系统架构是:客户端(pc/sc读写器)<应用服务器<加密机,应用服务器<数据库服务器. 客户端首先要安装IC读写器驱动(必须支持PC/SC规范),然后到pcscworkgroup网站下载文件installOCF.class和Reference_Impl.class. 运行>java installOCF 按照提示一步一步进行安装操作. 运行>java Reference_Impl 默认安装操作. 在安装完后将thirdparty\OCF1.2\lib\OCFPCSC1.DLL和thirdparty\OCF1.2\lib\OCFPCSCM.DLL拷贝到jdk的bin目录. 在jbuilder工程文件目录下建立opencard.properties文件,内容如下, # Configure the CardService Registry: # Use the service factory for the IBM MultiFunction Cards OpenCard.services = opencard.opt.util.PassThruCardServiceFactory #OpenCard.services = com.ibm.opencard.factory.MFCCardServiceFactory # OpenCard.services = com.slb.opencard.CyberflexAccess.CyberflexAccessCardServiceFactory # Configure the CardTerminal Registry: com.ibm.opencard.terminal.pcscmig.PcscMigCardTerminalFactory OpenCard.terminals = com.ibm.opencard.terminal.pcsc10.Pcsc10CardTerminalFactory # Configure Tracing. Detailed for all samples only: OpenCard.trace = opencard:8 在jbuilder中建立pcsc库. toolsconfigurelibraries 在user home下建立pcsc10,在required libraries选项卡中选择安装的目录下lib下的所有文件. 我用的读写期是某公司的,命令集与PBOC稍有改动,但基本格式是按照PCSC的. 我建立了3个文件: 接口文件:IReader.java,用于程序将来兼容其他读写器; 实现文件:ReaderMA,java,实现接口, 异常文件:ReaderException,用户捕获异常及错误处理. 实现文件如下: package com.microapp.application.reader; /** *

Title: 基于PC/SC标准的读写器实现

* *

Description:

* *

Copyright: Copyright (c) 2005

* *

Company: 我的软件公司

* * @author etd group * @version 1.0 */ import java.util.*; import opencard.core.*; import opencard.core.service.*; import opencard.core.terminal.*; import opencard.core.util.*; import opencard.opt.util.*; public class ReaderMA implements IReader { private static final int IFD_TIMEOUT = 5; // unit: seconds private static final int MAX_APDU_SIZE = 200; // unit: byte private static final int SW1_OK = (byte)0x90; private static final int SW2_OK = 0x00; private static final int RESPONSE_OK = 0x61; private static SmartCard sc = null; private static PassThruCardService ptcs = null; private static CardRequest cr = null; private static CommandAPDU capdu = null; private static ResponseAPDU rapdu = null; byte[] rbuf = null; public ReaderMA() { } /** * 复位 * @throws ReaderPCSCException */ public byte[] Reset() throws ReaderException { try { if (cr == null) { SmartCard.start(); cr = new CardRequest(CardRequest.ANYCARD, null, PassThruCardService.class); } cr.setTimeout(IFD_TIMEOUT); sc = SmartCard.waitForCard(cr); if(sc == null) { throw new ReaderPCSCException("did not get a SmartCard object!"); } CardID cardID = sc.getCardID(); byte[] atr = cardID.getATR(); capdu = new CommandAPDU(MAX_APDU_SIZE); ptcs = (PassThruCardService) sc.getCardService(PassThruCardService.class, true); return atr; } catch(CardTerminalException ex) { throw new ReaderException("Reset failed!" ex.getMessage()); } catch(CardServiceException ex) { throw new ReaderException("Reset failed!" ex.getMessage()); } catch(ClassNotFoundException ex) { throw new ReaderException("Reset failed!" ex.getMessage()); } catch(OpenCardPropertyLoadingException ex) { throw new ReaderException("Reset failed!" ex.getMessage()); } } /** * 下电 * @throws ReaderPCSCException */ public void ShutDown() throws ReaderException { try { if(sc.isStarted()) { sc.shutdown(); sc.close(); SmartCard.shutdown(); } sc = null; cr = null; } catch(CardTerminalException ex) { throw new ReaderException("Shutdown failed!" ex.getMessage()); } } /** * 读随机数 * @return byte[] */ public byte[] getChallenge() throws ReaderException { try { byte[] command = new byte[5]; command[0] = 0x00; // CLA command[1] = (byte)0x84; // INS command[2] = 0x00; // P1 command[3] = 0x00; // P2 command[4] = 0x08; // Lc capdu.setLength(0); capdu.append(command); ResponseAPDU response = ptcs.sendCommandAPDU(capdu); if(((response.sw1() == SW1_OK) && (response.sw2() == SW2_OK)) || (response.sw1() == RESPONSE_OK)) { return response.data(); } else { throw new ReaderPCSCException(response.sw1(), response.sw2()); } } catch(OpenCardException ex) { throw new ReaderPCSCException("Get challenge failed!" ex.getMessage()); } } /** * SelectTicketApplication * @return boolean */ public boolean SelectApplication() throws ReaderPCSCException { try { byte[] command = new byte[7]; command[0] = 0x00; // CLA command[1] = (byte)0xA4; // INS command[2] = 0x00; // P1 command[3] = 0x00; // P2 command[4] = 0x02; // Lc command[5] = 0x2F; command[6] = 0x01; capdu.setLength(0); capdu.append(command); ResponseAPDU response = ptcs.sendCommandAPDU(capdu); if(((response.sw1() == SW1_OK) && (response.sw2() == SW2_OK)) || (response.sw1() == RESPONSE_OK)) { return true; } return false; } catch(OpenCardException ex) { throw new ReaderPCSCException("Select Ticket Application failed!" ex.getMessage()); } } /** * 外部认证 * @param data String * @return boolean : true: pass, false: error. */ public boolean ExternalAuthentication(byte[] data) throws IndexOutOfBoundsException, NumberFormatException, ReaderPCSCException { try { byte[] command = new byte[13]; command[0] = 0x00; // CLA command[1] = (byte)0x82; // INS command[2] = 0x00; // P1 command[3] = 0x02; // P2 command[4] = 0x08; // Lc command[5] = data[0]; command[6] = data[1]; command[7] = data[2]; command[8] = data[3]; command[9] = data[4]; command[10] = data[5]; command[11] = data[6]; command[12] = data[7]; capdu.setLength(0); capdu.append(command); ResponseAPDU response = ptcs.sendCommandAPDU(capdu); if((response.sw1() != SW1_OK) || (response.sw2() != SW2_OK)) { throw new ReaderPCSCException(response.getByte(0), response.getByte(1)); } return true; } catch(OpenCardException ex) { throw new ReaderPCSCException("Get challenge failed!" ex.getMessage()); } catch(ReaderPCSCException ex) { throw new ReaderPCSCException(ex.getMessage()); } } /** * 内部认证 * @param data String * @return byte[] */ public byte[] IntenalAuthentication(byte[] data) throws IndexOutOfBoundsException, NumberFormatException, ReaderPCSCException { try { byte[] command = new byte[13]; command[0] = 0x00; // CLA command[1] = (byte)0x88; // INS command[2] = 0x00; // P1 command[3] = 0x01; // P2 command[4] = 0x08; // Lc command[5] = data[0]; command[6] = data[1]; command[7] = data[2]; command[8] = data[3]; command[9] = data[4]; command[10] = data[5]; command[11] = data[6]; command[12] = data[7]; capdu.setLength(0); capdu.append(command); ResponseAPDU response = ptcs.sendCommandAPDU(capdu); if(response.sw1() == 0x61) { command = new byte[5]; command[0] = 0x00; // CLA command[1] = (byte)0xC0; // INS command[2] = 0x00; // P1 command[3] = 0x00; // P2 command[4] = 0x08; // Lc capdu.setLength(0); capdu.append(command); response = ptcs.sendCommandAPDU(capdu); if((response.sw1() != SW1_OK) || (response.sw2() != SW2_OK)) { throw new ReaderPCSCException(response.sw1(), response.sw2()); } return response.data(); } else { throw new ReaderPCSCException(response.getByte(0), response.getByte(1)); } } catch(OpenCardException ex) { throw new ReaderPCSCException("Get challenge failed!" ex.getMessage()); } catch(ReaderPCSCException ex) { throw new ReaderPCSCException(ex.getMessage()); } } /** * 读基本信息文件 * @return byte[] * @throws ReaderPCSCException */ public byte[] ReadBasicFile() throws ReaderPCSCException { try { byte[] command = new byte[5]; command[0] = 0x00; // CLA command[1] = (byte)0xb0; // INS command[2] = (byte)0x95; // P1 command[3] = 0x00; // P2 command[4] = 0x27; // Lc capdu.setLength(0); capdu.append(command); ResponseAPDU response = ptcs.sendCommandAPDU(capdu); if((response.sw1() != SW1_OK) || (response.sw2() != SW2_OK)) { throw new ReaderPCSCException(response.getByte(39), response.getByte(40)); } return response.data(); } catch(OpenCardException ex) { throw new ReaderPCSCException("Read base file failed!" ex.getMessage()); } } /** * 读持卡人信息文件 * @return String * @throws ReaderPCSCException */ public byte[] ReadHolderFile() throws ReaderPCSCException { return null; } /** * 读基本信息文件 * @param record int * @return String * @throws ReaderPCSCException */ public byte[] ReadBasicInfo(int record) throws ReaderPCSCException { try { byte[] command = new byte[5]; command[0] = 0x00; command[1] = (byte)0xB2; command[2] = (byte)record; command[3] = (byte)0x84; command[4] = (byte)0x9C; capdu.setLength(0); capdu.append(command); ResponseAPDU response = ptcs.sendCommandAPDU(capdu); if((response.sw1() != SW1_OK) || (response.sw2() != SW2_OK)) { throw new ReaderPCSCException(response.sw1(), response.sw2()); } return response.data(); } catch(OpenCardException ex) { throw new ReaderPCSCException("Read ticket file error!" ex.getMessage()); } } /** * 写基本信息文件 * @param record * @param data String * @throws ReaderPCSCException */ public boolean WriteBasicInfo(int record, byte[] data) throws ReaderPCSCException { try { byte[] command = new byte[161]; command[0] = 0x00; command[1] = (byte)0xDC; command[2] = (byte)record; command[3] = (byte)0x84; command[4] = (byte)0x9C; System.arraycopy(data, 0, command, 5, 0x9C); capdu.setLength(0); capdu.append(command); ResponseAPDU response = ptcs.sendCommandAPDU(capdu); if((response.sw1() != SW1_OK) || (response.sw2() != SW2_OK)) { throw new ReaderPCSCException(response.sw1(), response.sw2()); } return true; } catch(OpenCardException ex) { throw new ReaderPCSCException("Get challenge failed!" ex.getMessage()); } catch(ReaderPCSCException ex) { throw new ReaderPCSCException(ex.getMessage()); } } 用opencard规范开发非常的简单,特别是处理返回数据,在responseAPDU内用sw1和sw22个方法用于返回sw1,sw2.数据是直接用response.data()即可.省缺了一般读写拼字节的过程. 在读写器之上我定义了一个基于应用的卡片类,AppCard,在这个类内实现卡片的具体操作. 如内部认证,外部认证,获取随机数等. public void reset() throws TicketException { try { byte[] batr = reader.Reset(); StringBuffer sb = new StringBuffer(); String s = new String(); for(int i = 0; i < batr.length; i ) { s = Integer.toHexString(batr[i]).toUpperCase(); if(s.length() == 1) { sb.append("0" s); } else if(s.length() > 2) { sb.append(s.substring(s.length() - 2, s.length())); } else { sb.append(s); } sb.append(" "); } atr = sb.toString(); } catch(ReaderPCSCException rex) { throw new TicketException("Reset failed! " rex.getMessage()); } } /** * ShutDown */ public void ShutDown() throws TicketException { try { reader.ShutDown(); } catch(ReaderException ex) { throw new TicketException("Shutdown failed!"); } } /** * 获取随机数 * @return String */ public String getChallenge() throws TicketException { try { StringBuffer sb = new StringBuffer(); String s = new String(); byte[] buf = reader.getChallenge(); for(int i = 0; i < buf.length; i ) { s = Integer.toHexString(buf[i]).toUpperCase(); if(s.length() == 1) { sb.append("0" s); } else if(s.length() > 2) { sb.append(s.substring(s.length() - 2, s.length())); } else { sb.append(s); } } return sb.toString(); } catch(ReaderPCSCException rex) { throw new TicketException(rex.getMessage()); } } /** * 内部认证 * @param data String * @return String */ public String IntenalAuthentication(String data) throws TicketException { try { byte[] sendbuf = new byte[8]; sendbuf[0] = (byte)(Integer.parseInt(data.substring(0,2), 16)); sendbuf[1] = (byte)(Integer.parseInt(data.substring(2,4), 16)); sendbuf[2] = (byte)(Integer.parseInt(data.substring(4,6), 16)); sendbuf[3] = (byte)(Integer.parseInt(data.substring(6,8), 16)); sendbuf[4] = (byte)(Integer.parseInt(data.substring(8,10), 16)); sendbuf[5] = (byte)(Integer.parseInt(data.substring(10,12), 16)); sendbuf[6] = (byte)(Integer.parseInt(data.substring(12,14), 16)); sendbuf[7] = (byte)(Integer.parseInt(data.substring(14,16), 16)); StringBuffer sb = new StringBuffer(); String s = new String(); byte[] recvbuf = reader.IntenalAuthentication(sendbuf); for(int i = 0; i < recvbuf.length; i ) { s = Integer.toHexString(recvbuf[i]).toUpperCase(); if(s.length() == 1) { sb.append("0" s); } else if(s.length() > 2) { sb.append(s.substring(s.length() - 2, s.length())); } else { sb.append(s); } } return sb.toString(); } catch(ReaderPCSCException rex) { throw new TicketException(rex.getMessage()); } catch(NumberFormatException ex) { throw new TicketException(ex.getMessage()); } catch(IndexOutOfBoundsException ex) { throw new TicketException(ex.getMessage()); } } /** * 外部认证 * * @param data String */ public boolean ExternalAuthentication(String data) throws TicketException { try { byte[] buf = new byte[8]; buf[0] = (byte)(Integer.parseInt(data.substring(0,2), 16)); buf[1] = (byte)(Integer.parseInt(data.substring(2,4), 16)); buf[2] = (byte)(Integer.parseInt(data.substring(4,6), 16)); buf[3] = (byte)(Integer.parseInt(data.substring(6,8), 16)); buf[4] = (byte)(Integer.parseInt(data.substring(8,10), 16)); buf[5] = (byte)(Integer.parseInt(data.substring(10,12), 16)); buf[6] = (byte)(Integer.parseInt(data.substring(12,14), 16)); buf[7] = (byte)(Integer.parseInt(data.substring(14,16), 16)); return reader.ExternalAuthentication(buf); } catch(ReaderPCSCException rex) { throw new TicketException(rex.getMessage()); } catch(NumberFormatException ex) { throw new TicketException(ex.getMessage()); } catch(IndexOutOfBoundsException ex) { throw new TicketException(ex.getMessage()); } } 利用该方法,在客户端实现了用户卡的读写,大大简化了开发,并运行稳定,性能完全预期要求. 下载本文示例代码


IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写IC卡应用系统开发-(一)卡片读写
阅读(233) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~