Our Online Store have the new products: RFID antenna board. Currently it can work with JC10M24R and JCOP4 card chips.
Compared with normal cards, the antenna board module has a smaller size and fixed holes, which is easy to integrate in the IOT(Internet Of Things) project.

javax.crypto.BadPaddingException

JavaCard Applet Development Related Questions and Answers.
Heather
Posts: 24
Joined: Mon Nov 30, 2015 5:41 am
Points :121
Contact:

javax.crypto.BadPaddingException

Post by Heather » Wed Jun 28, 2017 11:40 pm

I have coded a part of an applet which sends the public key from the smart card to an offcard side. To check the public key is sent properly, I am trying to encode a text with the public key of the smart card in the offcard side and sent to the smart card which decode it with its private key and return the plain text. But when I run the offcard side, it appears the following error:
javax.crypto.BadPaddingException: Message is larger than modulus


Have anyone experienced this issue? Please help me out.

The code of the off card side:

Code: Select all

// Text to send
byte [] s = {(byte) 'H', (byte) 'i'};
RSAPublicKeySpec pubKeySpec;
KeyFactory keyFactory = null;
PublicKey pubKey = null ;
Cipher cipher = null;

// Get the data from the apdu
byte[] publicKeyMessage = apdu.getDataOut();
byte[] modulusArray = new byte [64];

// Get the modulus from the public key sent in the apdu
for (int i=0; i<64; i++){
       modulusArray[i] = publicKeyMessage[i+2];
}
byte[] exponentArray = new byte [3];

// Get the modulus from the public key sent in the apdu
for (int i=0; i<3; i++){
     exponentArray[i] = publicKeyMessage[i+68];
}

BigInteger modulus = new BigInteger(modulusArray);
BigInteger exponent = new BigInteger(exponentArray);
       
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
pubKeySpec = new RSAPublicKeySpec(modulus, exponent);
keyFactory = KeyFactory.getInstance("RSA");

// Build the public Key by means of the modulus and exponent specs
pubKey = keyFactory.generatePublic(pubKeySpec);

// Indicate the cipher to use the pubKey which has just been built
cipher.init(Cipher.ENCRYPT_MODE,pubKey);
byte[] p = new byte[64];

// Encrypt with the public key
cipher.doFinal(s, 0, s.length, p, 0);



Part of the applet code:

Code: Select all


// In the constructor:
...
RSACipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1,false);
...

//In the process method:
...
buffer = apdu.getBuffer();
byte [] buf = null;

// Get the encoded message
short numBytes = apdu.setIncomingAndReceive();

// Copy to a aux buffer
Util.arrayCopy(buf, ISO7816.OFFSET_CDATA, buffer, (short)0, numBytes);

// Initialize the cipher and decrypt to send the plain text again
RSACipher.init(PrivateKeyRSAEnc,Cipher.MODE_DECRYPT); 
RSACipher.doFinal(buf,(short)0,numBytes,buffer,(short)0);
apdu.setOutgoingAndSend((short) 0, numBytes);
...

User avatar
mabel
Posts: 237
Joined: Mon May 18, 2015 3:09 am
Points :1705
Contact:

Re: javax.crypto.BadPaddingException

Post by mabel » Thu Jun 29, 2017 4:11 am

Try to replace the following code

Code: Select all

byte[] p = new byte[64];
 
// Encrypt with the public key
cipher.doFinal(s, 0, s.length, p, 0);


with

Code: Select all

// Encrypt with the public key
byte[] p = cipher.doFinal(s);

Heather
Posts: 24
Joined: Mon Nov 30, 2015 5:41 am
Points :121
Contact:

Re: javax.crypto.BadPaddingException

Post by Heather » Thu Jun 29, 2017 5:10 am

I did as you said, but the error is still there. :cry:

Tarantino
Posts: 101
Joined: Wed Aug 19, 2015 1:56 am
Points :478
Contact:

Re: javax.crypto.BadPaddingException

Post by Tarantino » Fri Jun 30, 2017 5:31 am

You just need to add a check for a negative modulus coming from the card. In RSA encryption, you use large integers for the calculation. Even the message is converted to a large integer. For the equation to work, the message has to be smaller than the modulus.
If the first bit of your modulus from the card is set, add a 0x00 byte to front before setting the modulus in your key spec instance.
The greatest glory in living lies not in never falling, but in rising every time we fall.--Nelson Mandela

tay00000
Posts: 161
Joined: Tue Sep 27, 2016 10:58 am
Points :2324
Contact:

Re: javax.crypto.BadPaddingException

Post by tay00000 » Sun Jul 02, 2017 9:17 am

I noticed some possible programming flaws:

Code: Select all

// In the constructor:
...
RSACipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1,false);
...

//In the process method:
...
buffer = apdu.getBuffer();
byte [] buf = null;  // <----- buf variable is null, what is it used for ??

// Get the encoded message
short numBytes = apdu.setIncomingAndReceive();

// Copy to a aux buffer
Util.arrayCopy(buf, ISO7816.OFFSET_CDATA, buffer, (short)0, numBytes); // <---- why are you copying null buf as source to buffer ??

// Initialize the cipher and decrypt to send the plain text again
RSACipher.init(PrivateKeyRSAEnc,Cipher.MODE_DECRYPT); 
RSACipher.doFinal(buf,(short)0,numBytes,buffer,(short)0); // <---- why are you attempting to put a null buf variable as source for RSA operation ?????!!
apdu.setOutgoingAndSend((short) 0, numBytes);


I noticed a null type 'buf' object that is not having any value of it's own being put into the RSA decrytion operation in my comments above. Are you actually trying to copy data from 'buffer' into 'buf' and messed that part up ?

Also, another alternative is to directly read the buffer and decrypt. Not highly advisable but can be done to simplify the codes and with lesser codes comes lesser errors as shown below. Below, it will read directly from the incoming APDU buffer and then perform RSA operation on the data within APDU buffer without needing to store somewhere else.

Code: Select all

// Allocate a temporary RAM memory flag for storing amount of processed bytes for RSA op
short[] sBuf = JCSystem.makeTransientShortArray((short 1, JCSystem.CLEAR_ON_DESELECT);

// Perform RSA op and store in temp flag the amount of processed bytes
sBuf[0] = RSACipher.doFinal(buffer, (short) 0, numBytes, buffer, (short) 0);

// Send out the processed bytes as per the amount of bytes returned from RSA op
apdu.setOutgoingAndSend((short) 0, sBuff[0]);


A lazier method as shown below if you feel very adventurous and very lazy by simply combining the RSA op with the output of result.

Code: Select all

// Send out the processed bytes as per the amount of bytes returned from RSA op using a single line of code
apdu.setOutgoingAndSend((short) 0, RSACipher.doFinal(buffer, (short) 0, numBytes, buffer, (short) 0));

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 55 guests

JavaCard OS : Disclaimer