RSA解密错误-IllegalBlockSizeException:数据长度不能超过128个字节 [英] RSA decryption error - IllegalBlockSizeException: Data must not be longer than 128 bytes

查看:217
本文介绍了RSA解密错误-IllegalBlockSizeException:数据长度不能超过128个字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在制作RSA消息认证软件.过程如下:

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

  1. 使用A的私钥(1024位)对消息签名
  2. 使用A的公钥(1024位)验证消息

下面的#1代码可以正常工作,并产生以下结果:

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

5554c9a9f6838b6cf40d9dbfbab3d90ea27aa6434ed095d289c13c2624617993ad99161ac265276d150510c176341d8ab8600d08b7353286d465e6bd3370a6fd8dd3ffb82916f612fd6dcee5e654ed801cfca6b6d2d5d6dc99ff7921b615abdf62eb67db1f71e6a6ea70012fd35e7cefa1a8d3aab7614c47746cfe1fc2bc875b

5554c9a9f6838b6cf40d9dbfbab3d90ea27aa6434ed095d289c13c2624617993ad99161ac265276d150510c176341d8ab8600d08b7353286d465e6bd3370a6fd8dd3ffb82916f612fd6dcee5e654ed801cfca6b6d2d5d6dc99ff7921b615abdf62eb67db1f71e6a6ea70012fd35e7cefa1a8d3aab7614c47746cfe1fc2bc875b

但是#2代码显示以下错误:

However the #2 code shows following error:

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

我认为#1 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");中的行 生成2048位(256字节)结果.也许这就是问题所在.记住我使用1024位私钥.

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.

那么#1代码如何生成128字节的结果?

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

1. SignMail.java

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));

    }


}

2. UserSMSVerifier.java

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(
                      userCertStream));



    //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;

}


}

#2代码是由以下JSP执行的

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" %>


<%
    request.setCharacterEncoding("euc-kr");

    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 + "'";

    Class.forName("com.mysql.jdbc.Driver");

    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";


    try{
        conn = DriverManager.getConnection(jdbcDriver, dbUser, dbPass);
        stmt = conn.createStatement();
        //stmt.executeUpdate(sql);
        rs=stmt.executeQuery(sql);
        while(rs.next()){
        //rs=stmt.executeQuery(sql);
        String userCertificate=rs.getString("certificate");
        UserSMSVerifier.messageGenarator(userCertificate, encryptedSMS);
        }



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

%>

推荐答案

您的签名字符串包含256个字符,但这是十六进制的,实际上代表128个 bytes .

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

在验证签名之前,必须将其转换回字节数组.这不是通过someString.getBytes()实现的,而是通过

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

此外,我强烈建议您在签名消息时使用Signature类而不是Cipher类.当前,您的代码只能处理长度小于128字节的消息(实际上,由于填充而较小).相反,您应该在签名之前对消息进行哈希处理(例如,使用 SHA256withRSA机制).

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).

这篇关于RSA解密错误-IllegalBlockSizeException:数据长度不能超过128个字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆