欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RSA加密长度限制问题解决 BadPaddingException

程序员文章站 2024-03-14 14:42:28
...
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();
        }

    }
}

相关标签: 加解密