FileDocCategorySizeDatePackage
SigMsgRecApplet.javaAPI DocJava Card9550Wed Mar 22 21:07:24 GMT 2006None

SigMsgRecApplet

public 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[]
sigBuff
the 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
recState
the 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 voidinstall(byte[] bArray, short bOffset, byte bLength)
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

        new SigMsgRecApplet(bArray,bOffset,bLength);
    
public voidprocess(APDU apdu)
Processes an incoming APDU.

see
APDU
param
apdu the incoming APDU
exception
ISOException with the response bytes per ISO 7816-4

        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 voidtestCryptoSign(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 voidtestCryptoVerifyFullMsgRecovery(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 voidtestCryptoVerifyPartMsgRecovery(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);
            }
        }