java RSA 加密解密

RSA工具類.java

package com.zjp.common.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;

/**
 * RSAUtil工具類
 */
public class RSAUtil {

    // RSA key位數
    private static final int KEY_SIZE = 512;

    // 單次RSA加密操作所允許的最大塊長度,該值與 KEY_SIZE、padding方法有關。
    // 1024key->128,2048key->1256,512key->53,11個字節用於保存padding信息。
    private static final int BLOCK_SIZE = 53;

    private static final int OUTPUT_BLOCK_SIZE = 64;

    // private static final int KEY_SIZE = 1024;
    // private static final int BLOCK_SIZE = 117;
    // private static final int OUTPUT_BLOCK_SIZE = 128;

    // private static final int KEY_SIZE = 2048;
    // private static final int BLOCK_SIZE = 245;
    // private static final int OUTPUT_BLOCK_SIZE = 256;

    private static SecureRandom secrand = new SecureRandom();
    public static Cipher rsaCipher;

    public static String Algorithm = "RSA";// RSA、RSA/ECB/PKCS1Padding

    // public static String
    // Algorithm="RSA/ECB/PKCS1Padding";//RSA、RSA/ECB/PKCS1Padding

    public RSAUtil() throws Exception {
    }

    /**
     * 生成密鑰對
     * 
     * @return KeyPair
     * @throws Exception
     * @throws NoSuchAlgorithmException
     * @throws Exception
     */
    public static KeyPair generateRSAKeyPair() {
        KeyPair keyPair  =  null;
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator
                    .getInstance(Algorithm);
            // 密鑰位數
            keyPairGen.initialize(KEY_SIZE);
            // 密鑰對
            keyPair = keyPairGen.generateKeyPair();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return keyPair;
    }

    /**
     * 生成密鑰對
     * 
     * @return KeyPair
     * @throws Exception
     * @throws NoSuchAlgorithmException
     * @throws Exception
     */
    public static String[] generateRSAKeyPairStringArray() {
        String[] keypair = new String[2];
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator
                    .getInstance(Algorithm);
            // 密鑰位數
            keyPairGen.initialize(KEY_SIZE);
            // 密鑰對
            KeyPair keyPair = keyPairGen.generateKeyPair();

            // 公鑰
            PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

            // 私鑰
            PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

            String publicKeyString = getKeyString(publicKey);
            System.out.println("Public KEY===>" + publicKeyString);
            keypair[0] = publicKeyString;

            String privateKeyString = getKeyString(privateKey);
            System.out.println("Private KEY===>" + privateKeyString);
            keypair[1] = privateKeyString;

        } catch (Exception e) {
            System.err.println("Exception:" + e.getMessage());
        }
        return keypair;
    }

    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = Base64Encoder.decode(key);

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(Algorithm);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = Base64Encoder.decode(key);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(Algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    public static String getKeyString(Key key) throws Exception {
        byte[] keyBytes = key.getEncoded();
        String s = Base64Encoder.encode(keyBytes);
        return s;
    }

    /**
     * 對content採用RSA 公鑰加密,再使用BASE64加密
     * 
     * @param strPubKey
     *            公鑰值
     * @param content
     *            明文串
     * @return cardSecretPwd
     * @throws Exception
     */
    public static String encodeSecret(String publicKeyString, String content)
            throws Exception {

        try {
            rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw e;
        }

        Key publicKey = getPublicKey(publicKeyString);
        try {
            // PublicKey pubkey = keys.getPublic();
            rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey, secrand);
            // System.out.println(rsaCipher.getBlockSize());
            // System.out.println(Message.getBytes("utf-8").length);
            // byte[] encryptedData =
            // rsaCipher.doFinal(Message.getBytes("utf-8"));
            byte[] data = content.getBytes("utf-8");
            int blocks = data.length / BLOCK_SIZE;
            int lastBlockSize = data.length % BLOCK_SIZE;
            byte[] encryptedData = new byte[(lastBlockSize == 0 ? blocks
                    : blocks + 1) * OUTPUT_BLOCK_SIZE];
            for (int i = 0; i < blocks; i++) {
                // int thisBlockSize = ( i + 1 ) * BLOCK_SIZE > data.length ?
                // data.length - i * BLOCK_SIZE : BLOCK_SIZE ;
                rsaCipher.doFinal(data, i * BLOCK_SIZE, BLOCK_SIZE,
                        encryptedData, i * OUTPUT_BLOCK_SIZE);
            }
            if (lastBlockSize != 0) {
                rsaCipher.doFinal(data, blocks * BLOCK_SIZE, lastBlockSize,
                        encryptedData, blocks * OUTPUT_BLOCK_SIZE);
            }
            return Base64Encoder.encode(encryptedData);

        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new IOException("InvalidKey");
        } catch (ShortBufferException e) {
            e.printStackTrace();
            throw new IOException("ShortBuffer");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new IOException("UnsupportedEncoding");
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new IOException("IllegalBlockSize");
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new IOException("BadPadding");
        } finally {

        }
    }

    /**
     * 對content採用RSA加密,再BASE64加密
     * 
     * @param privateKeyString
     *            私鑰值
     * @param content
     *            明文串
     * @return cardSecretPwd
     * @throws Exception
     */
    public static String encodeSecretByPriKey(String privateKeyString,
            String content) throws Exception {

        try {
            rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw e;
        }

        Key privateKey = getPrivateKey(privateKeyString);
        try {
            // PublicKey pubkey = keys.getPublic();
            rsaCipher.init(Cipher.ENCRYPT_MODE, privateKey, secrand);
            // System.out.println(rsaCipher.getBlockSize());
            // System.out.println(Message.getBytes("utf-8").length);
            // byte[] encryptedData =
            // rsaCipher.doFinal(Message.getBytes("utf-8"));
            byte[] data = content.getBytes("utf-8");
            int blocks = data.length / BLOCK_SIZE;
            int lastBlockSize = data.length % BLOCK_SIZE;
            byte[] encryptedData = new byte[(lastBlockSize == 0 ? blocks
                    : blocks + 1) * OUTPUT_BLOCK_SIZE];
            for (int i = 0; i < blocks; i++) {
                // int thisBlockSize = ( i + 1 ) * BLOCK_SIZE > data.length ?
                // data.length - i * BLOCK_SIZE : BLOCK_SIZE ;
                rsaCipher.doFinal(data, i * BLOCK_SIZE, BLOCK_SIZE,
                        encryptedData, i * OUTPUT_BLOCK_SIZE);
            }
            if (lastBlockSize != 0) {
                rsaCipher.doFinal(data, blocks * BLOCK_SIZE, lastBlockSize,
                        encryptedData, blocks * OUTPUT_BLOCK_SIZE);
            }
            return Base64Encoder.encode(encryptedData);

        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new IOException("InvalidKey");
        } catch (ShortBufferException e) {
            e.printStackTrace();
            throw new IOException("ShortBuffer");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new IOException("UnsupportedEncoding");
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new IOException("IllegalBlockSize");
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new IOException("BadPadding");
        } finally {

        }
    }

    /**
     * BASE64解密,再RSA解密
     * 
     * @param strPriKey
     *            私鑰值
     * @param content
     *            密文串
     * @return 用私鑰解密串
     * @throws Exception
     */
    public static String decodeSecret(String privateKeyString, String content)
            throws Exception {

        try {
            rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw e;
        }

        byte[] decoded = null;
        try {
            decoded = Base64Encoder.decode(content);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        Key privateKey = getPrivateKey(privateKeyString);
        try {
            rsaCipher.init(Cipher.DECRYPT_MODE, privateKey, secrand);
            int blocks = decoded.length / OUTPUT_BLOCK_SIZE;
            ByteArrayOutputStream decodedStream = new ByteArrayOutputStream(
                    decoded.length);
            for (int i = 0; i < blocks; i++) {
                decodedStream.write(rsaCipher.doFinal(decoded, i
                        * OUTPUT_BLOCK_SIZE, OUTPUT_BLOCK_SIZE));
            }
            return new String(decodedStream.toByteArray(), "UTF-8");
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new IOException("InvalidKey");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new IOException("UnsupportedEncoding");
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new IOException("IllegalBlockSize");
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new IOException("BadPadding");
        } finally {

        }
    }

    /**
     * BASE64解密,再RSA解密
     * 
     * @param strPriKey
     *            私鑰值
     * @param content
     *            密文串
     * @return 用私鑰解密串
     * @throws Exception
     */
    public static String decodeSecretByPubKey(String publicKeyString,
            String content) throws Exception {

        try {
            rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw e;
        }

        byte[] decoded = null;
        try {
            decoded = Base64Encoder.decode(content);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        Key publicKey = getPublicKey(publicKeyString);
        try {
            rsaCipher.init(Cipher.DECRYPT_MODE, publicKey, secrand);
            int blocks = decoded.length / OUTPUT_BLOCK_SIZE;
            ByteArrayOutputStream decodedStream = new ByteArrayOutputStream(
                    decoded.length);
            for (int i = 0; i < blocks; i++) {
                decodedStream.write(rsaCipher.doFinal(decoded, i
                        * OUTPUT_BLOCK_SIZE, OUTPUT_BLOCK_SIZE));
            }
            return new String(decodedStream.toByteArray(), "UTF-8");
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new IOException("InvalidKey");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new IOException("UnsupportedEncoding");
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new IOException("IllegalBlockSize");
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new IOException("BadPadding");
        } finally {

        }
    }

}

測試:

package com.zjp.test.codec;

import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import org.junit.Test;

import com.zjp.common.utils.RSAUtil;

/**
 * 算法測試
 * 
 * @author babylon
 * 2016-5-10
 */
public class RSATest {

    public static void main(String[] args) throws Exception {
        KeyPair kp = RSAUtil.generateRSAKeyPair();
        RSAPublicKey pubk = (RSAPublicKey) kp.getPublic();//生成公鑰
        RSAPrivateKey prik= (RSAPrivateKey) kp.getPrivate();//生成私鑰
        String publicKey = RSAUtil.getKeyString(pubk);
        String privateKey = RSAUtil.getKeyString(prik);
        System.out.println("生成的公鑰 " + publicKey);
        System.out.println("生成的祕鑰 " + privateKey);
        String encodeStr = RSAUtil.encodeSecret(publicKey, "你好啊,嘿嘿嘿");
        System.out.println("使用公鑰後加密的內容 :" +encodeStr);
        String decodeStr = RSAUtil.decodeSecret(privateKey, encodeStr);
        System.out.println("解密後的內容:"+decodeStr);
    }

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