SigMsgRecAppletpublic class SigMsgRecApplet extends Applet package AID 0xA0:0x00:0x00:0x00:0x62:0x03:0x01:0x0C:0x0C |
Fields Summary |
---|
public static final byte | CLA | public static final byte | INS_SIGN | public static final byte | INS_VERIFY_FULL_MSG_REC | public static final byte | INS_VERIFY_PART_MSG_REC | public static final short | ERROR_BAD_SIG_LEN | public static final short | ERROR_VERIFICATION_FAILED | public static final short | SIG_LENGTH | private static final byte[] | RSA_PUB_KEY_EXP | private static final byte[] | RSA_PUB_PRIV_KEY_MOD | private static final byte[] | RSA_PRIV_KEY_EXP | javacard.security.RSAPublicKey | pubKey | javacard.security.RSAPrivateKey | privKey | javacard.security.SignatureMessageRecovery | sig | byte[] | sigBuffthe sigBuff buffer would hold the signature output of the Signature
class and an extra 2 bytes for the length of recoverable message
sent back to the caller | short | sigLen | byte | recStatethe following state variable has the following value:
0 => recovery has not yet started
1 => signature recovered. Waiting for rest of message |
Constructors Summary |
---|
protected SigMsgRecApplet(byte[] bArray, short bOffset, byte bLength)Only this class's install method should create the applet object.
byte aidLen = bArray[bOffset];
if (aidLen== (byte)0){
//System.out.println("using dfault");
register();
} else {
//System.out.println("using provided");
register(bArray, (short)(bOffset+1), aidLen);
}
pubKey = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC,KeyBuilder.LENGTH_RSA_512,false);
privKey = (RSAPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE,KeyBuilder.LENGTH_RSA_512,false);
privKey.setExponent(RSA_PRIV_KEY_EXP,(short)0,(short)RSA_PRIV_KEY_EXP.length);
privKey.setModulus(RSA_PUB_PRIV_KEY_MOD,(short)0,(short)RSA_PUB_PRIV_KEY_MOD.length);
pubKey.setExponent(RSA_PUB_KEY_EXP,(short)0,(short)RSA_PUB_KEY_EXP.length);
pubKey.setModulus(RSA_PUB_PRIV_KEY_MOD,(short)0,(short)RSA_PUB_PRIV_KEY_MOD.length);
sigBuff = JCSystem.makeTransientByteArray((short)(SIG_LENGTH+2),JCSystem.CLEAR_ON_DESELECT);
sig = (SignatureMessageRecovery)Signature.getInstance(Signature.ALG_RSA_SHA_ISO9796_MR,false);
recState = (byte)0;
|
Methods Summary |
---|
public static void | install(byte[] bArray, short bOffset, byte bLength)Installs this applet.
new SigMsgRecApplet(bArray,bOffset,bLength);
| public void | process(APDU apdu)Processes an incoming APDU.
byte buffer[] = apdu.getBuffer();
// check SELECT APDU command
if ((buffer[ISO7816.OFFSET_CLA] == 0) &&
(buffer[ISO7816.OFFSET_INS] == (byte)(0xA4))){
return;
}
switch (buffer[ISO7816.OFFSET_INS]){
case INS_SIGN:
testCryptoSign(apdu);
break;
case INS_VERIFY_FULL_MSG_REC:
testCryptoVerifyFullMsgRecovery(apdu);
break;
case INS_VERIFY_PART_MSG_REC:
testCryptoVerifyPartMsgRecovery(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
| private void | testCryptoSign(APDU apdu)For the purposes of this sample, Assumed that all the data to be
signed fits into one APDU buffer
byte []buffer = apdu.getBuffer();
short bytesRead = apdu.setIncomingAndReceive();
short []m1Data = JCSystem.makeTransientShortArray((short)1,JCSystem.CLEAR_ON_DESELECT);
sig.init(privKey,Signature.MODE_SIGN);
sigLen=sig.sign(buffer,ISO7816.OFFSET_CDATA,bytesRead,sigBuff,(short)0,m1Data,(short)0);
//set m1Length into sigBuff array
sigBuff[sigLen] = (byte)((short)(m1Data[(short)0] & ((short)0xFF00)) >> ((short)8));
sigBuff[(short)(sigLen+1)] = (byte)(m1Data[(short)0] & ((short)0x00FF));
apdu.setOutgoing();
apdu.setOutgoingLength((short)(sigLen+2));//The extra 2 bytes for m1Length
apdu.sendBytesLong(sigBuff,(short)0,(short)(sigLen+2));
| private void | testCryptoVerifyFullMsgRecovery(APDU apdu)in this case, all the message is inside the signature.
We only expect one APDU with signature
sig.init(pubKey,Signature.MODE_VERIFY);
boolean verified=false;
byte []buffer = apdu.getBuffer();
short dataLength = (short)(buffer[ISO7816.OFFSET_LC] & (short)0xFF);
//get the signature from APDU
short bytesRead = apdu.setIncomingAndReceive();
Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, sigBuff, (short)0,bytesRead);
short m1Length = sig.beginVerify(sigBuff,(short)0,bytesRead);
verified = sig.verify(sigBuff,(short)0,(short)0);
//In either case m1 is consumed by this applet
if(!verified){
ISOException.throwIt(ERROR_VERIFICATION_FAILED);
}
| private void | testCryptoVerifyPartMsgRecovery(APDU apdu)This method is called when there is partial message recovery. The recoverable
message inside the signature is consumed by this applet. In this case, the
first APDU contains the signature and returns true if recovery successful
the second APDU contains the remainder of the message and the return value
represents signature verification
byte []buffer = apdu.getBuffer();
short dataLength = (short)(buffer[ISO7816.OFFSET_LC] & (short)0xFF);
//get the signature from APDU
short bytesRead = apdu.setIncomingAndReceive();
Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, sigBuff, (short)0,bytesRead);
if(recState == 0){
//recover the recoverable message from signature
sig.init(pubKey,Signature.MODE_VERIFY);
short m1Length = sig.beginVerify(sigBuff,(short)0,bytesRead);
//consume the recoverable message. Theen discard it
sigBuff[0] = (byte)((short)(m1Length & ((short)0xFF00)) >> ((short)8));
sigBuff[1] = (byte)(m1Length & ((short)0x00FF));
//return back the length of recoverable message
apdu.setOutgoing();
apdu.setOutgoingLength((short)2);
apdu.sendBytesLong(sigBuff,(short)0,(short)2);
recState = 1;
}else{
recState = 0;
//rest of message sent. verify
if(!sig.verify(sigBuff,(short)0,bytesRead)){
ISOException.throwIt(ERROR_VERIFICATION_FAILED);
}
}
|
|