How to programmatically load a Java card applet ( .cap file ) using java or java Applet.
I'm trying to install an applet (.cap file) into a smart card. I read that can be done using APDU. I created my applet using Netbeans.
I have already created a .CAP file using Netbeans for my applet which I would now like to install/load into the physical smart card. I would appreciate assistance on how or what tool I could use to install the .CAP file to the card. Also, what else do I need to install into the card. And I have two devices HID OMNIKEY CARDMAN 5x21 1 and HID OMNIKEY CARDMAN 3x21 0 java smart card reader and also I have two kinds of cards like java card (J2A.. or J3A..) and basics cards(ZC..) Note: I don't want to use any third party software or tools And my applet code is: package smartCard; import javacard.framework.*;
/** * * @author patidar */ public class SmartCard extends Applet {
/**
* Installs this applet.
*
* @param bArray
* the array containing installation parameters
* @param bOffset
* the starting offset in bArray
* @param bLength
* the length in bytes of the parameter data in bArray
*/
/**
* Only this class's install method should create the applet object.
*/
protected SmartCard() {
register();
}
/**
* Processes an incoming APDU.
*
* @see APDU
* @param apdu
* the incoming APDU
*/
/* constants declaration */
// code of CLA byte in the command APDU header
final static byte Wallet_CLA =(byte)0x80;
// codes of INS byte in the command APDU header
final static byte VERIFY = (byte) 0x20;
final static byte CREDIT = (byte) 0x30;
final static byte DEBIT = (byte) 0x40;
final static byte GET_BALANCE = (byte) 0x50;
// maximum balance
final static short MAX_BALANCE = 0x7FFF;
// maximum transaction amount
final static byte MAX_TRANSACTION_AMOUNT = 127;
// maximum number of incorrect tries before the
// PIN is blocked
final static byte PIN_TRY_LIMIT =(byte)0x03;
// maximum size PIN
final static byte MAX_PIN_SIZE =(byte)0x08;
// signal that the PIN verification failed
final static short SW_VERIFICATION_FAILED =
0x6300;
// signal the the PIN validation is required
// for a credit or a debit transaction
final static short SW_PIN_VERIFICATION_REQUIRED =
0x6301;
// signal invalid transaction amount
// amount > MAX_TRANSACTION_AMOUNT or amount < 0
final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83;
// signal that the balance exceed the maximum
final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;
// signal the the balance becomes negative
final static short SW_NEGATIVE_BALANCE = 0x6A85;
/* instance variables declaration */
OwnerPIN pin;
short balance;
private SmartCard (byte[] bArray,short bOffset,byte bLength)
// It is good programming practice to allocate
// all the memory that an applet needs during
// its lifetime inside the constructor
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
byte iLen = bArray[bOffset]; // aid length
bOffset = (short) (bOffset+iLen+1);
byte cLen = bArray[bOffset]; // info length
bOffset = (short) (bOffset+cLen+1);
byte aLen = bArray[bOffset]; // applet data length
// The installation parameters contain the PIN
// initialization value
pin.update(bArray, (short)(bOffset+1), aLen);
register();
} // end of the constructor
public static void install(byte[] bArray, short bOffset, byte bLength) {
// create a Wallet applet instance
new SmartCard(bArray, bOffset, bLength);
} // end of install method
public boolean select() {
// The applet declines to be selected
// if the pin is blocked.
if ( pin.getTriesRemaining() == 0 )
return false;
return true;
}// end of select method
public void deselect() {
// reset the pin value
pin.reset();
}
public void process(APDU apdu) {
// APDU object carries a byte array (buffer) to
// transfer incoming and outgoing APDU header
// and data bytes between card and CAD
// At this point, only the first header bytes
// [CLA, INS, P1, P2, P3] are available in
// the APDU buffer.
// The interface javacard.framework.ISO7816
// declares constants to denote the offset of
// these bytes in the APDU buffer
byte[] buffer = apdu.getBuffer();
// check SELECT APDU command
if (apdu.isISOInterindustryCLA()) {
if (buffer[ISO7816.OFFSET_INS] == (byte)(0xA4)) {
return;
} else {
ISOException.throwIt (ISO7816.SW_CLA_NOT_SUPPORTED);
}
}
// verify the reset of commands have the
// correct CLA byte, which specifies the
// command structure
if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA)
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
switch (buffer[ISO7816.OFFSET_INS]) {
case GET_BALANCE:
getBalance(apdu);
return;
case DEBIT:
debit(apdu);
return;
case CREDIT:
credit(apdu);
return;
case VERIFY:
verify(apdu);
return;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
} // end of process method
private void credit(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
// Lc byte denotes the number of bytes in the
// data field of the command APDU
byte numBytes = buffer[ISO7816.OFFSET_LC];
// indicate that this APDU has incoming data
// and receive data starting from the offset
// ISO7816.OFFSET_CDATA following the 5 header
// bytes.
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
// it is an error if the number of data bytes
// read does not match the number in Lc byte
if ( ( numBytes != 1 ) || (byteRead != 1) )
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// get the credit amount
byte creditAmount = buffer[ISO7816.OFFSET_CDATA];
// check the credit amount
if ( ( creditAmount > MAX_TRANSACTION_AMOUNT)
|| ( creditAmount < 0 ) )
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
// check the new balance
if ( (short)( balance + creditAmount) > MAX_BALANCE )
ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
// credit the amount
balance = (short)(balance + creditAmount);
} // end of deposit method
private void debit(APDU apdu) {
// access authentication
if ( ! pin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
byte numBytes =
(byte)(buffer[ISO7816.OFFSET_LC]);
byte byteRead =
(byte)(apdu.setIncomingAndReceive());
if ( ( numBytes != 1 ) || (byteRead != 1) )
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
// get debit amount
byte debitAmount = buffer[ISO7816.OFFSET_CDATA];
// check debit amount
if ( ( debitAmount > MAX_TRANSACTION_AMOUNT)
|| ( debitAmount < 0 ) )
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
// check the new balance
if ( (short)( balance - debitAmount ) < (short)0 )
ISOException.throwIt(SW_NEGATIVE_BALANCE);
balance = (short) (balance - debitAmount);
} // end of debit method
private void getBalance(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// inform system that the applet has finished
// processing the command and the system should
// now prepare to construct a response APDU
// which contains data field
short le = apdu.setOutgoing();
if ( le < 2 )
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
//informs the CAD the actual number of bytes
//returned
apdu.setOutgoingLength((byte)2);
// move the balance data into the APDU buffer
// starting at the offset 0
buffer[0] = (byte)(balance >> 8);
buffer[1] = (byte)(balance & 0xFF);
// send the 2-byte balance at the offset
// 0 in the apdu buffer
apdu.sendBytes((short)0, (short)2);
} // end of getBalance method
private void verify(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// retrieve the PIN data for validation.
byte byteRead = (byte)(apdu.setIncomingAndReceive());
// check pin
// the PIN data is read into the APDU buffer
// at the offset ISO7816.OFFSET_CDATA
// the PIN data length = byteRead
if ( pin.check(buffer, ISO7816.OFFSET_CDATA,
byteRead) == false )
ISOException.throwIt(SW_VERIFICATION_FAILED);
} // end of validate method
} // end of class SmartCard
With this information can anyone help me to build the correct APDU to install my cap file into a real smart card? Thank you.
I also stuck with the same issue and I found the solution which I am going to share with you.
Please follow the below steps:
1: Please click here and download the gp.exe
2: Open your windows command prompt.
3: Go to the location/directory
which contains the gp.exe
file.
4: Now connect your card reader into machine and insert card into reader.
5: Than type the
cmd > gp.exe
cmd > gp –help
And if everything is fine than you will see the all supported commands listed there:
a cmd > gp –info
This will list all the card information.
b cmd > gp –list
This will list all the applets installed in the cards.
c: cmd > gp –delete AID(of applet )
This will delete the installed applet.
d: cmd > gp –install xyz.cap
(copy the .cap
file in same directory where gp.exe
is placed and select in place of xyz.cap
) This will install your applet onto the physical smart card.
Now you need the APDU commands to communicate with the card.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.