RSA加密長度限制問題解決 BadPaddingException

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2223)
    at com.asymmetric.rsa.TestRSA.testDecrypt(TestRSA.java:115)
    at com.asymmetric.rsa.TestRSA.main(TestRSA.java:34)

RSA加密支持長度117,解密支持最大長度128【同事測試結果】
RSA可以用公鑰加密,私鑰解密,同時也可以用私鑰加密,公鑰解密;

直接貼工具類


import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * SecurityUtil簡介
 *
 * @author zengdezheng3
 * @date 2020-02-20 19:29
 */
public class SecurityUtil {

    private final static Logger log = Logger.getLogger(SecurityUtil.class);
    private String secretKey;//加解密密鑰
    private String charetSet = "utf-8";

    /**
     * 加密算法RSA
     */
    private static final String KEY_ALGORITHM = "RSA";
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    /**
     * 常量0
     */
    private static final int ZERO = 0;

    public SecurityUtil(){

    }

    public SecurityUtil(String secretKey) {
        this.setSecretKey(secretKey);
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public void setCharetSet(String charetSet) {
        this.charetSet = charetSet;
    }

    /**
     * AES加密
     *
     * @param str
     * @return
     */
    public String encryptStrWithAes(String str) {
        String resStr = null;
        try {
            byte[] raw = secretKey.getBytes(charetSet);
            SecretKeySpec key = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/補碼方式"
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] byteContent = str.getBytes(charetSet);
            byte[] encrypted = cipher.doFinal(byteContent);
            BASE64Encoder encoder = new BASE64Encoder();
            resStr = encoder.encode(encrypted);
        } catch (Exception e) {
            log.error("AES加密失敗", e);
            throw new RuntimeException("AES加密失敗",e) ;
        }
        return resStr;
    }

    /**
     * AES解密
     *
     * @param str
     * @return
     */
    public String decryptStrWithAes(String str) {
        String resStr = null;
        try {
            byte[] raw = secretKey.getBytes(charetSet);
            SecretKeySpec key = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] decrypted = cipher.doFinal(decoder.decodeBuffer(str));
            resStr = new String(decrypted, charetSet);
        } catch (Exception e) {
            log.error("AES解密失敗", e);
            throw new RuntimeException("AES解密失敗",e) ;
        }
        return resStr;
    }

    public String aesEncode(String str){

        String resStr = null;
        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(secretKey.getBytes(charetSet));
            KeyGenerator kGen = KeyGenerator.getInstance("AES");
            kGen.init(128, random);
            SecretKey secretKey = kGen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 創建密碼器
            byte[] byteContent = str.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
            byte[] result = cipher.doFinal(byteContent);
            BASE64Encoder encoder = new BASE64Encoder();
            resStr= encoder.encode(result);
        } catch (Exception e){
            e.printStackTrace();
        }
        return resStr;
    }

    public String aesDecode(String str){
        String resStr = null;
        try {

            KeyGenerator kGen = KeyGenerator.getInstance("AES");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(secretKey.getBytes());
            kGen.init(128, random);
            SecretKey secretKey = kGen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 創建密碼器
            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] decrypted = cipher.doFinal(decoder.decodeBuffer(str));
            resStr = new String(decrypted, charetSet);
        } catch (Exception e){
            e.printStackTrace();
        }
        return resStr;
    }

    /**
     * 隨機生成密鑰對
     * @throws NoSuchAlgorithmException
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator類用於生成公鑰和私鑰對,基於RSA算法生成對象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密鑰對生成器,密鑰大小爲96-1024位
        keyPairGen.initialize(1024,new SecureRandom());
        // 生成一個密鑰對,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私鑰
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公鑰
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到私鑰字符串
        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
        // 將公鑰和私鑰保存到Map
        System.out.println("公鑰:" + publicKeyString);
        System.out.println("私鑰:" + privateKeyString);

    }
    /**
     * RSA公鑰加密
     * @param str
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String encrypt( String str, String publicKey ) throws Exception{
        //base64編碼的公鑰
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
    }

    /**
     * RSA私鑰解密
     * @param str
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String decrypt(String str, String privateKey) throws Exception{
        //64位解碼加密後的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
        //base64編碼的私鑰
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return new String(cipher.doFinal(inputByte));
    }

    /**
     * 公鑰加密
     *
     * @param content      源數據
     * @param publicKey 公鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String content, String publicKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        byte[] data = content.getBytes(StandardCharsets.UTF_8);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        byte[] encrypt = encrypt(data, KeyFactory.getInstance(KEY_ALGORITHM), keyFactory.generatePublic(x509KeySpec));
        return  Base64.encodeBase64String(encrypt);
    }


    /**
     * 私鑰加密
     *
     * @param content       源數據
     * @param privateKey 私鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static String encryptByPrivateKey(String content, String privateKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        byte[] data = content.getBytes(StandardCharsets.UTF_8);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        byte[] encrypt = encrypt(data, keyFactory, privateK);
        return Base64.encodeBase64String(encrypt);
    }


    /**
     * 私鑰解密
     *
     * @param content 已加密數據
     * @param privateKey    私鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static String decryptByPrivateKey(String content, String privateKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        //64位解碼加密後的字符串
        byte[] encryptedData = Base64.decodeBase64(content.getBytes(StandardCharsets.UTF_8));
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        return new String(decrypt(encryptedData, keyFactory, keyFactory.generatePrivate(pkcs8KeySpec)));
    }


    /**
     * 公鑰解密
     *
     * @param content 已加密數據
     * @param publicKey     公鑰(BASE64編碼)
     * @return
     * @throws Exception
     */
    public static String decryptByPublicKey(String content, String publicKey)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        //64位解碼加密後的字符串
        byte[] encryptedData = Base64.decodeBase64(content.getBytes(StandardCharsets.UTF_8));
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        return new String(decrypt(encryptedData, keyFactory, publicK));

    }

    /**
     * 解密公共方法
     */
    private static byte[] decrypt(byte[] data, KeyFactory keyFactory, Key key) throws Exception {

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, key);
        return encryptAndDecrypt(data, cipher, MAX_DECRYPT_BLOCK);
    }

    /**
     * 加密公共方法
     */
    private static byte[] encrypt(byte[] data, KeyFactory keyFactory, Key key) throws Exception {
        // 對數據加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return encryptAndDecrypt(data, cipher, MAX_ENCRYPT_BLOCK);
    }


    /**
     * 加密解密分段處理公共方法
     */
    private static byte[] encryptAndDecrypt(byte[] data, Cipher cipher, int maxSize) throws Exception {
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = ZERO;
        byte[] cache;
        int i = ZERO;
        // 對數據分段加密
        while (inputLen - offSet > ZERO) {
            if (inputLen - offSet > maxSize) {
                cache = cipher.doFinal(data, offSet, maxSize);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, ZERO, cache.length);
            i++;
            offSet = i * maxSize;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }


    public static String decryptRSADefault(String privateKeyStr,String data) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] privateKeyArray = privateKeyStr.getBytes();
        byte[] dataArray = data.getBytes();
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyArray));
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(cipher.doFinal(Base64.decodeBase64(dataArray)), StandardCharsets.UTF_8);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            /*genKeyPair();*/
            String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrqdHrXcgPbVvJkVfV9yyWfOsQiMSWtZRz40GUDjhiLmW6lsrU5" +
                    "HixbIc69O6ms4LL3joYnFvkvTRAkBbuMTRY6aaup6Cpsg+9HDFS6qlSPeq53VlTkoIZ990QvSL6fMyT/mwt7T66QevU8cXUHv3RT4Sbj5TclIwr2PXiom84mwIDAQAB";

String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOup0etdyA9tW8mRV9X3LJZ86xCIxJa1lHPjQZQOOGIuZbqWytTke" +
                    "LFshzr07qazgsveOhicW+S9NECQFu4xNFjppq6noKmyD70cMVLqqVI96rndWVOSghn33RC9Ivp8zJP+bC3tPrpB69TxxdQe/dFPhJuPlNyUjCvY9eKibzibAgM" +
                    "BAAECgYAnJ9MqIS3halEq34xRj70Hz/+agq7vP4JH8wVtXSN/JKhgZTeUQdXP3PFnGVUhu4fK6cSLXEdkbQ9mfspgjypcHeV+lTzqR52oiuPEiMJPHFsSNYslorL" +
                    "ONmSWHyFGZAQe9H6Tl02GuIkSAXeruPYIHkx8WBGsIIwUeO3vRyXtUQJBAP033/PF8yAQwOJ6nnthcaaeSfu9zovPicKZ6P+5gXdBQYXX61cLqDX3gnyASZyrkgRn7" +
                    "FiZqZF2HPitPLJ+w+MCQQDuQJNYn7zt09E2fEvNjzWobt2oilpn/rDPzEzeaSGg1soxWt7KLWFqNfL+t++iUvlj+Kzx3I+o36HQK32vroXpAkABh7DmvC935iIEPFFw1" +
                    "WnmY9Z2mvMAjUR71Io/4VMS8WX/9QoLAJsHmHNFZVEMjUzYkfgvoN4RbvFF32YafgGZAkAAgG5O/3ccYRfNr5FRS33nbuRUmIX8NhMVPO7kgQArIIiodfKGJnZQDPEID" +
                    "Eca5mXUChADKl27E0157L2FAy8RAkAmnqO1yH+jN0dYccz6CibH0ReTjFNddojHqMxzl/ohDlCBTtn3RPHnzVz4U7iOh15Ka4JCVh+mMYtVoA9rgZwl";

            String content = "aRiSY6lzi0k/VfnSRc25R31pp4rEHfx633+E/vUF7yzzD9Gdblgn295jdvHn4eSB/uuDpYmwNQkpjYpaMCXJOJ6f2/Pp3uJEvurgnOOOoGw6OUHEUQh3YCYngWGi8jbwtXs0D5OZw1S6zQQAFWMMpzReMdEt67DcNOqvIe68xmCVTvfJhnW7lzFRrtcMe2w8ia8vYLJwlfr2fA1OfJlI+h6obEyVSFJhISTmccfkCCNqbZNnlzow2jA+NMkGoLnXXdOAnWspo7E/OV2mKkOhXxmFsUTCPE4ToC41N47VLn6Lc7byyYyMhPO4ZsmFI1tZAH01OiF+hMGgaHGzhHySpQ==";
            String decrypt = decryptByPrivateKey(content,privateKey);
            System.out.println("解密結果:" + decrypt);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

發佈了32 篇原創文章 · 獲贊 23 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章