RSA-公鑰加密,私鑰解密 、私鑰加密,公鑰解密、私鑰加簽,公鑰驗籤
阿新 • • 發佈:2019-01-03
一、案例內容:
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、
案例中的privateKey和publicKey是通過openssl生成的,可以直接用
(參考文章:https://blog.csdn.net/qq_31289187/article/details/84973338);
2、本案例有專門生成公私鑰對的方法,案例中使用了(commons-codec) 這個jar包,使用JDK8自帶的base64編解碼也可以。