天天看點

解決超長内容加密失敗解決方案

    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:344)

    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)

    at javax.crypto.Cipher.doFinal(Cipher.java:2165)

    at com.asymmetric.rsa.TestRSA.testDecrypt(TestRSA.java:82)

    at com.asymmetric.rsa.TestRSA.main(TestRSA.java:33)

異常解釋

加密塊大小錯誤,rsa 加密 塊大小為117 ,解密塊大小為128 ,和公鑰加密或者私鑰加密無關,

測試程式碼如下:

import java.security.InvalidKeyException;

import java.security.Key;

import java.security.KeyFactory;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.spec.InvalidKeySpecException;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import java.util.Base64;

import javax.crypto.BadPaddingException;

import javax.crypto.Cipher;

import javax.crypto.IllegalBlockSizeException;

import javax.crypto.NoSuchPaddingException;

public class TestRSA {

    public static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQgEoj3z9JrdPNI23DbMQkl3gkGuDke7iBr5yrYyqolkTyxuBLWFwHNuGv4VKOj9fXg61QxpaJ/fxDBvMvmkBSRowHBloGFceVTx8wV/8u0DcjvTCu0IZ1zp6wjG6xBn5j66Sg/q+9hvaY2p7fkKmsvcW6VoNPgQHU1Cf01DLZmQIDAQAB+oXcINOiE3AsuZ4VJmwNZg9Y/7fY+OFRS2JAh5YMsrv2qyoGP+Z9ksre26NYR+Lt91B2lhdwJHLpQpziaANZm/ONb31fj/lwIDAQAB";

    public static String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANCASiPfP0mt080jbcNsxCSXeCQa4OR7uIGvnKtjKqiWRPLG4EtYXAc24a/hUo6P19eDrVDGlon9/EMG8y+aQFJGjAcGWgYVx5VPHzBX/y7QNyO9MK7QhnXOnrCMbrEGfmPrpKD+r72G9pjant+Qqay9xbpWg0+BAdTUJ/TUMtmZAgMBAAECgYBSozY/Z4FW+31h5fPgK+DFu/8TGFAgXuTvCaJnz2Md9IkZTDejxT6cYWUr53toI5zhvz/XLw6FXNQ54KxMJq/s9PiZYUgq/PMrnyU4gBSTm5BmiWjdaGicVEZ1lofHjpkAchPNW/CzwxD8AeKI7QaObE+EkWbLAi6sa+nRdHKgrQJBAOwYLD2DncU15XCKS0RNzTrNohdBQcisOPHdtQO0CGZlxx3xjuU4WL6/EpdmbjTeYbOSDKCmY5vyVbYZdOWfEs8CQQDiFIwWpvW2WLxLVw3i2P55WmMMXuecwEzg++ae3Ht7nW0zNcWSsyvHh40sM8XqEzmWOzMY6JOePbkuVfWTc4cXAkBRzf5mQhiEoKwjVofF3v9hhKbJT/8vPR1uENgLtHHEqTdZFL3ihqeZUDNs6jz9bKCFy/E8KOsSueEg+6kZdwjZAkEAj2RW4fstd2VasDJb5ViaNqAEmJENOBej60L6KCJR07qqy0M8t+oaR2iLOtDvo6Jj8QxFQXQqRMCDVodAxjANKwJAL3KuaqA6kdy9RxdV3uP8nRXLY7C/1ZIK6U0pyZqKXEwpD+7Ar3hwwhPz9TeuoqjB/cCknZjw70BQFQ0/VUHW2g==";

    private static String algorithm = "RSA"; //$NON-NLS-1$

    private static String data = "這是一個test"; //$NON-NLS-1$

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {

        byte[] test = testEncrypt(privateKey,data);

        String testDecrypt = testDecrypt(publicKey, test);

        System.out.println(testDecrypt);

    }

    /**

     * 加密

     * @param key

     * @param data

     * @return

     * @throws NoSuchAlgorithmException

     * @throws InvalidKeySpecException

     * @throws NoSuchPaddingException

     * @throws IllegalBlockSizeException

     * @throws BadPaddingException

     * @throws InvalidKeyException

     */

    public static byte[] testEncrypt(String key,String data) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException{

        byte[] decode = Base64.getDecoder().decode(key);

        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode);

        KeyFactory kf = KeyFactory.getInstance(algorithm);

        PrivateKey generatePrivate = kf.generatePrivate(pkcs8EncodedKeySpec);

        Cipher ci = Cipher.getInstance(algorithm);

        ci.init(1, generatePrivate);

        byte[] doFinal = ci.doFinal(data.getBytes());

//        return Base64.getEncoder().encodeToString(doFinal);

        return doFinal;

     * 解密

    public static String testDecrypt(String key,byte[] data) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException{

//        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode); //java底層 RSA公鑰隻支援X509EncodedKeySpec這種格式

        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode);

        PublicKey generatePublic = kf.generatePublic(x509EncodedKeySpec);

        ci.init(1,generatePublic);

//        byte[] doFinal = ci.doFinal(Base64.getDecoder().decode(data));

        byte[] doFinal = ci.doFinal(Base64.getDecoder().decode(data));

        return Base64.getEncoder().encodeToString(doFinal);

}

問題點:

後來發現是解密的時候.cipher.init(1,generatePublic)  cipher 模式填錯了,1就代表是加密模式,2是解密模式

將解密方法裡的cipher初始化改為 cipher.init(2,generatePublic) 即可

後來看到這個異常用大量資料去測試,也報這個異常,說明rsa加密必須對加密資料進行分組加密

查api指出:<code>IllegalBlockSizeException</code> - 如果此 Cipher 為 Cipher 塊,未請求任何填充(隻針對加密模式),並且由此 Cipher 處理的資料總輸入長度不是塊大小的倍數;如果此加密演算法無法處理所提供的輸入資料。

修正後的程式碼:

import java.io.ByteArrayOutputStream;

import java.io.IOException;

// PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode); //java底層 RSA公鑰隻支援X509EncodedKeySpec這種格式

X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode);

KeyFactory kf = KeyFactory.getInstance(algorithm);

PublicKey generatePublic = kf.generatePublic(x509EncodedKeySpec);

Cipher ci = Cipher.getInstance(algorithm);

ci.init(Cipher.DECRYPT_MODE,generatePublic);