user1349407 user1349407 - 1 year ago 488
Java Question

RSA decryption error - IllegalBlockSizeException: Data must not be longer than 128 bytes

I am now on making RSA message authentication software. The process is as follows:

  1. Sign the message by using A's private key (1024 bit)

  2. Verify the message by using A's public key (1024 bit)

The #1 code (below) works fine and generates following result:


However the #2 code shows following error:

javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes

I think the line in #1
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

generates 2048 bits (256 bytes) result. Perhaps this is the problem... remember that I use 1024 bit private key.

So how can the #1 code generate 128-byte result?


public class SignMail {

static {
Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());

public static String sign(String userOriginalMessage) throws Exception {

PEMReader userPrivateKey = new PEMReader(
new InputStreamReader(
new FileInputStream(Environment.getExternalStorageDirectory()+"/pkcs10priv.key")));

KeyPair keyPair = (KeyPair)userPrivateKey.readObject();

byte[] cipherText;
//modified by JEON 20130817
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//encrypt the message using private key
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
cipherText = cipher.doFinal(userOriginalMessage.getBytes());
return new String(Hex.encode(cipherText));




public class UserSMSVerifier {

static String signedMail;

static {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

public static String messageGenarator(
String UserCert,
String origninalMessage
) throws Exception{

InputStream userCertStream = new ByteArrayInputStream(UserCert.getBytes("UTF-8"));

PEMReader userCerti = new PEMReader(
new InputStreamReader(

//KeyPair userPrivate = (KeyPair)userPrivateKey.readObject();
X509Certificate userCert = (X509Certificate)userCerti.readObject();

byte[] dectyptedText = null;
// decrypt the text using the private key
//modified by JEON 20130817
//Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, userCert.getPublicKey());
dectyptedText = cipher.doFinal(origninalMessage.getBytes());

String result = new String(dectyptedText, Charset.forName("UTF-8"));
return result;



the #2 code was executed by the following JSP

#3 messageVeri.JSP

<%@ page language="java" contentType="text/html; charset=euc-kr" %>

<%@ page session = "true" %>

<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.Statement" %>
<%@ page import="java.sql.SQLException" %>
<%@ page import="java.sql.ResultSet" %>

<%@ page import="myPackage.UserSMSVerifier" %>


String userID = request.getParameter("sender");
String encryptedSMS = request.getParameter("encryptedSMS");

//String sql = "select user_id, user_pw from testca.testca_init where user_id=? and user_pw=?";
//String sql = "update testca.testca_init set pkcs10request = '"+pkcs10request_new+"' where user_id='user1'";
String sql = "select * from testca.testca_init where user_id='" + userID + "'";


Connection conn = null;
PreparedStatement pstmt = null;

Statement stmt = null;
ResultSet rs = null;

String jdbcDriver = "jdbc:mysql://localhost:3306/";
String dbUser = "root";
String dbPass = "fo.......t";

conn = DriverManager.getConnection(jdbcDriver, dbUser, dbPass);
stmt = conn.createStatement();
String userCertificate=rs.getString("certificate");
UserSMSVerifier.messageGenarator(userCertificate, encryptedSMS);

}catch(Exception ex){out.print("Error 2: " +ex);}
//session.setAttribute("userID", userID);
out.print("Insert Succeed!");
//out.print("Welcome!" + " " + session.getAttribute("userID"));
out.print("failed to login!");


Answer Source

Your signature string contains 256 characters, however this is hexadecimal and really represents 128 bytes.

Before you verify the signature, you must convert this back to a byte array. This is not achieved through someString.getBytes() but rather via DatatypeConvert.parseHexBinary(someString) (or any other method you prefer from Google).

Also, I would strongly recommend you use the Signature class rather than the Cipher class when signing messages. Currently your code can only handle messages that are smaller than 128 bytes in length (smaller, in fact, due to padding). Instead, you should be hashing the message prior to signing (e.g. using the SHA256withRSA mechanism).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download