1. 程式人生 > >RSA-公鑰加密,私鑰解密 、私鑰加密,公鑰解密、私鑰加簽,公鑰驗籤

RSA-公鑰加密,私鑰解密 、私鑰加密,公鑰解密、私鑰加簽,公鑰驗籤

一、案例內容:

RSA 公鑰加密,私鑰解密;
RSA 私鑰加密,公鑰解密;
RSA 私鑰加簽,公鑰驗籤(SHA1WithRSA或者SHA256WithRSA-數字簽名)

二、引入的jar包

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <!-- Base64編碼 -->
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.11</version>
</dependency>

三、案例程式碼

package com.cn.dl;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

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;

/**
 * 1、RSA 公鑰加密,私鑰解密
 * 2、RSA 私鑰加密,公鑰解密
 * 3、RSA 私鑰加簽,公鑰驗籤(SHA1WithRSA或者SHA256WithRSA-數字簽名)
 *
 * Created by yanshao on 2018/12/12.
 */
public class NewRSAUtils {

    //加密演算法
    private static final String  SHA256WithRSA = "SHA256WithRSA";
    //public static final String  SIGN_ALGORITHMS = "SHA1WithRSA";
    private static final String   RSA = "RSA";

    //編碼
    private static final String CHARSET_UTF_8 = "utf-8";

    //私鑰
    private static final String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCqrpUHZx/NSRsK" +
            "jQc9i/gCGzU9Q3qRf44pm0lML9FfJf+m9mo9qdAEsMl3N0Y/nVcdGWb8VBry+dyl" +
            "mKNR4VPfFNGQKWW8OtvUlT9l3I9/MTd/ZsoVt2dQdBvOp7+9hrClS+rmw/HFz81l" +
            "RCFcku8HIIIcFxPQylRgSxHI8PMVJEodBsQSRvOzGtzWTfhTfG0Y0sgZPt75hKjd" +
            "J1rTo4264AG3YzlxHlmqrrQxxmYEKEnNplmNVga2bXvPICZ2VPbl9w/52mlSobg3" +
            "6VPKMzdlhTUgFsADPMaG2Pf3GqOa2GTSupzgTyz/54LyF6gCbXcAknRFgH5eyAv5" +
            "tPqV9CsrAgMBAAECggEAAXIHCxABgfCLjRRSql/EEuh+E+29XPwSjSGmhkGlaUPe" +
            "HWDa13jXrSJ+IkdSjflcIn/zklF4BPS+vJxFTc01s57ug2UGWoi5EdzNs6Qhhvc4" +
            "vBh3v6VU96Z0EdTz17wLROsWqyufoYg3+hKQocMQySOqVmiPn2YHPuWD2grIVDZ9" +
            "68mC1FykGEcv9De0m6yVEsfZDXNUxm3cz1758iBqakvyOVxGsI+V+e7/iSxJiwIB" +
            "6f3NSGQVtEsqwyhnl6dZRYDtnq5iUiwUOshl5Z2CYBfBcyTpMKC2RuHp3u9THHpc" +
            "3TFE4I1Li5HkiFy+ai6QKl2M85ce3GCXmjyw7n2vmQKBgQDTHihNX6uu6YlVFcRa" +
            "XhhGigyLrIP8LbLd4r/dKMXuGa8XqkLPlDtXelh2n565Lo5DPGlpANi3Jp495Hzn" +
            "bL+YnHJs7boVOGtORB0XHUbiMaTlT85snpvVjwFngHvY/ZxtXclpsnX563AvzCyl" +
            "amrKEhV17BFZbRQOTEL1UNp57QKBgQDO98AyfVgs1tCdtLOsFSFiWrAsJJimBS7b" +
            "ec+W/UPGDAl3hFzQzJ2SUvF4EneatYVOEDdHLUzVnT7XXeA/eMZL56N8BTSffh8q" +
            "XK0E21K8tW4hRbze6CIjbsJ1x7ZLZaoM4Ub2YAvkulF0PcasX0kWl+bv/DnkI09x" +
            "/n3vgbO2dwKBgQCoAnj6UmeztEDJiKARdo6FHHmtciY7Ozb8Y+Zin38c5C22fJXc" +
            "0k+DZ2cdSBwtrQIkOeB9YuIUp1QJV1ubZKz5S4+4ZlvPZW3oBEbOTUtK2U0r/J3/" +
            "TR4hD0SD1Pk6j2G8m4Wdaxt+P8KxFyB0p8LCey++/5Yy/56VXlVvGuAzZQKBgQCU" +
            "VfcXeMTIplGwpkGcFSzvLCZWDQim/NH/lYdWJUD84cWrNl+7ett4cyADueClLnJT" +
            "Z8Xmqq4F8ASJIQxHEY21+1gt3CFCKoe1ueR7taHQBIzhJfVfIarOEGUpOzEJSt0d" +
            "DBzrGh2MGomksV4CTuy4V7i5yeHIBBK9lfO2xBQEswKBgQCIzYO53kTFl6YGjmWO" +
            "qUJsT+5WegR4GdxtqYpQGPC1RmU7ig1TZzen+X3xB+lIHqgA1HvTr6M+tPkmnMwU" +
            "iARPOgjXY0zmsStXaHQYKruT3EjZRs2GnmVpVOAj1asqi+/2t0NgLgB5gPLYMXS+" +
            "BGf01OehvUt5Ge+OChDBXSW5Bw==";

    //公鑰
    private static final String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqq6VB2cfzUkbCo0HPYv4" +
            "Ahs1PUN6kX+OKZtJTC/RXyX/pvZqPanQBLDJdzdGP51XHRlm/FQa8vncpZijUeFT" +
            "3xTRkCllvDrb1JU/ZdyPfzE3f2bKFbdnUHQbzqe/vYawpUvq5sPxxc/NZUQhXJLv" +
            "ByCCHBcT0MpUYEsRyPDzFSRKHQbEEkbzsxrc1k34U3xtGNLIGT7e+YSo3Sda06ON" +
            "uuABt2M5cR5Zqq60McZmBChJzaZZjVYGtm17zyAmdlT25fcP+dppUqG4N+lTyjM3" +
            "ZYU1IBbAAzzGhtj39xqjmthk0rqc4E8s/+eC8heoAm13AJJ0RYB+XsgL+bT6lfQr" +
            "KwIDAQAB";

    /**
     * 生成公私鑰對
     * @return String[0]:公鑰,String[1]:私鑰
     */
    public static String[] generateKeyPair()
    {
        KeyPairGenerator keyPairGenerator = null;
        try
        {
            keyPairGenerator = keyPairGenerator.getInstance(RSA);
            keyPairGenerator.initialize(1024, new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            return new String[]{new Base64().encodeToString(publicKey.getEncoded()),
                     new Base64().encodeToString(privateKey.getEncoded())};
        }
        catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 使用私鑰給入參簽名
     * @param privateKey 私鑰
     * @param param      簽名的資料
     * @return            返回入參簽名16進位制字串
     * */
    public static String sign(String privateKey, String param) {
        try {
            //獲取privatekey
            byte[] privateKeyByte = new Base64().decode(privateKey);
            KeyFactory keyfactory = KeyFactory.getInstance(RSA);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
            PrivateKey key = keyfactory.generatePrivate(pkcs8EncodedKeySpec);

            //用私鑰給入參加籤
            Signature sign = Signature.getInstance(SHA256WithRSA);
            sign.initSign(key);
            sign.update(param.getBytes());

            byte[] signature = sign.sign();
            //將簽名的入參轉換成16進位制字串
            return bytesToHexStr(signature);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 用公鑰驗證簽名
     * @param param       入參
     * @param signature   使用私鑰簽名的入參字串
     * @param publicKey   公鑰
     * @return             返回驗證結果
     * */

    public static boolean verifySign(String param,String signature,String publicKey){
        try {
            //獲取公鑰
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            byte[] publicKeyByte = new Base64().decode(publicKey);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
            PublicKey key= keyFactory.generatePublic(x509EncodedKeySpec);

            //用獲取到的公鑰對   入參中未加簽引數param 與  入參中的加簽之後的引數signature 進行驗籤
            Signature sign=Signature.getInstance(SHA256WithRSA);
            sign.initVerify(key);
            sign.update(param.getBytes());

            //將16進位制碼轉成字元陣列
            byte[] hexByte = hexStrToBytes(signature);
            //驗證簽名
            return sign.verify(hexByte);

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

    /**
     * 使用公鑰加密
     * @param publicKey  公鑰
     * @param param      私鑰
     * @return  加密後的字串
     * */
    public static String RSAPublicEncrypt(String publicKey, String param) throws Exception {

        try {
            byte[] publicKeyByte = new Base64().decode(publicKey);
            KeyFactory keyfactory = KeyFactory.getInstance(RSA);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
            RSAPublicKey key = (RSAPublicKey)keyfactory.generatePublic(x509EncodedKeySpec);
            // 使用預設RSA
            Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.ENCRYPT_MODE,key);
            byte[] output = cipher.doFinal(param.getBytes(CHARSET_UTF_8));
            return bytesToHexStr(output);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 使用私鑰解密
     * @param privateKey  私鑰
     * @param encryptParam  公鑰加密的字串
     * @return  解密後的字串
     * */
    public static String RSAPrivateDecrypt(String privateKey,String encryptParam) throws Exception {

        Cipher cipher = null;
        try {
            // 使用預設RSA
            byte[] privateKeyByte = new Base64().decode(privateKey);
            KeyFactory keyfactory = KeyFactory.getInstance(RSA);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
            RSAPrivateKey key = (RSAPrivateKey)keyfactory.generatePrivate(pkcs8EncodedKeySpec);

            cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] output = cipher.doFinal(hexStrToBytes(encryptParam));
            return new String(output);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 私鑰加密,公鑰解密
     * @param privateKey   私鑰
     * @param param         需要加密的資料
     * @return 返回加密後的資料
     * */
    public static String RSAPrivateEncrypt(String privateKey, String param){
        try{

            // 使用預設RSA
            byte[] privateKeyByte = new Base64().decode(privateKey);
            KeyFactory keyfactory = KeyFactory.getInstance(RSA);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
            RSAPrivateKey key = (RSAPrivateKey)keyfactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] output = cipher.doFinal(param.getBytes(CHARSET_UTF_8));
            return bytesToHexStr(output);

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

    /**
     * 私鑰加密,公鑰解密
     * @param publicKey    公鑰
     * @param encryptParam   需要解密的資料
     * @return  返回解密後的資料
     * */
    public static String RSAPublicDecrypt(String publicKey, String encryptParam){
        try{
            byte[] publicKeyByte = new Base64().decode(publicKey);
            KeyFactory keyfactory = KeyFactory.getInstance(RSA);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
            RSAPublicKey key = (RSAPublicKey)keyfactory.generatePublic(x509EncodedKeySpec);
            // 使用預設RSA
            Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.DECRYPT_MODE,key);
            byte[] output = cipher.doFinal(hexStrToBytes(encryptParam));
            return new String(output);
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }


    /**
     * byte陣列轉換成十六進位制字串
     * @param bytes byte陣列
     * @return      返回十六進位制字串
     */
    private static String bytesToHexStr(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer("");
        for (int i = 0; i < bytes.length; ++i) {
            stringBuffer.append(Integer.toHexString(0x0100 + (bytes[i] & 0x00FF)).substring(1).toUpperCase());
        }
        return stringBuffer.toString();
    }

    /**
     * 十六進位制字串轉成byte陣列
     * @param hexStr   十六進位制字串
     * @return          返回byte陣列
     * */
    private static byte[] hexStrToBytes(String hexStr) {
        byte[] bytes = new byte[hexStr.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(hexStr.substring(2 * i, 2 * i + 2), 16);
        }
        return bytes;
    }

    public static void main(String[] args) throws Exception{

        String[] keyPair = generateKeyPair();
        System.out.println("公鑰>>"+keyPair[0]);
        System.out.println("私鑰>>"+keyPair[1]);

        JSONObject json = new JSONObject();
        json.put("name","yanshao");
        json.put("ab","ab");
        json.put("age",25);
        json.put("address","武漢");
        String params = json.toJSONString();
        System.out.println("入參>>>"+params);
        String sign = sign(keyPair[1],params);
        System.out.println("簽名後的引數>>>"+sign);
        System.out.println("驗證結果>>>"+verifySign(params,sign,keyPair[0]));


        String encrypt = RSAPublicEncrypt(keyPair[0],params);
        System.out.println("公鑰加密>>>"+encrypt);
        System.out.println("私鑰解密>>>"+RSAPrivateDecrypt(keyPair[1],encrypt));


        String encrypt1 = RSAPrivateEncrypt(keyPair[1],params);
        System.out.println("私鑰加密>>>"+encrypt1);
        System.out.println("公鑰解密>>>"+RSAPublicDecrypt(keyPair[0],encrypt1));


    }

}

四、執行結果

公鑰>>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9SZS0czkGetJU/+JcoVIyt3T0HYbk/s7E2kdReyEBdU06s8SPwSFIcn9D+zh2rEvzDylAYBpWIHfIWJhqkz53qxKH2GqkVrY2SipYQiVyH673mH7zmeYQWUZLW1AaAPZj+0ZJf8l82/P6c3zV1D/rgQHQDFaXS3xMwyah+KrjVQIDAQAB
私鑰>>MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAL1JlLRzOQZ60lT/4lyhUjK3dPQdhuT+zsTaR1F7IQF1TTqzxI/BIUhyf0P7OHasS/MPKUBgGlYgd8hYmGqTPnerEofYaqRWtjZKKlhCJXIfrveYfvOZ5hBZRktbUBoA9mP7Rkl/yXzb8/pzfNXUP+uBAdAMVpdLfEzDJqH4quNVAgMBAAECgYEAitUhIIkyVjJXesiDenVIGLK+MR5HBkZt2axPis/IkY07q8aWcOmyQ7TW60GjVEdjHU8Nbo4OQwVlVajFgcWlllHDaXrdh1cdzR0FTpxQV+dSr/U9UyLRmuSK2q/yavn4Zp9OVvoC7jPSe/J8lEwGIo6MSGD2JwGQFyAK4l5dcLECQQD+Ccb/R15RJUqRAbwMUtFDci1l2dwR/vte95RAIybWjxZ9AxHGvlqHLX40nxWWUc9SELawdxnZJYiPLdBqRuOPAkEAvr/LRkzo0Sd9gczWkn8/JP7HuiBJOvkYZWkSRMvKuu1smO3SjWIXqjf37S/nAqxP7NKvEiEamf0pZG0JJppI2wJBANR+EzGHXhJcMhI3NDfOsnJLOEQgxp9a/KLETwKTJLKGP9ZT0fO/V/QIjq+vfhwd1GAd0OKszTdA2QiC1vl+0GsCQCa9UQ1gBVClEopQDawHB839qJaWhAjkGh5ObpVmRjAclBejBUYNi/zYDRQwzFvwnvLb/w5RhtOLZOKuelNKtk0CQQDwd7ZSgGdo57Vf+LE8q/A3tW6QaobLK8A/wBG+hJuT9oS5pdIyl9BrbVR9srpedaDUK9QDkUaL+BhN4rzV/Iei
入參>>>{"ab":"ab","address":"武漢","name":"yanshao","age":25}
簽名後的引數>>>585E4FBBAF8D33D19E9CE8F7FBC9EC37C6E840BB0D1637FA84231A0D3B12942ADB768AEA15A2ADF5563C4400490254BB7F559B2B57B658C4421F408254E1F2BD759860FCED241C619FE86AE9403C5B1956AE232A1BF3B160A8D975349288421A4EB86B4AB975CE2A5788E3AA57B24E7811CFC3D8ED93BF6E8C2F3E4E599CA543
驗證結果>>>true
公鑰加密>>>8CB761651490298D0EBB68A78238A758E0DDC4D21CB289BF0268B50388033B2F1A1A7BB04B32BE3FD2A2911AC5C8E5EFE87340888DF193BBF17DAF67EC8D08BA24CB08C4C3086B4AEAE978E3349A1F454E87BF067101D596E77D148D2E6B092C256631D20C5D1AEA077E7765578DCC874CDC8CFC2051255009A613F159C22BB8
私鑰解密>>>{"ab":"ab","address":"武漢","name":"yanshao","age":25}
私鑰加密>>>360DF16454327F526FDD5B657FDBA8F2EF29210CA7797C3AD0C420A712871CD974A7ACC027009C3BF819E16344FD8EF8465D2C778A9DC8B1F839F0B60B818CC465A073A29121B736E9DFB5F82786BA1EE14155FEE9CC9145C07AC6795DF6590CA5746324DC63660560E8EA32C0722698DAD58E9BB555DBDBE961D5BBA4C93CA3
公鑰解密>>>{"ab":"ab","address":"武漢","name":"yanshao","age":25}

注意:

1、
案例中的privateKeypublicKey是通過openssl生成的,可以直接用 

(參考文章:https://blog.csdn.net/qq_31289187/article/details/84973338);

2、本案例有專門生成公私鑰對的方法,案例中使用了(commons-codec) 這個jar包,使用JDK8自帶的base64編解碼也可以。