天天看點

[轉]關于JAVA中RSA加簽解簽,私鑰加密公鑰解密和公鑰加密私鑰解密代碼詳解

一般為了安全采用的是私鑰加密,公鑰解密(公鑰可以用Base64轉換後公開)

package com.chitic.supplywater.common.service;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;

/**
 * <p>
 * 封裝同RSA非對稱加密算法有關的方法,可用于數字簽名,RSA加密解密
 * </p>
 *
 * @Copyright:WDSsoft
 */

public class RSATool {

    public RSATool() {
    }

    /**
     * 使用私鑰加密資料
     * 用一個已打包成byte[]形式的私鑰加密資料,即數字簽名
     *
     * @param keyInByte 打包成byte[]的私鑰
     * @param source    要簽名的資料,一般應是數字摘要
     * @return 簽名 byte[]
     */
    public static byte[] sign(byte[] keyInByte, byte[] source) {
        try {
            PKCS8EncodedKeySpec priv_spec = new PKCS8EncodedKeySpec(keyInByte);
            KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privKey = mykeyFactory.generatePrivate(priv_spec);
            Signature sig = Signature.getInstance("SHA1withRSA");
            sig.initSign(privKey);
            sig.update(source);
            return sig.sign();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 驗證數字簽名
     *
     * @param keyInByte 打包成byte[]形式的公鑰
     * @param source    原文的數字摘要
     * @param sign      簽名(對原文的數字摘要的簽名)
     * @return 是否證明 boolean
     */
    public static boolean verify(byte[] keyInByte, byte[] source, byte[] sign) {
        try {
            KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
            Signature sig = Signature.getInstance("SHA1withRSA");
            X509EncodedKeySpec pub_spec = new X509EncodedKeySpec(keyInByte);
            PublicKey pubKey = mykeyFactory.generatePublic(pub_spec);
            sig.initVerify(pubKey);
            sig.update(source);
            return sig.verify(sign);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 建立新的密鑰對,傳回打包的byte[]形式私鑰和公鑰
     *
     * @return 包含打包成byte[]形式的私鑰和公鑰的object[], 其中,object[0]為私鑰byte[],object[1]為公鑰byte[]
     */
    public static Object[] giveRSAKeyPairInByte() {
        KeyPair newKeyPair = creatmyKey();
        if (newKeyPair == null) {
            return null;
        }
        Object[] re = new Object[2];
        if (newKeyPair != null) {
            PrivateKey priv = newKeyPair.getPrivate();
            byte[] b_priv = priv.getEncoded();
            PublicKey pub = newKeyPair.getPublic();
            byte[] b_pub = pub.getEncoded();
            re[0] = b_priv;
            re[1] = b_pub;
            return re;
        }
        return null;
    }

    /**
     * 建立密鑰對
     *
     * @return KeyPair對象
     */
    public static KeyPair creatmyKey() {
        KeyPair myPair;
        long mySeed;
        mySeed = System.currentTimeMillis();
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
            random.setSeed(mySeed);
            keyGen.initialize(1024, random);
            myPair = keyGen.generateKeyPair();
        } catch (Exception e1) {
            return null;
        }
        return myPair;
    }

    /**
     * 使用RSA公鑰加密資料
     *
     * @param pubKeyInByte 打包的byte[]形式公鑰
     * @param data         要加密的資料
     * @return 加密資料
     */
    public static byte[] encryptByRSA(byte[] pubKeyInByte, byte[] data) {
        try {
            KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec pub_spec = new X509EncodedKeySpec(pubKeyInByte);
            PublicKey pubKey = mykeyFactory.generatePublic(pub_spec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 用RSA私鑰解密
     *
     * @param privKeyInByte 私鑰打包成byte[]形式
     * @param data          要解密的資料
     * @return 解密資料
     */
    public static byte[] decryptByRSA(byte[] privKeyInByte, byte[] data) {
        try {
            PKCS8EncodedKeySpec priv_spec = new PKCS8EncodedKeySpec(
                    privKeyInByte);
            KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privKey = mykeyFactory.generatePrivate(priv_spec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            return null;
        }

    }


    /**
     * 使用RSA私鑰加密資料
     *
     * @param privKeyInByte 打包的byte[]形式私鑰
     * @param data          要加密的資料
     * @return 加密資料
     */
    public static byte[] encryptByRSA1(byte[] privKeyInByte, byte[] data) {
        try {
            PKCS8EncodedKeySpec priv_spec = new PKCS8EncodedKeySpec(
                    privKeyInByte);
            KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privKey = mykeyFactory.generatePrivate(priv_spec);
            Cipher cipher = Cipher.getInstance(mykeyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * 用RSA公鑰解密
     *
     * @param pubKeyInByte 公鑰打包成byte[]形式
     * @param data         要解密的資料
     * @return 解密資料
     */
    public static byte[] decryptByRSA1(byte[] pubKeyInByte, byte[] data) {
        try {
            KeyFactory mykeyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec pub_spec = new X509EncodedKeySpec(pubKeyInByte);
            PublicKey pubKey = mykeyFactory.generatePublic(pub_spec);
            Cipher cipher = Cipher.getInstance(mykeyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, pubKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 計算字元串的SHA數字摘要,以byte[]形式傳回
     */
    public static byte[] MdigestSHA(String source) {
        //byte[] nullreturn = { 0 };
        try {
            MessageDigest thisMD = MessageDigest.getInstance("SHA");
            byte[] digest = thisMD.digest(source.getBytes("UTF-8"));
            return digest;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 測試
     */
    public static void main(String[] args) {
        try {
            //私鑰加密 公鑰解密
            //生成私鑰-公鑰對
            Object[] v = giveRSAKeyPairInByte();
            //獲得摘要
            byte[] source = MdigestSHA("假設這是要加密的客戶資料");
            //使用私鑰對摘要進行加密 獲得密文 即數字簽名
            byte[] sign = sign((byte[]) v[0], source);
            //使用公鑰對密文進行解密,解密後與摘要進行比對
            boolean yes = verify((byte[]) v[1], source, sign);
            if (yes) {
                System.out.println("比對成功 合法的簽名!");
            }


            //公鑰加密私鑰解密
            //獲得摘要
            byte[] sourcepub_pri = ("13265986584||316494646546486498||01||public").getBytes("UTF-8");

            //使用公鑰對摘要進行加密 獲得密文
            byte[] signpub_pri = encryptByRSA((byte[]) v[1], sourcepub_pri);
            //System.out.println("公鑰加密密文:"+new String(Base64.encodeBase64(signpub_pri)));

            //使用私鑰對密文進行解密 傳回解密後的資料
            byte[] newSourcepub_pri = decryptByRSA((byte[]) v[0], signpub_pri);

            System.out.println("私鑰解密:" + new String(newSourcepub_pri, "UTF-8"));
            //對比源資料與解密後的資料
            if (Arrays.equals(sourcepub_pri, newSourcepub_pri)) {
                System.out.println("比對成功 合法的私鑰!");
            }


            //私鑰加密公鑰解密
            //獲得摘要
            //byte[] sourcepri_pub = MdigestSHA("假設這是要加密的客戶資料");
            byte[] sourcepri_pub = ("13265986584||316494646546486498||01||private").getBytes("UTF-8");


            //使用私鑰對摘要進行加密 獲得密文
            byte[] signpri_pub = encryptByRSA1((byte[]) v[0], sourcepri_pub);

            //   System.out.println("私鑰加密密文:"+new String(Base64.encodeBase64(sign11)));
            //使用公鑰對密文進行解密 傳回解密後的資料
            byte[] newSourcepri_pub = decryptByRSA1((byte[]) v[1], signpri_pub);

            System.out.println("公鑰解密:" + new String(newSourcepri_pub, "UTF-8"));




            String PUBLICKEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCEGENnf3rdiO20isoLQqezw12FoWXII9FBw8nR1MWQ3X0CVzOsqY1hOmxD/YI9OB7WVIaVax5tj1l+wk6A0v85Z4OpGWqz4B5L3fCUlBwf/M6DXHlSN1OZttvQF3OeWvc6gvJHihR7pp18zc4KfCJx0Ry6IrGH/2SNOVE1AIgvRQIDAQAB";
            String PRIVATEKEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIQYQ2d/et2I7bSKygtCp7PDXYWhZcgj0UHDydHUxZDdfQJXM6ypjWE6bEP9gj04HtZUhpVrHm2PWX7CToDS/zlng6kZarPgHkvd8JSUHB/8zoNceVI3U5m229AXc55a9zqC8keKFHumnXzNzgp8InHRHLoisYf/ZI05UTUAiC9FAgMBAAECgYAGNcHNds/G5G4QY8n1149cwx19b8YCL7Thu5ucUr1q/w6mcoUKY/oyjPWUCLH7wMyqVNTy51NJ4UhazjW0lrbK4ZbPDHFij9CiZ7QFASiQ/TQWaL+KSIWnE6/rK9IdouwFKxk+cvvLteZoAXP6mFcrsa7LzfkENiIMu7mjpTNHAQJBANXv9U5JWOAVhWHDQcEWKn7YKpAVRleXdeUeJrXcdkqBDI+P6suA9j+ahDREfu+x65wUsrJotPHUXgJG0TarJIUCQQCeEPLrv6Qvi5+nbn2Eifn/fjsmIdI0U2WZKDHWJEnLsRUuGDNYxVE/SPDNDedA2OHeFB6j0Kk/ECdsWnUq6zvBAkAgUGViFMwa1MVX1fFZo+p5TFdpef0s/9Cr8djxAULQ0BtAmAFkCa+oPcOYTXxK4jnvUmUHc69ZE7W7bEzvj/wtAkB50X4mClAzBFxK4XCC0QOG0HYtcStbgFpwqvWdn+Hvxc4Y9DW+WHPBXimXHvv2ki+gw8jJX2rQW1bGvwBFz30BAkASPkORJxVWv91StjI2f/HXDO5eG5/su/XIb3eajaLUSEdaQlcs3ywLrrJ0o3VAR0J9aq59cmp6em017AMnmbF7";

            byte[] signPrivate = Base64.decodeBase64(PRIVATEKEY.getBytes());
            byte[] signPublic = Base64.decodeBase64(PUBLICKEY.getBytes());


            String publicpwd = "N/b4nYbbLFVq0yTAIOpNNydtNQUCQxQy0B7bD6kzxLMW2guYxXtWOC/9Z5dpWecx/y7d5CezUJ6cf/8++msiNie4DcKBaFDFPh5rPbjeEB+DRfhjcdR2BsVGXWLsq3dLYLgZObQXG6Tb9rXakuH34Y+6KIIwCjiODH2QAU+PSiM=";
            String privatepwd = "MTMyNjU5ODY1ODR8fDMxNjQ5NDY0NjU0NjQ4NjQ5OHx8MDF8fHByaXZhdGU=";
            //使用私鑰對密文進行解密 傳回解密後的資料
            byte[] newSource111 = decryptByRSA(signPrivate, Base64.decodeBase64(publicpwd.getBytes()));
            System.out.println("私鑰解密1:" + new String(newSource111, "UTF-8"));


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

        /*運作結果:

        比對成功 合法的簽名!
        私鑰解密:13265986584||316494646546486498||01||public
        比對成功 合法的私鑰!
        公鑰解密:13265986584||316494646546486498||01||private
        私鑰解密1:13265986584||316494646546486498||01||3156464564*/

    }

}