1. 程式人生 > >Java 加解密技術系列之 RSA

Java 加解密技術系列之 RSA

<span style="font-family:Comic Sans MS;font-size:12px;">package com.test.rsa;

import com.google.common.collect.Maps;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;

/**
 * Created by xiang.li on 2015/3/3.
 * RSA 加解密工具類
 */
public class RSA {
    /**
     * 定義加密方式
     */
    private final static String KEY_RSA = "RSA";
    /**
     * 定義簽名演算法
     */
    private final static String KEY_RSA_SIGNATURE = "MD5withRSA";
    /**
     * 定義公鑰演算法
     */
    private final static String KEY_RSA_PUBLICKEY = "RSAPublicKey";
    /**
     * 定義私鑰演算法
     */
    private final static String KEY_RSA_PRIVATEKEY = "RSAPrivateKey";

    /**
     * 初始化金鑰
     * @return
     */
    public static Map<String, Object> init() {
        Map<String, Object> map = null;
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_RSA);
            generator.initialize(1024);
            KeyPair keyPair = generator.generateKeyPair();
            // 公鑰
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            // 私鑰
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            // 將金鑰封裝為map
            map = Maps.newHashMap();
            map.put(KEY_RSA_PUBLICKEY, publicKey);
            map.put(KEY_RSA_PRIVATEKEY, privateKey);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 用私鑰對資訊生成數字簽名
     * @param data 加密資料
     * @param privateKey 私鑰
     * @return
     */
    public static String sign(byte[] data, String privateKey) {
        String str = "";
        try {
            // 解密由base64編碼的私鑰
            byte[] bytes = decryptBase64(privateKey);
            // 構造PKCS8EncodedKeySpec物件
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);
            // 指定的加密演算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取私鑰物件
            PrivateKey key = factory.generatePrivate(pkcs);
            // 用私鑰對資訊生成數字簽名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initSign(key);
            signature.update(data);
            str = encryptBase64(signature.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 校驗數字簽名
     * @param data 加密資料
     * @param publicKey 公鑰
     * @param sign 數字簽名
     * @return 校驗成功返回true,失敗返回false
     */
    public static boolean verify(byte[] data, String publicKey, String sign) {
        boolean flag = false;
        try {
            // 解密由base64編碼的公鑰
            byte[] bytes = decryptBase64(publicKey);
            // 構造X509EncodedKeySpec物件
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            // 指定的加密演算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取公鑰物件
            PublicKey key = factory.generatePublic(keySpec);
            // 用公鑰驗證數字簽名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initVerify(key);
            signature.update(data);
            flag = signature.verify(decryptBase64(sign));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 私鑰解密
     * @param data 加密資料
     * @param key 私鑰
     * @return
     */
    public static byte[] decryptByPrivateKey(byte[] data, String key) {
        byte[] result = null;
        try {
            // 對私鑰解密
            byte[] bytes = decryptBase64(key);
            // 取得私鑰
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 對資料解密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            result = cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 私鑰解密
     * @param data 加密資料
     * @param key 公鑰
     * @return
     */
    public static byte[] decryptByPublicKey(byte[] data, String key) {
        byte[] result = null;
        try {
            // 對公鑰解密
            byte[] bytes = decryptBase64(key);
            // 取得公鑰
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 對資料解密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            result = cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 公鑰加密
     * @param data 待加密資料
     * @param key 公鑰
     * @return
     */
    public static byte[] encryptByPublicKey(byte[] data, String key) {
        byte[] result = null;
        try {
            byte[] bytes = decryptBase64(key);
            // 取得公鑰
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 對資料加密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            result = cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 私鑰加密
     * @param data 待加密資料
     * @param key 私鑰
     * @return
     */
    public static byte[] encryptByPrivateKey(byte[] data, String key) {
        byte[] result = null;
        try {
            byte[] bytes = decryptBase64(key);
            // 取得私鑰
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 對資料加密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            result = cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 獲取公鑰
     * @param map
     * @return
     */
    public static String getPublicKey(Map<String, Object> map) {
        String str = "";
        try {
            Key key = (Key) map.get(KEY_RSA_PUBLICKEY);
            str = encryptBase64(key.getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 獲取私鑰
     * @param map
     * @return
     */
    public static String getPrivateKey(Map<String, Object> map) {
        String str = "";
        try {
            Key key = (Key) map.get(KEY_RSA_PRIVATEKEY);
            str = encryptBase64(key.getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * BASE64 解密
     * @param key 需要解密的字串
     * @return 位元組陣列
     * @throws Exception
     */
    public static byte[] decryptBase64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * BASE64 加密
     * @param key 需要加密的位元組陣列
     * @return 字串
     * @throws Exception
     */
    public static String encryptBase64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /**
     * 測試方法
     * @param args
     */
    public static void main(String[] args) {
        String privateKey = "";
        String publicKey = "";
        // 生成公鑰私鑰
        Map<String, Object> map = init();
        publicKey = getPublicKey(map);
        privateKey = getPrivateKey(map);
        System.out.println("公鑰: \n\r" + publicKey);
        System.out.println("私鑰: \n\r" + privateKey);
        System.out.println("公鑰加密--------私鑰解密");
        String word = "你好,世界!";
        byte[] encWord = encryptByPublicKey(word.getBytes(), publicKey);
        String decWord = new String(decryptByPrivateKey(encWord, privateKey));
        System.out.println("加密前: " + word + "\n\r" + "解密後: " + decWord);
        System.out.println("私鑰加密--------公鑰解密");
        String english = "Hello, World!";
        byte[] encEnglish = encryptByPrivateKey(english.getBytes(), privateKey);
        String decEnglish = new String(decryptByPublicKey(encEnglish, publicKey));
        System.out.println("加密前: " + english + "\n\r" + "解密後: " + decEnglish);
        System.out.println("私鑰簽名——公鑰驗證簽名");
        // 產生簽名
        String sign = sign(encEnglish, privateKey);
        System.out.println("簽名:\r" + sign);
        // 驗證簽名
        boolean status = verify(encEnglish, publicKey, sign);
        System.out.println("狀態:\r" + status);
    }
}</span>