java版RSA工具類


/**
 * RSA算法加密/解密工具類
 */
public class RSAUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);
    /** 算法名稱 */
    private static final String ALGORITHM =  "RSA";
    /** 默認密鑰大小 */
    private static final int KEY_SIZE = 1024;
    /** 用來指定保存密鑰對的文件名和存儲的名稱 */
    private static final String PUBLIC_KEY_NAME = "publicKey";
    private static final String PRIVATE_KEY_NAME = "privateKey";
    private static final String PUBLIC_FILENAME = "publicKey.properties";
    private static final String PRIVATE_FILENAME = "privateKey.properties";
    /** 密鑰對生成器 */
    private static KeyPairGenerator keyPairGenerator = null;

    private static KeyFactory keyFactory = null;
    /** 緩存的密鑰對 */
    private static KeyPair keyPair = null;
    /** Base64 編碼/解碼器 JDK1.8 */
    private static Base64.Decoder decoder = Base64.getDecoder();
    private static Base64.Encoder encoder = Base64.getEncoder();
    /** 初始化密鑰工廠 */
    static{
        try {
            keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
            keyFactory = KeyFactory.getInstance(ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error(e.getMessage(),e);
        }
    }
    /** 私有構造器 */
    private RSAUtils(){}

    /**
     * 生成密鑰對
     * 將密鑰分別用Base64編碼保存到#publicKey.properties#和#privateKey.properties#文件中
     * 保存的默認名稱分別為publicKey和privateKey
     */
    public static synchronized Map<String, Object> generateKeyPair(){
        try {
            keyPairGenerator.initialize(KEY_SIZE,new SecureRandom(UUID.randomUUID().toString().replaceAll("-","").getBytes()));
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (InvalidParameterException e){
            LOGGER.error("KeyPairGenerator does not support a key length of " + KEY_SIZE + ".",e);
        } catch (NullPointerException e){
            LOGGER.error("RSAUtils#key_pair_gen is null,can not generate KeyPairGenerator instance.",e);
        }
        RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
        String publicKeyString = encoder.encodeToString(rsaPublicKey.getEncoded());
        String privateKeyString = encoder.encodeToString(rsaPrivateKey.getEncoded());
        storeKey(publicKeyString,PUBLIC_KEY_NAME,PUBLIC_FILENAME);
        storeKey(privateKeyString,PRIVATE_KEY_NAME,PRIVATE_FILENAME);
        Map<String, Object> keyPair = new HashMap<>();
        keyPair.put("public", privateKeyString);
        keyPair.put("private", privateKeyString);
        return keyPair;
    }

    /**
     * 將指定的密鑰字符串保存到文件中,如果找不到文件,就創建
     * @param keyString 密鑰的Base64編碼字符串(值)
     * @param keyName  保存在文件中的名稱(鍵)
     * @param fileName 目標文件名
     */
    private static void storeKey(String keyString,String keyName,String fileName){
        Properties properties = new Properties();
        //存放密鑰的絕對地址
        String path = null;
        try{
            path = RSAUtils.class.getClassLoader().getResource(fileName).toString();
            path = path.substring(path.indexOf(":") + 1);
        }catch (NullPointerException e){
            //如果不存#fileName#就創建
            LOGGER.warn("storeKey()# " + fileName + " is not exist.Begin to create this file.");
            String classPath = RSAUtils.class.getClassLoader().getResource("").toString();
            String prefix = classPath.substring(classPath.indexOf(":") + 1);
            String suffix = fileName;
            File file = new File(prefix + suffix);
            try {
                file.createNewFile();
                path = file.getAbsolutePath();
            } catch (IOException e1) {
                LOGGER.error(fileName +" create fail.",e1);
            }
        }
        try(OutputStream out = new FileOutputStream(path)){
            properties.setProperty(keyName,keyString);
            properties.store(out,"There is " + keyName);
        } catch (FileNotFoundException e) {
            LOGGER.error("ModulusAndExponent.properties is not found.",e);
        } catch (IOException e) {
            LOGGER.error("OutputStream output failed.",e);
        }
    }

    /**
     * 獲取密鑰字符串
     * @param keyName 需要獲取的密鑰名
     * @param fileName 密鑰所在文件
     * @return Base64編碼的密鑰字符串
     */
    private static String getKeyString(String keyName,String fileName){
        if (RSAUtils.class.getClassLoader().getResource(fileName) == null){
            LOGGER.warn("getKeyString()# " + fileName + " is not exist.Will run #generateKeyPair()# firstly.");
            generateKeyPair();
        }
        try(InputStream in = RSAUtils.class.getClassLoader().getResource(fileName).openStream()){
            Properties properties = new Properties();
            properties.load(in);
            return properties.getProperty(keyName);
        } catch (IOException e) {
            LOGGER.error("getKeyString()#" + e.getMessage(),e);
        }
        return  null;
    }

    /**
     * 從文件獲取RSA公鑰
     * @return RSA公鑰
     * @throws InvalidKeySpecException
     */
    public static RSAPublicKey getPublicKey(){
        try {
            byte[] keyBytes = decoder.decode(getKeyString(PUBLIC_KEY_NAME,PUBLIC_FILENAME));
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
            return (RSAPublicKey)keyFactory.generatePublic(x509EncodedKeySpec);
        }catch (InvalidKeySpecException e) {
            LOGGER.error("getPublicKey()#" + e.getMessage(),e);
        }
        return null;
    }

    /**
     * 從文件獲取RSA私鑰
     * @return RSA私鑰
     * @throws InvalidKeySpecException
     */
    public static RSAPrivateKey getPrivateKey(){
        try {
            byte[] keyBytes = decoder.decode(getKeyString(PRIVATE_KEY_NAME,PRIVATE_FILENAME));
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
            return (RSAPrivateKey)keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (InvalidKeySpecException e) {
            LOGGER.error("getPrivateKey()#" + e.getMessage(),e);
        }
        return null;
    }

    /**
     * RSA公鑰加密
     * @param content 等待加密的數據
     * @param publicKey RSA 公鑰 if null then getPublicKey()
     * @return 加密后的密文(16進制的字符串)
     */
    public static String encryptByPublic(byte[] content,PublicKey publicKey){
        if (publicKey == null){
            publicKey = getPublicKey();
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE,publicKey);
            //該密鑰能夠加密的最大字節長度
            int splitLength = ((RSAPublicKey)publicKey).getModulus().bitLength() / 8 -11;
            byte[][] arrays = splitBytes(content,splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays){
                stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
        } catch (NoSuchPaddingException e) {
            LOGGER.error("encrypt()#NoSuchPaddingException",e);
        } catch (InvalidKeyException e) {
            LOGGER.error("encrypt()#InvalidKeyException",e);
        } catch (BadPaddingException e) {
            LOGGER.error("encrypt()#BadPaddingException",e);
        } catch (IllegalBlockSizeException e) {
            LOGGER.error("encrypt()#IllegalBlockSizeException",e);
        }
        return null;
    }

    /**
     * RSA私鑰加密
     * @param content 等待加密的數據
     * @param privateKey RSA 私鑰 if null then getPrivateKey()
     * @return 加密后的密文(16進制的字符串)
     */
    public static String encryptByPrivate(byte[] content,PrivateKey privateKey){
        if (privateKey == null){
            privateKey = getPrivateKey();
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE,privateKey);
            //該密鑰能夠加密的最大字節長度
            int splitLength = ((RSAPrivateKey)privateKey).getModulus().bitLength() / 8 -11;
            byte[][] arrays = splitBytes(content,splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for(byte[] array : arrays){
                stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
        } catch (NoSuchPaddingException e) {
            LOGGER.error("encrypt()#NoSuchPaddingException",e);
        } catch (InvalidKeyException e) {
            LOGGER.error("encrypt()#InvalidKeyException",e);
        } catch (BadPaddingException e) {
            LOGGER.error("encrypt()#BadPaddingException",e);
        } catch (IllegalBlockSizeException e) {
            LOGGER.error("encrypt()#IllegalBlockSizeException",e);
        }
        return null;
    }



    /**
     * RSA私鑰解密
     * @param content 等待解密的數據
     * @param privateKey RSA 私鑰 if null then getPrivateKey()
     * @return 解密后的明文
     */
    public static String decryptByPrivate(String content,PrivateKey privateKey){
        if (privateKey == null){
            privateKey = getPrivateKey();
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE,privateKey);
            //該密鑰能夠加密的最大字節長度
            int splitLength = ((RSAPrivateKey)privateKey).getModulus().bitLength() / 8;
            byte[] contentBytes = hexStringToBytes(content);
            byte[][] arrays = splitBytes(contentBytes,splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            String sTemp = null;
            for (byte[] array : arrays){
                stringBuffer.append(new String(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
        } catch (NoSuchPaddingException e) {
            LOGGER.error("encrypt()#NoSuchPaddingException",e);
        } catch (InvalidKeyException e) {
            LOGGER.error("encrypt()#InvalidKeyException",e);
        } catch (BadPaddingException e) {
            LOGGER.error("encrypt()#BadPaddingException",e);
        } catch (IllegalBlockSizeException e) {
            LOGGER.error("encrypt()#IllegalBlockSizeException",e);
        }
        return null;
    }

    /**
     * RSA公鑰解密
     * @param content 等待解密的數據
     * @param publicKey RSA 公鑰 if null then getPublicKey()
     * @return 解密后的明文
     */
    public static String decryptByPublic(String content,PublicKey publicKey){
        if (publicKey == null){
            publicKey = getPublicKey();
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE,publicKey);
            //該密鑰能夠加密的最大字節長度
            int splitLength = ((RSAPublicKey)publicKey).getModulus().bitLength() / 8;
            byte[] contentBytes = hexStringToBytes(content);
            byte[][] arrays = splitBytes(contentBytes,splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            String sTemp = null;
            for (byte[] array : arrays){
                stringBuffer.append(new String(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
        } catch (NoSuchPaddingException e) {
            LOGGER.error("encrypt()#NoSuchPaddingException",e);
        } catch (InvalidKeyException e) {
            LOGGER.error("encrypt()#InvalidKeyException",e);
        } catch (BadPaddingException e) {
            LOGGER.error("encrypt()#BadPaddingException",e);
        } catch (IllegalBlockSizeException e) {
            LOGGER.error("encrypt()#IllegalBlockSizeException",e);
        }
        return null;
    }



    /**
     * 根據限定的每組字節長度,將字節數組分組
     * @param bytes 等待分組的字節組
     * @param splitLength 每組長度
     * @return 分組后的字節組
     */
    public static byte[][] splitBytes(byte[] bytes,int splitLength){
        //bytes與splitLength的余數
        int remainder = bytes.length % splitLength;
        //數據拆分后的組數,余數不為0時加1
        int quotient = remainder != 0 ? bytes.length / splitLength + 1:bytes.length / splitLength;
        byte[][] arrays = new byte[quotient][];
        byte[] array = null;
        for (int i =0;i<quotient;i++){
            //如果是最后一組(quotient-1),同時余數不等於0,就將最后一組設置為remainder的長度
            if (i == quotient -1 && remainder != 0){
                array = new byte[remainder];
                System.arraycopy(bytes,i * splitLength,array,0,remainder);
            } else {
                array = new byte[splitLength];
                System.arraycopy(bytes,i*splitLength,array,0,splitLength);
            }
            arrays[i] = array;
        }
        return arrays;
    }

    /**
     * 將字節數組轉換成16進制字符串
     * @param bytes 即將轉換的數據
     * @return 16進制字符串
     */
    public static String bytesToHexString(byte[] bytes){
        StringBuffer sb = new StringBuffer(bytes.length);
        String temp = null;
        for (int i = 0;i< bytes.length;i++){
            temp = Integer.toHexString(0xFF & bytes[i]);
            if(temp.length() <2){
                sb.append(0);
            }
            sb.append(temp);
        }
        return sb.toString();
    }

    /**
     * 將16進制字符串轉換成字節數組
     * @param hex 16進制字符串
     * @return byte[]
     */
    public static byte[] hexStringToBytes(String hex){
        int len = (hex.length() / 2);
        hex = hex.toUpperCase();
        byte[] result = new byte[len];
        char[] chars = hex.toCharArray();
        for (int i= 0;i<len;i++){
            int pos = i * 2;
            result[i] = (byte)(toByte(chars[pos]) << 4 | toByte(chars[pos + 1]));
        }
        return result;
    }

    /**
     * 將char轉換為byte
     * @param c char
     * @return byte
     */
    private static byte toByte(char c){
        return (byte)"0123456789ABCDEF".indexOf(c);
    }


    public static void main(String[] args) {
        String s = "test";
        RSAUtils.generateKeyPair();
        String c1 = RSAUtils.encryptByPublic(s.getBytes(),null);
        String m1 = RSAUtils.decryptByPrivate(c1,null);
        String c2 = RSAUtils.encryptByPrivate(s.getBytes(),null);
        String m2 = RSAUtils.decryptByPublic(c2,null);
        System.out.println(c1);
        System.out.println(m1);
        System.out.println(c2);
        System.out.println(m2);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM