2

I'm trying to implement the modPow function on Java Card using the build in RSA CryptoSystem. The code seems trivial but I have issued on implementation.

My code untill now :

    Cipher m_encryptCipherRSA = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); // create the cipher
    RSAPublicKey m_rsaPublicKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC,KeyBuilder.LENGTH_RSA_1024,false);  // create the public key
    m_random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
    m_random.generateData(temp1, (short)0, MODULUS_LENGTH);
    m_rsaPublicKey.setModulus(temp1,(short)0, MODULUS_LENGTH); //generate modulus
    m_random.generateData(temp1,(short)0, (short) EXPONENT_LENGTH);
    m_rsaPublicKey.setExponent(temp1,(short)0, (short)EXPONENT_LENGTH); 

The cod seems to work ok if EXPONENT_LENGTH has no more than 10 bytes.The Java Card I have has limited the dimension of public exponent. However my project is based on numbers up to 128bytes long.Is there a way to create a generic modpow function based on this hardware limitation? Is there another way I could implement the power exponentiation which is still feasible.

Alberto12
  • 509
  • 2
  • 16
  • What happens when you use `EXPONENT_LENGTH > 10`? What status word do you get? – vojta Apr 29 '16 at 11:28
  • @vojta 6f 00 which is unknown error. – Alberto12 Apr 30 '16 at 12:19
  • Catch the thrown exception and tell us its type (use the instanceof operator) and its reason (output of getReason() method), please. – vojta Apr 30 '16 at 17:16
  • @vojta I managed to solve the problem by using the private exponent instead of public one.Now I have the problem with dofinal method on Rsa when input is 1024 bits long and starts with an octet greater than 0x68. – Alberto12 May 01 '16 at 12:15
  • @vojta I started the new problem [here](http://stackoverflow.com/questions/36966764/rsa-cipher-java-card-error) with a detailed explanation – Alberto12 May 01 '16 at 12:43

2 Answers2

1

I managed to solve the problem by using the private exponent ( which seems not be constraint by RSA cryptosystem).Below is the working code.

    public byte[] modPow(byte[] x,short xOffset,short xLength,byte[] y,short yOffset,short yLength)
{
    Util.arrayCopy(y, yOffset, tempBuffer, (short)(Configuration.TEMP_OFFSET_EXPONENT+4), yLength);
    Util.arrayFillNonAtomic(tempBuffer, Configuration.TEMP_OFFSET_EXPONENT, (byte)4,(byte)0x00);
    mRsaPrivateKeyModPow.setExponent(tempBuffer,Configuration.TEMP_OFFSET_EXPONENT, (short)(yLength+4));
    mRsaCipherModPow.init(mRsaPrivateKeyModPow, Cipher.MODE_DECRYPT);
    Util.arrayCopy(x,xOffset,tempBuffer, Configuration.TEMP_OFFSET_RSA, Configuration.LENGTH_RSAOBJECT_MODULUS);
    mRsaCipherModPow.doFinal(tempBuffer,Configuration.TEMP_OFFSET_RSA, (short) (Configuration.LENGTH_RSAOBJECT_MODULUS), tempBuffer,Configuration.TEMP_OFFSET_RSA);
    mRsaPrivateKeyModPow.clearKey();
    return tempBuffer;
}
Alberto12
  • 509
  • 2
  • 16
1

Well, I tried both RSAPublicKey and RSAPrivateKey for two different cards, and both worked fine:

package soqPack;

import javacard.framework.*;
import javacard.security.KeyBuilder;
import javacard.security.RSAPrivateKey;
import javacard.security.RSAPublicKey;
import javacard.security.RandomData;
import javacardx.biometry.BioBuilder;
import javacardx.crypto.Cipher;

public class modPowtest extends Applet {

    //Definition Of INS in APDU command
    public static final byte INS_MOD_POW = (byte) 0x00;

    //Switch cases to choose RSA Public key or RSA Private key for ModPow()
    //P1 in APDU command.
    public static final byte USE_PUB_KEY = (byte) 0x00;
    public static final byte USE_PRI_KEY = (byte) 0x01;

    //Required objects
    byte[] tempMem;
    Cipher myCipher;
    RSAPrivateKey rsaPriKey;
    RSAPublicKey rsaPubKey;
    RandomData random;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new modPowtest();
    }

    protected modPowtest() {
        myCipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
        rsaPriKey = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_1024, false);
        rsaPubKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_1024, false);
        tempMem = JCSystem.makeTransientByteArray((short) 0x80, JCSystem.CLEAR_ON_DESELECT);
        random = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
        register();
    }

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

        byte[] buffer = apdu.getBuffer();
        switch (buffer[ISO7816.OFFSET_INS]) {
            case INS_MOD_POW:
                modPow(apdu);
                break;
            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }

    public void modPow(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        switch (buffer[ISO7816.OFFSET_P1]) {
            case USE_PUB_KEY:
                random.generateData(tempMem, (short) 0x00, (short) 0x80);
                rsaPubKey.setModulus(tempMem, (short) 0x00, (short) 0x80);
                random.generateData(tempMem, (short) 0x00, (short) 0x03);
                rsaPubKey.setExponent(tempMem, (short) 0x00, (short) 0x03);
                break;
            case USE_PRI_KEY:
                random.generateData(tempMem, (short) 0x00, (short) 0x80);
                rsaPriKey.setModulus(tempMem, (short) 0x00, (short) 0x80);
                random.generateData(tempMem, (short) 0x00, (short) 0x03);
                rsaPriKey.setExponent(tempMem, (short) 0x00, (short) 0x03);
                break;
            default:
                ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }

    }
}

Works as below:

Download Cap begin...
Download Cap successful.
Install Applet begin...
Install Applet successful.
Select Applet begin...
Select Applet successful.

Send: 00 00 00 00 00
Recv: 90 00

Send: 00 00 01 00 00
Recv: 90 00

Update: (Related your new question in the comments and here):

I also, changed value of tempMem[0] just before the setModulus and setExponent methods to 0x69, and it still works fine.

Community
  • 1
  • 1
EbraHim
  • 2,279
  • 2
  • 16
  • 28
  • 2
    I read that `setExponent()` may fail if the size of the exponent is greater than 4 bytes.From the oracle documentation I found this `All implementations must support exponent values up to 4 bytes in length. Implementations may also support exponent values greater than 4 bytes in length.` Here is the [link](http://www.win.tue.nl/pinpasjc/docs/apis/jc222/javacard/security/RSAPublicKey.html). – Alberto12 May 01 '16 at 13:03
  • I start [here](http://stackoverflow.com/questions/36966764/rsa-cipher-java-card-error) with the new problem.It seems to me a problem with the modulus vallue.I guess it is less than the x-value from RSA and the algorithm fails. – Alberto12 May 01 '16 at 13:08