10

私は現在、RSA メッセージ認証ソフトウェアを作成しています。プロセスは次のとおりです。

  1. A の秘密鍵 (1024 ビット) を使用してメッセージに署名する
  2. A の公開鍵 (1024 ビット) を使用してメッセージを検証する

#1 コード (以下) は正常に動作し、次の結果が生成されます。

5554c9a9f6838b6cf40d9dbfbab3d90ea27aa6434ed095d289c13c2624617993ad99161ac265276d150510c176341d8ab8600d08b7353286d465e6bd3370a6fd8dd3ffb82916f612fd6dcee5e654ed801cfca6b6d2d5d6dc99ff7921b615abdf62eb67db1f71e6a6ea70012fd35e7cefa1a8d3aab7614c47746cfe1fc2bc875b

ただし、#2 コードには次のエラーが表示されます。

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

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); #1 の行は2048 ビット (256 バイト) の結果を生成すると思います。おそらくこれが問題です... 1024 ビットの秘密鍵を使用していることを思い出してください。

では、1 番目のコードはどのようにして 128 バイトの結果を生成できるのでしょうか?

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 によって実行されました

#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();
    }
    */

%>
4

5 に答える 5

2

Duncan が言ったように、DateTypeConverter のようなものが必要です。

Base64.getDecoder().decode(encodedString)を使用すると、128 バイトの配列が返されました。

encodedString.getBytes() を使用していたとき、172 バイトの配列が返されました。

ちなみに、私は 1024 ビットの RSA キーを持っていました。

于 2016-11-25T11:03:24.910 に答える
0

publicKey でデータを分割する必要があります

int keyLength = publicKey.getModulus().bitLength() / 16;
String[] datas = splitString(data, keyLength - 11);
String mi = "";
        //如果明文长度大于模长-11则要分组加密
for (String s : datas) {
            mi += bcd2Str(cipher.doFinal(s.getBytes()));
}
return mi;


public static String bcd2Str(byte[] bytes) {
    char temp[] = new char[bytes.length * 2], val;

    for (int i = 0; i < bytes.length; i++) {
        val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
        temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

        val = (char) (bytes[i] & 0x0f);
        temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
    }
    return new String(temp);
}
于 2016-07-19T03:24:15.110 に答える