Announce two new product: SmartCard Reader Rockey200 and USB2.0 Extension Cable

ROCKEY 200 is a handy and portable USB Smart Card reader that can perform read/write operations on any ISO 7816-1/2/3/4 smart cards which are compatible with protocol T=0 and T=1.

USB2.0 Extension Cable With high speed USB 2.0 devices such as USB token ,USB Card Reader and so on.

Come to try it now!

The ALgorithm of RSA Sample Code

Applets Development Guide

Moderator: product

User avatar
JavaCardOS
Posts: 257
Joined: Thu Apr 30, 2015 12:00 pm
Points: 2253
Contact:

The ALgorithm of RSA Sample Code

Postby JavaCardOS » Sat Jul 09, 2016 6:01 am

The following code is the ALgorithm of RSA Sample Code in JavaCard API Specification.

You can copy and use it directly or you can download the JCIDE project from the attachment and build it.


Code: Select all


/*
 * @file  RSASample.java
 * @version v1.0
 * Package AID: 4A617661436172644F53
 * Applet AID:  4A617661436172644F5303
 * @brief The ALgorithm of RSA Sample Code in JavaCard API Specification
 * @comment The purpose of this example is only used to show the usage of API functions and there is no practical significance.
 * @copyright Copyright(C) 2016 JavaCardOS Technologies Co., Ltd. All rights reserved.
 */
 
package JavaCardOS.Sample.Algorithm;

import javacard.framework.*;
import javacard.security.KeyBuilder;
import javacard.security.*;
import javacardx.crypto.*;

public class RSASample extends Applet
{
   private static final byte INS_GEN_RSA_KEYPAIR          = (byte)0x30;
    private static final byte INS_GET_RSA_PUBKEY           = (byte)0x31;
    private static final byte INS_GET_RSA_PRIKEY           = (byte)0x32;
    private static final byte INS_SET_RSA_PUBKEY           = (byte)0x33;
    private static final byte INS_SET_RSA_PRIKEY           = (byte)0x34;
    private static final byte INS_RSA_SIGN                 = (byte)0x35;
    private static final byte INS_RSA_VERIFY               = (byte)0x36;
    private static final byte INS_DO_RSA_CIPHER            = (byte)0x37;

   private byte[] tempBuffer;

    private byte[] flags;
    private static final short OFF_INS    = (short)0;
    private static final short OFF_P1     = (short)1;
    private static final short OFF_P2     = (short)2;
    private static final short OFF_LEN    = (short)3;
    private static final short FLAGS_SIZE = (short)5;

   private static final byte ID_N   = 0;
    private static final byte ID_D   = 1;
    private static final byte ID_P   = 2;
    private static final byte ID_Q   = 3;
    private static final byte ID_PQ  = 4;
    private static final byte ID_DP1 = 5;
    private static final byte ID_DQ1 = 6;
   
   private byte[] rsaPubKey;
    private short rsaPubKeyLen;
    private byte[] rsaPriKey;
    private short rsaPriKeyLen;
    private boolean isRSAPriKeyCRT;
    private Cipher rsaCipher;   
    private Signature rsaSignature;
   
   private static final short SW_REFERENCE_DATA_NOT_FOUND = (short)0x6A88;
   
   public RSASample()
    {
       //Create a transient byte array to store the temporary data
        tempBuffer = JCSystem.makeTransientByteArray((short)256, JCSystem.CLEAR_ON_DESELECT);
        flags = JCSystem.makeTransientByteArray(FLAGS_SIZE, JCSystem.CLEAR_ON_DESELECT);

        rsaPubKey = new byte[(short)   (256 + 32)];
        rsaPriKey = new byte[(short)(128 * 5)];
        rsaPubKeyLen = 0;
        rsaPriKeyLen = 0;
        isRSAPriKeyCRT = false;
        rsaSignature = null;
        //Create a RSA(not pad) object instance
        rsaCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);

        JCSystem.requestObjectDeletion();
    }
   
   public static void install(byte[] bArray, short bOffset, byte bLength)
   {
      new RSASample().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
   }

   public void process(APDU apdu)
   {
      if (selectingApplet())
      {
         return;
      }

      byte[] buf = apdu.getBuffer();
      short len = apdu.setIncomingAndReceive();
      switch (buf[ISO7816.OFFSET_INS])
      {
      case INS_GEN_RSA_KEYPAIR:
           //GEN_RSA_KEYPAIR
           genRsaKeyPair(apdu, len);
            break;
        case INS_GET_RSA_PUBKEY:
           //GET_RSA_PUBKEY
            getRsaPubKey(apdu, len);
            break;
        case INS_GET_RSA_PRIKEY:
           //GET_RSA_PRIKEY
           getRsaPriKey(apdu, len);
            break;
        case INS_SET_RSA_PUBKEY:
           // SET_RSA_PUBKEY
            setRsaPubKey(apdu, len);
            break;
        case INS_SET_RSA_PRIKEY:
           //SET_RSA_PRIKEY
            setRsaPriKey(apdu, len);
            break;
        case INS_RSA_SIGN:
           //RSA_SIGN
            rsaSign(apdu, len);
            break;
        case INS_RSA_VERIFY:
           //RSA_VERIFY
            rsaVerify(apdu, len);
            break;
        case INS_DO_RSA_CIPHER:   
           //RSA_CIPHER
           doRSACipher(apdu, len);
           break;
      default:
         ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
      }
   }
   
   //RSA algorithm encrypt and decrypt
   private void doRSACipher(APDU apdu, short len)
    {
       byte[] buffer = apdu.getBuffer();
        byte p1Tmp = buffer[ISO7816.OFFSET_P1];
        boolean hasMoreCmd = (p1Tmp & 0x80) != 0;
        boolean isEncrypt = (p1Tmp & 0x01) != 1;
       short keyLen = (p1Tmp & 0x08) == (byte)0x00 ? KeyBuilder.LENGTH_RSA_1024 : KeyBuilder.LENGTH_RSA_2048;
       short offset = (p1Tmp & 0x08) == (byte)0x00 ? (short)128 : (short)256;
       
        if (len <= 0)
        {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        //RSA encrypt, Public Key will be used
        if (isEncrypt)
      {
         //Create uninitialized public key for signature and cipher algorithms.
         RSAPublicKey pubKey = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, keyLen, false);
         pubKey.setModulus(rsaPubKey, (short)0, offset);
         pubKey.setExponent(rsaPubKey, offset, (short)3);
         if (buffer[ISO7816.OFFSET_P2] == 0x00)
         {
            //In multiple-part encryption/decryption operations, only the fist APDU command will be used.
            rsaCipher.init(pubKey, Cipher.MODE_ENCRYPT);
         }
         
         if (hasMoreCmd)
         {
            //This method is intended for multiple-part encryption/decryption operations.
            rsaCipher.update(buffer, ISO7816.OFFSET_CDATA, len, tempBuffer, (short)0);
         }
         else
         {
            //Generates encrypted output from all input data.
            short outlen = rsaCipher.doFinal(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0);
            apdu.setOutgoingAndSend((short)0, outlen);   
         }
      }
      else//RSA decrypt, Private Key will be used
      {
         if (!isRSAPriKeyCRT)
            {
               //RSA Alogrithm, create uninitialized private key for decypt
               RSAPrivateKey priKey = (RSAPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, keyLen, false);
               //Set the modulus value of the key.
            priKey.setModulus(rsaPriKey, (short)0, offset);
            //Sets the private exponent value of the key
            priKey.setExponent(rsaPriKey, offset, offset);
            if (buffer[ISO7816.OFFSET_P2] == 0x00)
            {
               //In multiple-part encryption/decryption operations, only the fist APDU command will be used.
               rsaCipher.init(priKey, Cipher.MODE_DECRYPT);
            }
            if (hasMoreCmd)
            {
               //This method is intended for multiple-part encryption/decryption operations.
               rsaCipher.update(buffer, ISO7816.OFFSET_CDATA, len, tempBuffer, (short)0);
            }
            else
            {
               short outlen = rsaCipher.doFinal(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0);
               apdu.setOutgoingAndSend((short)0, outlen);   
            }
            }
            else
            {
               //RSA CRT Algorithm, need to create uninitialized private key and set the value of some parameters, such as P Q PQ DP DQ.执行解密运算前,设置私钥
               RSAPrivateCrtKey priCrtKey = (RSAPrivateCrtKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_CRT_PRIVATE, keyLen, false);
                priCrtKey.setP(rsaPriKey, (short)0, (short)(offset / 2));
                priCrtKey.setQ(rsaPriKey, (short)(offset / 2), (short)(offset / 2));
                priCrtKey.setPQ(rsaPriKey, (short)offset, (short)(offset / 2));
                priCrtKey.setDP1(rsaPriKey, (short)(offset + offset / 2), (short)(offset / 2));
                priCrtKey.setDQ1(rsaPriKey, (short)(offset * 2), (short)(offset / 2));
               
                if (buffer[ISO7816.OFFSET_P2] == 0x00)
            {
               //Initializes the Cipher object with the appropriate Key.
               //In multiple-part encryption/decryption operations, only the fist APDU command will be used.
               rsaCipher.init(priCrtKey, Cipher.MODE_DECRYPT);
            }
            if (hasMoreCmd)
            {
               //This method is intended for multiple-part encryption/decryption operations.
               rsaCipher.update(buffer, ISO7816.OFFSET_CDATA, len, tempBuffer, (short)0);
            }
            else
            {
               //Generates decrypted output from all input data.
               short outlen = rsaCipher.doFinal(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0);
               apdu.setOutgoingAndSend((short)0, outlen);   
            }
            }
      }       
    }
   
    //Get the value of RSA Public Key from the global variable 'rsaPubKey'
    private void getRsaPubKey(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        if (rsaPubKeyLen == 0)
        {
            ISOException.throwIt(SW_REFERENCE_DATA_NOT_FOUND);
        }

        short modLen = rsaPubKeyLen <= (128 + 32) ? (short)128 : (short)256;
        switch (buffer[ISO7816.OFFSET_P1])
        {
        case 0:
            Util.arrayCopyNonAtomic(rsaPubKey,(short)0,buffer,(short)0,modLen);
            apdu.setOutgoingAndSend((short)0,modLen);
            break;
        case 1:
            //get public key E
            short eLen = (short)(rsaPubKeyLen - modLen);
            Util.arrayCopyNonAtomic(rsaPubKey,modLen,buffer,(short)0,eLen);
            apdu.setOutgoingAndSend((short)0,eLen);
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            break;
        }

    }
   //According to the different ID, returns the value/length of RSA Private component
    private short getRsaPriKeyComponent(byte id, byte[] outBuff, short outOff)
    {
        if (rsaPriKeyLen == 0)
        {
            return (short)0;
        }
        short modLen;
        if (isRSAPriKeyCRT)
        {
            if (rsaPriKeyLen == 64 * 5)
            {
                modLen = (short)128;
            }
            else
            {
                modLen = (short)256;
            }
        }
        else
        {
            if (rsaPriKeyLen == 128 * 2)
            {
                modLen = (short)128;
            }
            else
            {
                modLen = (short)256;
            }
        }
        short readOff;
        short readLen;

        switch (id)
        {
        case ID_N:
            //RSA private key N
            if (isRSAPriKeyCRT)
            {
                return (short)0;
            }
            readOff = (short)0;
            readLen = modLen;
            break;
        case ID_D:
            if (isRSAPriKeyCRT)
            {
                return (short)0;
            }
            //RSA private key D
            readOff = modLen;
            readLen = modLen;
            break;
        case ID_P:
            if (!isRSAPriKeyCRT)
            {
                return (short)0;
            }
            readOff = (short)0;
            readLen = (short)(modLen / 2);
            break;
        case ID_Q:
            if (!isRSAPriKeyCRT)
            {
                return (short)0;
            }
            readOff = (short)(modLen / 2);
            readLen = (short)(modLen / 2);
            break;
        case ID_PQ:
            if (!isRSAPriKeyCRT)
            {
                return (short)0;
            }
            readOff = (short)(modLen);
            readLen = (short)(modLen / 2);
            break;
        case ID_DP1:
            if (!isRSAPriKeyCRT)
            {
                return (short)0;
            }
            readOff = (short)(modLen / 2 * 3);
            readLen = (short)(modLen / 2);
            break;
        case ID_DQ1:
            if (!isRSAPriKeyCRT)
            {
                return (short)0;
            }
            readOff = (short)(modLen * 2);
            readLen = (short)(modLen / 2);
            break;
        default:
            return 0;
        }
        Util.arrayCopyNonAtomic(rsaPriKey, readOff, outBuff, outOff, readLen);
        return readLen;
    }

   //Get the value of RSA Private Key
    private void getRsaPriKey(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        if ((buffer[ISO7816.OFFSET_P1] & 0xff) > 6)
        {
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }
        short ret = getRsaPriKeyComponent(buffer[ISO7816.OFFSET_P1], buffer, (short)0);
        if (ret == 0)
        {
            ISOException.throwIt(SW_REFERENCE_DATA_NOT_FOUND);
        }
        apdu.setOutgoingAndSend((short)0, ret);
    }

   //Set the value of RSA public key
    private void setRsaPubKey(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        if (buffer[ISO7816.OFFSET_P2] == 0) // first block
        {
            rsaPubKeyLen = (short)0;
            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_INS, flags, OFF_INS, (short)3);
            Util.setShort(flags, OFF_LEN, (short)0);
        }
        else
        {
            if (flags[OFF_INS] != buffer[ISO7816.OFFSET_INS]
                    || (flags[OFF_P1] & 0x7f) != (buffer[ISO7816.OFFSET_P1] & 0x7f)
                    || (short)(flags[OFF_P2] & 0xff) != (short)((buffer[ISO7816.OFFSET_P2] & 0xff) - 1))
            {
                Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            }

            flags[OFF_P2] ++;
        }
        short loadedLen = Util.getShort(flags, OFF_LEN);
        if (loadedLen + len > rsaPubKey.length)
        {
            Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
      //Copy the value of RSA public key  to the global variable 'rsaPubKey'.
        Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, rsaPubKey, loadedLen, len);
        loadedLen += len;

        if ((buffer[ISO7816.OFFSET_P1] & 0x80) == 0) //last block
        {
            Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
            short modLen = (buffer[ISO7816.OFFSET_P1] & 0x01) == 0 ? (short)128 : (short)256;
            if (loadedLen < modLen + 3 || loadedLen > modLen + 32)
            {
                ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }

            rsaPubKeyLen = loadedLen;
        }
        else
        {
            Util.setShort(flags, OFF_LEN, loadedLen);
        }

    }

   //Set the value of RSA private key
    private void setRsaPriKey(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        if (buffer[ISO7816.OFFSET_P2] == 0) // first block
        {
            rsaPriKeyLen = (short)0;
            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_INS, flags, OFF_INS, (short)3);
            Util.setShort(flags, OFF_LEN, (short)0);
        }
        else
        {
            if (flags[OFF_INS] != buffer[ISO7816.OFFSET_INS]
                    || (flags[OFF_P1] & 0x7f) != (buffer[ISO7816.OFFSET_P1] & 0x7f)
                    || (short)(flags[OFF_P2] & 0xff) != (short)((buffer[ISO7816.OFFSET_P2] & 0xff) - 1))
            {
                Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            }

            flags[OFF_P2] ++;
        }
        short loadedLen = Util.getShort(flags, OFF_LEN);
        if (loadedLen + len > rsaPriKey.length)
        {
            Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
            ISOException.throwIt(ISO7816.SW_WRONG_DATA);
        }
      //Copy the value of RSA private key  to the global variable 'rsaPriKey'.
      Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, rsaPriKey, loadedLen, len);
        loadedLen += len;

        if ((buffer[ISO7816.OFFSET_P1] & 0x80) == 0) //last block
        {
            Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
            short modLen = (buffer[ISO7816.OFFSET_P1] & 0x01) == 0 ? (short)128 : (short)256;
            boolean isCRT = (buffer[ISO7816.OFFSET_P1] & 0x40) != 0;
            if ((isCRT && (loadedLen != modLen / 2 * 5)) || (!isCRT && (loadedLen != modLen * 2)))
            {
                ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }

            isRSAPriKeyCRT = isCRT;
            rsaPriKeyLen = loadedLen;
        }
        else
        {
            Util.setShort(flags, OFF_LEN, loadedLen);
        }
    }
    //
   private void genRsaKeyPair(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        short keyLen = buffer[ISO7816.OFFSET_P1] == 0 ? (short)1024 : (short)2048;
        byte alg = buffer[ISO7816.OFFSET_P2] == 0 ? KeyPair.ALG_RSA : KeyPair.ALG_RSA_CRT;
        KeyPair keyPair = new KeyPair(alg, keyLen);
        if (len > 32)
        {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        if (len > 0)
        {
            ((RSAPublicKey)keyPair.getPublic()).setExponent(buffer, ISO7816.OFFSET_CDATA, len);
        }
        //(Re)Initializes the key objects encapsulated in this KeyPair instance with new key values.
        keyPair.genKeyPair();
        JCSystem.beginTransaction();
        rsaPubKeyLen = 0;
        rsaPriKeyLen = 0;
        JCSystem.commitTransaction();
        //Get a reference to the public key component of this 'keyPair' object.
        RSAPublicKey pubKey = (RSAPublicKey)keyPair.getPublic();
        short pubKeyLen = 0;
        //Store the RSA public key value in the global variable 'rsaPubKey', the public key contains modulo N and Exponent E
        pubKeyLen += pubKey.getModulus(rsaPubKey, pubKeyLen);
        pubKeyLen += pubKey.getExponent(rsaPubKey, pubKeyLen);

        short priKeyLen = 0;
        if (alg == KeyPair.ALG_RSA)
        {
           isRSAPriKeyCRT = false;
           //Returns a reference to the private key component of this KeyPair object.
            RSAPrivateKey priKey = (RSAPrivateKey)keyPair.getPrivate();
            //RSA Algorithm,  the Private Key contains N and D, and store these parameters value in global variable 'rsaPriKey'.
            priKeyLen += priKey.getModulus(rsaPriKey, priKeyLen);
            priKeyLen += priKey.getExponent(rsaPriKey, priKeyLen);
        }
        else //RSA CRT
        {
           isRSAPriKeyCRT =  true;
           //The RSAPrivateCrtKey interface is used to sign data using the RSA algorithm in its Chinese Remainder Theorem form.
            RSAPrivateCrtKey priKey = (RSAPrivateCrtKey)keyPair.getPrivate();
            //RSA CRT Algorithm,  the Private Key contains P Q PQ DP and DQ, and store these parameters value in global variable 'rsaPriKey'.
            priKeyLen += priKey.getP(rsaPriKey, priKeyLen);
            priKeyLen += priKey.getQ(rsaPriKey, priKeyLen);
            priKeyLen += priKey.getPQ(rsaPriKey, priKeyLen);
            priKeyLen += priKey.getDP1(rsaPriKey, priKeyLen);
            priKeyLen += priKey.getDQ1(rsaPriKey, priKeyLen);
        }

        JCSystem.beginTransaction();
        rsaPubKeyLen = pubKeyLen;
        rsaPriKeyLen = priKeyLen;
        JCSystem.commitTransaction();

        JCSystem.requestObjectDeletion();
    }
   //RSA Signature
    private void rsaSign(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        if (rsaPriKeyLen == 0)
        {
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
        }
        boolean hasMoreCmd = (buffer[ISO7816.OFFSET_P1] & 0x80) != 0;
        short resultLen = 0;
        if (buffer[ISO7816.OFFSET_P2] == 0) //first block
        {
            Key key;
            if (!isRSAPriKeyCRT)
            {
                short ret;
                //Creates uninitialized private keys for signature algorithms.
                key = KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, (short)(rsaPriKeyLen / 2 * 8), false);
                ret = getRsaPriKeyComponent(ID_N, tempBuffer, (short)0);
                ((RSAPrivateKey)key).setModulus(tempBuffer, (short)0, ret);
                ret = getRsaPriKeyComponent(ID_D, tempBuffer, (short)0);
                ((RSAPrivateKey)key).setExponent(tempBuffer, (short)0, ret);
            }
            else
            {
                short ret;
                //Creates uninitialized private keys for signature algorithms.
                key = KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_CRT_PRIVATE, (short)(rsaPriKeyLen / 5 * 16), false);
                ret = getRsaPriKeyComponent(ID_P, tempBuffer, (short)0);
                ((RSAPrivateCrtKey)key).setP(tempBuffer, (short)0, ret);
                ret = getRsaPriKeyComponent(ID_Q, tempBuffer, (short)0);
                ((RSAPrivateCrtKey)key).setQ(tempBuffer, (short)0, ret);
                ret = getRsaPriKeyComponent(ID_DP1, tempBuffer, (short)0);
                ((RSAPrivateCrtKey)key).setDP1(tempBuffer, (short)0, ret);
                ret = getRsaPriKeyComponent(ID_DQ1, tempBuffer, (short)0);
                ((RSAPrivateCrtKey)key).setDQ1(tempBuffer, (short)0, ret);
                ret = getRsaPriKeyComponent(ID_PQ, tempBuffer, (short)0);
                ((RSAPrivateCrtKey)key).setPQ(tempBuffer, (short)0, ret);
            }
         // Creates a Signature object instance of the ALG_RSA_SHA_PKCS1 algorithm.
            rsaSignature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
            JCSystem.requestObjectDeletion();
         //Initializ the Signature object.
            rsaSignature.init(key, Signature.MODE_SIGN);

            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_INS, flags, OFF_INS, (short)3);
            JCSystem.requestObjectDeletion();
        }
        else
        {
            if (flags[OFF_INS] != buffer[ISO7816.OFFSET_INS]
                    || (flags[OFF_P1] & 0x7f) != (buffer[ISO7816.OFFSET_P1] & 0x7f)
                    || (short)(flags[OFF_P2] & 0xff) != (short)((buffer[ISO7816.OFFSET_P2] & 0xff) - 1))
            {
                Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            }

            flags[OFF_P2] ++;
        }

        if (hasMoreCmd)
        {
           // Accumulates a signature of the input data.
            rsaSignature.update(buffer, ISO7816.OFFSET_CDATA, len);
        }
        else
        {
           //Generates the signature of all input data.
            short ret = rsaSignature.sign(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0);
            Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
            apdu.setOutgoingAndSend((short)0, ret);
        }
    }
    //RSA Signature and Verify
    private void rsaVerify(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        if (rsaPubKeyLen == 0)
        {
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
        }
        boolean hasMoreCmd = (buffer[ISO7816.OFFSET_P1] & 0x80) != 0;
        short resultLen = 0;
        short offset = ISO7816.OFFSET_CDATA;
        short modLen = rsaPubKeyLen > 256 ? (short)256 : (short)128;
        if (buffer[ISO7816.OFFSET_P2] == 0) //first block
        {
            Key key;
            // Create uninitialized public keys for signature  algorithms.
            key = KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, (short)(modLen * 8), false);
            //Sets the modulus value of the key.
            ((RSAPublicKey)key).setModulus(rsaPubKey, (short)0, modLen);
            //Sets the public exponent value of the key.
            ((RSAPublicKey)key).setExponent(rsaPubKey, modLen, (short)(rsaPubKeyLen - modLen));

         //Create a ALG_RSA_SHA_PKCS1 object instance.
            rsaSignature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
            JCSystem.requestObjectDeletion();
            //Initializes the Signature object with the appropriate Key.
            rsaSignature.init(key, Signature.MODE_VERIFY);
            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_INS, flags, OFF_INS, (short)3);
            Util.setShort(flags, OFF_LEN, (short)0);
            JCSystem.requestObjectDeletion();
        }
        else
        {
            if (flags[OFF_INS] != buffer[ISO7816.OFFSET_INS]
                    || (flags[OFF_P1] & 0x7f) != (buffer[ISO7816.OFFSET_P1] & 0x7f)
                    || (short)(flags[OFF_P2] & 0xff) != (short)((buffer[ISO7816.OFFSET_P2] & 0xff) - 1))
            {
                Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            }

            flags[OFF_P2] ++;
        }

        short sigLen = Util.getShort(flags, OFF_LEN);
        if (sigLen < modLen)
        {
            short readLen = (short)(modLen - sigLen);
            if (readLen > len)
            {
                readLen = len;
            }
            Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, tempBuffer, sigLen, readLen);
            sigLen += readLen;
            len -= readLen;
            Util.setShort(flags, OFF_LEN, sigLen);
            offset += readLen;
        }
        if (hasMoreCmd)
        {
            if (len > 0)
            {
               //Accumulates a signature of the input data.
                rsaSignature.update(buffer, offset, len);
            }
        }
        else
        {
            if (sigLen != modLen)
            {
                Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
                ISOException.throwIt(ISO7816.SW_WRONG_DATA);
            }
            //Verify the signature of all/last input data against the passed in signature.
            boolean ret = rsaSignature.verify(buffer, offset, len, tempBuffer, (short)0, sigLen);
            Util.arrayFillNonAtomic(flags, (short)0, (short)flags.length, (byte)0);
            buffer[(short)0] = ret ? (byte)1 : (byte)0;
            apdu.setOutgoingAndSend((short)0, (short)1);
        }
    }
   
}



Note:
The purpose of this example is only used to show the usage of RSA algorithm .
You do not have the required permissions to view the files attached to this post. Please login first.

noabrw
Posts: 2
Joined: Wed Jan 03, 2018 5:31 am
Points: 104
Contact:

Re: The ALgorithm of RSA Sample Code

Postby noabrw » Mon Jan 22, 2018 4:31 am

how can i run this code and install it in card?

User avatar
JavaCardOS
Posts: 257
Joined: Thu Apr 30, 2015 12:00 pm
Points: 2253
Contact:

Re: The ALgorithm of RSA Sample Code

Postby JavaCardOS » Tue Jan 23, 2018 4:12 am

Hi,
You can use JCIDE to build this project and download the CAP file to java card.
You can refer to this forum:
viewforum.php?f=3


Return to “Applets Development Guide”

Who is online

Users browsing this forum: No registered users and 1 guest

JavaCard OS : Disclaimer