wdss的blog

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

rsa默认最多只能加密密钥长度/8-11长度的明文,最多只能解密密钥长度/8长度的密文,如:

密钥长度为1024,则明文长度最长117,密文长度最长128。

可以采用分段加解密的方式,增加明文密文长度(同时加解密的效率也会按比例降低)。

工具类如下:

 

package com.kuandeng.common.common.util;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
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.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


@Slf4j
public class RSACipher {
    
    public static String AlgorithmName = "RSA";
    public static String Algorithm = "RSA/ECB/PKCS1Padding";
    public static int KeyLength = 2048;
    private static int MAX_ENCRYPT_BLOCK = 117;
    private static int MAX_DECRYPT_BLOCK = 128;
    static {
        MAX_ENCRYPT_BLOCK = KeyLength/8 - 11;
        MAX_DECRYPT_BLOCK = KeyLength/8;
    }

    @Getter
    private String publicKey;

    @Getter
    private String privateKey;

    //公钥加密
    private Cipher publicEncryptCipher = null;
    //私钥解密
    private Cipher privateDecryptCipher = null;
    //私钥加密
    private Cipher privateEncryptCipher = null;
    //公钥解密
    private Cipher publicDecryptCipher = null;

    public RSACipher(String publicKey, String privateKey) {
        this.init(publicKey, privateKey);
    }

    public void init(String publicKey, String privateKey){
        this.publicKey = publicKey;
        this.privateKey = privateKey;
        //公钥加密
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = null;
        try {
            pubKey = (RSAPublicKey) KeyFactory.getInstance(AlgorithmName).generatePublic(new X509EncodedKeySpec(decoded));
//            publicCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            publicEncryptCipher = Cipher.getInstance(Algorithm);
            publicEncryptCipher.init(Cipher.ENCRYPT_MODE, pubKey);
        } catch (InvalidKeySpecException | InvalidKeyException |
                NoSuchPaddingException | NoSuchAlgorithmException e) {
            log.warn(ExceptionHelper.getStackTraceString(e));
        }

        //私钥解密
        //64位解码加密后的字符串
        //base64编码的私钥
        byte[] decoded2 = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = null;
        try {
            priKey = (RSAPrivateKey) KeyFactory.getInstance(AlgorithmName).generatePrivate(new PKCS8EncodedKeySpec(decoded2));
//            privateCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            privateDecryptCipher = Cipher.getInstance(Algorithm);
            privateDecryptCipher.init(Cipher.DECRYPT_MODE, priKey);
        } catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException |
                InvalidKeyException e) {
            log.warn(ExceptionHelper.getStackTraceString(e));
        }

        //私钥加密
        byte[] decoded3 = Base64.decodeBase64(privateKey);
        RSAPrivateKey pubKey2 = null;
        try {
            pubKey2 = (RSAPrivateKey) KeyFactory.getInstance(AlgorithmName).generatePrivate(new PKCS8EncodedKeySpec(decoded3));
//            publicCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            privateEncryptCipher = Cipher.getInstance(Algorithm);
            privateEncryptCipher.init(Cipher.ENCRYPT_MODE, pubKey2);
        } catch (InvalidKeySpecException | InvalidKeyException |
                NoSuchPaddingException | NoSuchAlgorithmException e) {
            log.warn(ExceptionHelper.getStackTraceString(e));
        }

        //公钥解密
        //64位解码加密后的字符串
        //base64编码的私钥
        byte[] decoded23 = Base64.decodeBase64(publicKey);
        RSAPublicKey priKey2 = null;
        try {
            priKey2 = (RSAPublicKey) KeyFactory.getInstance(AlgorithmName).generatePublic(new X509EncodedKeySpec(decoded23));
//            privateCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            publicDecryptCipher = Cipher.getInstance(Algorithm);
            publicDecryptCipher.init(Cipher.DECRYPT_MODE, priKey2);
        } catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException |
                InvalidKeyException e) {
            log.warn(ExceptionHelper.getStackTraceString(e));
        }
    }

    //随机生成密钥对
    public static String[] genKeyPair() {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance(AlgorithmName);
        } catch (NoSuchAlgorithmException e) {
            log.warn(ExceptionHelper.getStackTraceString(e));
        }
        // 初始化密钥对生成器,密钥大小为96-1024位
        assert keyPairGen != null;
        keyPairGen.initialize(KeyLength, 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())));
        log.info("随机生成的公钥为:" + publicKeyString);
        log.info("随机生成的私钥为:" + privateKeyString);
        return new String[]{publicKeyString, privateKeyString};
    }


    private byte[] crypt(byte[] data, Cipher cipher, int maxLength) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int inputLen = data.length;
        int offSet = 0;
        byte[] cache;
        // 对数据分段解密
        try {
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > maxLength) {
                    cache = cipher.doFinal(data, offSet, maxLength);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                offSet += maxLength;
            }
            return out.toByteArray();
        } catch (BadPaddingException  | IllegalBlockSizeException e) {
            log.warn(ExceptionHelper.getStackTraceString(e));
        }
        finally {
            try{
                out.close();
            }catch (Exception e){
                log.warn(ExceptionHelper.getStackTraceString(e));
            }
        }
        return null;
    }

    /**
     * RSA分段加密
     *
     * @param str       加密字符串
     * @return 密文
     */
    private String encrypt(String str, Cipher cipher) {
        //只能处理MAX_ENCRYPT_BLOCK长度的数据,故用下面的代码改写
//        try {
//            return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
//        } catch (IllegalBlockSizeException e) {
//            e.printStackTrace();
//        } catch (BadPaddingException e) {
//            e.printStackTrace();
//        }

        byte[] data = str.getBytes(StandardCharsets.UTF_8);
        return Base64.encodeBase64String(crypt(data, cipher, MAX_ENCRYPT_BLOCK));
    }


    /**
     * RSA分段解密
     *
     * @param str        加密字符串
     * @return 明文
     */
    private String decrypt(String str, Cipher cipher) {
        //只能处理MAX_DECRYPT_BLOCK长度的数据,故用下面的代码改写
//        byte[] data = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
//        try {
//            return new String(privateDecryptCipher.doFinal(data));
//        } catch (BadPaddingException |
//                IllegalBlockSizeException e) {
//            e.printStackTrace();
//        }

        byte[] data = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
        byte[] result = crypt(data, cipher, MAX_DECRYPT_BLOCK);
        if(result == null){
            return null;
        }
        return new String(result, StandardCharsets.UTF_8);
    }



    /**
     * RSA公钥加密
     *
     * @param str       加密字符串
     * @return 密文
     */
    public String publicEncrypt(String str) {
        return encrypt(str, publicEncryptCipher);
    }


    /**
     * RSA私钥解密
     *
     * @param str        加密字符串
     * @return 明文
     */
    public String privateDecrypt(String str) {
        return decrypt(str, privateDecryptCipher);
    }

    /**
     * RSA私钥加密
     *
     * @param str       加密字符串
     * @return 密文
     */
    public String privateEncrypt(String str) {
        return encrypt(str, privateEncryptCipher);
    }


    /**
     * RSA公钥解密
     *
     * @param str        加密字符串
     * @return 明文
     */
    public String publicDecrypt(String str) {
        return decrypt(str, publicDecryptCipher);
    }
}

  

 

posted on 2024-05-31 16:46  wdss  阅读(8)  评论(0编辑  收藏  举报