Christmas is coming soon! To thank for the support from all our dear customers, Christmas promotional activity is going on in JavaCardOS online store. For more activities details, please check this post.

Error when decrypting with RSA algorithm

Algorithm School

Moderator: UNKNwYSHSA

Robertdul
Posts: 7
Joined: Wed Sep 14, 2016 4:07 am
Points :92
Contact:

Error when decrypting with RSA algorithm

Post by Robertdul » Tue Mar 21, 2017 2:24 am

I am using RSA algorithm to encrypt data in my applet. But when I do the decryption, it gave prompt" Illegal Use Error".
Could somebody help to point out the mistake in my code? Many thanks.

Main section of my code:

Code: Select all

    public class RSAsamp extends Applet{  
    byte[] rsaPublic = new byte[4]; 
    byte[] rsaPrivate = new byte[4]; 
    byte[] rsaPublicMod = new byte[4]; 
    RSAPrivateKey pri ; 
    RSAPublicKey pub ; 
    private final static byte INS_ENCRYPT = (byte) 0x20; 
    private final static byte INS_DECRYPT = (byte) 0x30; 
    KeyPair pair ; 
   
    private RSAsamp() { 
      super(); 
      register(); 
    } 
     
     
    public static void install(byte bArray[], short bOffset, byte bLength) 
      throws ISOException { 
      new RSAsamp(); 
    } 
     
     
    public boolean select() { 
      pair = new KeyPair(KeyPair.ALG_RSA, (short) 512); 
      pair.genKeyPair(); 
    pri = (RSAPrivateKey) pair.getPrivate(); 
    pub = (RSAPublicKey) pair.getPublic(); 
     
      return super.select(); 
    } 
     
     
    public void deselect() { 
      super.deselect(); 
    } 
     
     
       public void process(APDU apdu) throws ISOException { 
        byte[] buffer = apdu.getBuffer(); 
        switch(buffer[ISO7816.OFFSET_INS]) 
        { 
        case INS_ENCRYPT: 
        encrypt(apdu); 
        break; 
        case INS_DECRYPT: 
        decrypt(apdu); 
        break; 
        } 
       } 
     
     
    private void decrypt(APDU apdu) { 
      byte[] buffer = apdu.getBuffer(); 
      byte byteRead = (byte)(apdu.setIncomingAndReceive()); 
      short size = 0; 
      try{ 
      Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false); 
      cipher.init(pri, Cipher.MODE_DECRYPT); 
     
      size =  cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short)byteRead, buffer, 
      (short) 0); 
      } 
      catch(CryptoException e) 
      { 
      switch(e.getReason()) 
      { 
      case CryptoException.ILLEGAL_USE: 
      ISOException.throwIt(ISO7816.SW_DATA_INVALID); 
      break; 
      case CryptoException.ILLEGAL_VALUE: 
      ISOException.throwIt(ISO7816.SW_FILE_INVALID); 
      break; 
      case CryptoException.INVALID_INIT: 
      ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); 
      break; 
      case CryptoException.NO_SUCH_ALGORITHM: 
      ISOException.throwIt(ISO7816.SW_FILE_INVALID); 
      break; 
      case CryptoException.UNINITIALIZED_KEY: 
      ISOException.throwIt(ISO7816.SW_FILE_FULL); 
      break; 
      default: 
      ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); 
      break; 
      } 
      } 
      apdu.setOutgoing(); 
      apdu.setOutgoingLength(size); 
      apdu.sendBytes((short)0, size); 
    } 
     
     
    private void encrypt(APDU apdu) { 
      byte[] buffer = apdu.getBuffer(); 
      byte byteRead = (byte)(apdu.setIncomingAndReceive()); 
      short size = 0; 
      try{ 
      Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false); 
      cipher.init(pub, Cipher.MODE_ENCRYPT); 
      size =  cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short)byteRead, buffer, 
      (short) 0); 
      } 
      catch(CryptoException e) 
      { 
      switch(e.getReason()) 
      { 
      case CryptoException.ILLEGAL_USE: 
      ISOException.throwIt(ISO7816.SW_DATA_INVALID); 
      break; 
      case CryptoException.ILLEGAL_VALUE: 
      ISOException.throwIt(ISO7816.SW_FILE_INVALID); 
      break; 
      case CryptoException.INVALID_INIT: 
      ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); 
      break; 
      case CryptoException.NO_SUCH_ALGORITHM: 
      ISOException.throwIt(ISO7816.SW_FILE_INVALID); 
      break; 
      case CryptoException.UNINITIALIZED_KEY: 
      ISOException.throwIt(ISO7816.SW_FILE_FULL); 
      break; 
      default: 
      ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); 
      break; 
      } 
      } 
      apdu.setOutgoing(); 
      apdu.setOutgoingLength(size); 
      apdu.sendBytes((short)0, size); 
    }   
     
    } 

User avatar
UNKNwYSHSA
Posts: 630
Joined: Thu May 21, 2015 4:05 am
Points :3027
Contact:

Re: Error when decrypting with RSA algorithm

Post by UNKNwYSHSA » Wed Mar 22, 2017 3:08 am

From your code, you didn't export any key (especially the public key), how do you encrypt the data? Where's the data you want to decrypted come from?
sense and simplicity

tay00000
Posts: 123
Joined: Tue Sep 27, 2016 10:58 am
Points :1600
Contact:

Re: Error when decrypting with RSA algorithm

Post by tay00000 » Thu Mar 23, 2017 10:08 pm

Just to add on to @UNKNwYSHSA comments, I would like to point out that these codes may have been copied without looking through or possibly another forum already have OP's questions.

Take a look at this site: http://www.amicuk.com/rsa-decrypt-not-working-please-help/

Before this turns into a spoonfeeding session where we simply give out answers to newbies, we need to make them think on what they are doing.

Let's break down those highly suspicious copy-and-paste codes.

Code: Select all

byte[] rsaPublic = new byte[4];  
byte[] rsaPrivate = new byte[4]; 
byte[] rsaPublicMod = new byte[4]; 


Creating a bunch of arrays for ? Maybe this is a code fragment and you simply forget to remove that before posting the code fragment ? Smart Cards have limited resources and limited Read/Write lifespan so be very careful on how you use them.

Code: Select all

public boolean select() {  
      pair = new KeyPair(KeyPair.ALG_RSA, (short) 512); 
      pair.genKeyPair(); 
    pri = (RSAPrivateKey) pair.getPrivate(); 
    pub = (RSAPublicKey) pair.getPublic(); 
     
      return super.select(); 
    }


This is a horrible code fragment. Totally horrible. What is the select() method in a JC ? Apparently you don't understand what select() means and simply just dump codes there. Whenever you select an applet, it calls the select() method and start loading the applet into JCVM for execution. Imagine you are to generate a new keypair everytime you select() a card applet, you will always have different private and public keys. How would you be able to encrypt and decrypt properly if you have none matching keypairs everytime you "boot up" your applet ? On top of that, you do not have a public key export to retrieve the public key before you encrypt the data to the card.

On top of all that issues, if you were to generate new keypair everytime you "boot up" your card, it will start to burn through the Read/Write lifespan of the EEPROM or Flash memory used to store the keys. This might not be a big issue if it's a card that you are going to use and throw pretty quickly but imagine if you are going to use it for daily use and a host computer would need to contact the card many times to encrypt and decrypt data frequently, you are going to run into tonnes of trouble for durability of the card.

Now let's go to the most important part on dissecting CryptoException.ILLEGAL_USE exception.

Take a look at the JC documentation for CryptoException.ILLEGAL_USE here: http://www.javafind.net/library/111/javacard_specifications-3_0_4-RR/classic/api_classic/index.html?overview-summary.html

You might want to book mark the link as well.

What it means is the padding in the cipher is misaligned and cannot be processed. Why would the padding be misaligned ? Look back at the cipher you are using which is ALG_RSA_PKCS1. It uses the PKCS1 padding method for RSA and how it is done for PKCS1 padding is it has a PKCS1 structure in ASN.1 syntax which encapsulates the plaintext and the padding within the ASN.1 formatted PKCS1 padding scheme. This PKCS1 style ASN.1 formatted data will then be encrypted by the RSA Private Key. If you have the wrong Public Key to encrypt that does not match the Private Key in the card, the card will attempt to decrypt the ciphertext and look for the ASN.1 structure first before extracting the plaintext.

By failing to decrypt (due to wrong keys used), it will most likely return the ILLEGAL_USE exception.

The entire problem lies in the select() method. Move the keypair generation to the install() method so that you will only invoke keypair generation when you install() the applet (happens only once) and then you will permanently have the same keypair for the entire lifecycle of the applet. You will also need a key export mechanism via another APDU to read out the RSA Public Key's Modulus via the PublicKey.getModulus(...) method.

Also, as a new developer for JC applets, you will be highly encouraged to read the following basic materials:
ftp://ftp.icm.edu.pl/packages/javasoft-docs/javacard/JCADG.pdf
http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-1.aspx

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 3 guests

JavaCard OS : Disclaimer