最近一直在和保險公司做對接,發現保險公司為了數據的安全一直都在用非對稱加密算法(RSA)來保證數據的安全,以前也了解過RSA的原理,就是文字的理解,但是時間一長就忘了,這次正好重新整理一下,順便一個demo 奉獻上。
為什么呢,因為他相對安全呀,既然說到相對,就有相對不安全的,以前大家為了加密數據,都是用的對稱加密,意思就是進行數據交互的書雙方用一套規則,甲方用這個規則來加密,把加密的數據給乙方,乙方根據這個規則反推,把數據解密出來,但是有一個問題,其中一方把這個規則丟了,數據就不再安全。 那么為什么RSA可以呢,RSA在1977年就又三個大神Rivest、Shamir 和 Adleman 設計了一種算法,可以實現非對稱加密,他的大致思想就是把以前的一套規則轉而去用兩套規則生成兩個秘鑰,一個稱為公鑰,一個稱為私鑰公鑰可以給任何人,但是私鑰自己留著,這樣只要私鑰不丟,數據就是安全的,迄今為止還沒有能破解2048位的秘鑰,所以來說相對安全。具體私鑰和公鑰是如何生成的,大家可以看這篇博客RSA算法原理,講的很詳細,我就不粘貼了。
工具類如下
package com.algor;import org.apache.commons.codec.binary.Base64;import org.apache.commons.collections.map.HashedMap;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 menghaibin on 2017/2/19. */public class RSATest { private static final String KEY_ALGORITHM = "RSA"; private static final String SIGNATURE_ALGORITHM = "md5withRSA"; private static final String PUBLIC_KEY = "RSAPublicKey"; private static final String PRIVATE_KEY = "RSAPrivateKey"; /** * 初始化公鑰和私鑰 * @return * @throws Exception */ public static Map<String,Object> initKey() throws Exception{ KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); pairGenerator.initialize(1024); KeyPair keyPair = pairGenerator.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String,Object> map = new HashedMap(2); map.put(PUBLIC_KEY,publicKey); map.put(PRIVATE_KEY,privateKey); return map; } public static String encryptBASE64(byte[] key) throws Exception { //return (new BASE64Encoder()).encodeBuffer(key); return Base64.encodeBase64String(key); } public static byte[] decryptBASE64(String key) throws Exception { //return (new BASE64Decoder()).decodeBuffer(key); return Base64.decodeBase64(key); } /** * 獲取公鑰 * @param map * @return */ public static String getPublicKey(Map<String,Object> map){ Key key = (Key) map.get(PUBLIC_KEY); try { return encryptBASE64(key.getEncoded()); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 獲取私鑰 * @param map * @return */ public static String getPrivateKey(Map<String,Object> map){ Key key = (Key) map.get(PRIVATE_KEY); try { return encryptBASE64(key.getEncoded()); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 用私鑰加密 * @param data 數據 * @param key 私鑰 * * @return */ public static byte[] encryptByPrivateKey(byte[] data,String key) throws Exception { //對秘鑰解密 byte[] keyBytes = decryptBASE64(key); //取得私鑰 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //對數據加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE,privateKey); return cipher.doFinal(data); } /** * 用公鑰加密數據 * @param data 數據 * @param key 公鑰 * @return 返回加密的數據 * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data,String key) throws Exception{ byte[] keyBytes = decryptBASE64(key); //取得公鑰 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = factory.generatePublic(x509EncodedKeySpec); //對數據加密 Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE,publicKey); return cipher.doFinal(data); } /** * 用公鑰解密 * @param data * @param key * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] data,String key) throws Exception{ byte[] keyBytes = decryptBASE64(key); //取得公鑰 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = factory.generatePublic(x509EncodedKeySpec); //對數據解密 Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE,publicKey); return cipher.doFinal(data); } /** * 用公鑰解密 * @param data * @param key * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] data,String key) throws Exception{ byte[] keyBytes = decryptBASE64(key); //取得私鑰 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = factory.generatePrivate(pkcs8EncodedKeySpec); //用私鑰解密 Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE,privateKey); return cipher.doFinal(data); } public static boolean verify(byte[] data,String publicKey,String sign) throws Exception { //解密由64編碼的公鑰 byte[] keyBytes = decryptBASE64(publicKey); //構造X509EncodedKeySpec的方法 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); //KEY_ALGORITHM指定的加密算法 KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM); //取公鑰對象 PublicKey pubKey = factory.generatePublic(x509EncodedKeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); return signature.verify(decryptBASE64(sign)); } /** * 用私鑰對信息生成數字簽名 * * @param data * 加密數據 * @param privateKey * 私鑰 * * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { // 解密由base64編碼的私鑰 byte[] keyBytes = decryptBASE64(privateKey); // 構造PKCS8EncodedKeySpec對象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取私鑰匙對象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 用私鑰對信息生成數字簽名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); }}甲方構建密鑰對兒,將公鑰公布給乙方,將私鑰保留。 甲方使用私鑰加密數據,然后用私鑰對加密后的數據簽名,發送給乙方簽名以及加密后的數據;乙方使用公鑰、簽名來驗證待解密數據是否有效,如果有效使用公鑰對數據解密。 乙方使用公鑰加密數據,向甲方發送經過加密后的數據;甲方獲得加密數據,通過私鑰解密。 
結果如下 乙方解密甲方的加密數據
甲方解密乙方的數據結果 
簡單總結一下,甲方通過私鑰加密數據給乙方和簽名給乙方,乙方用公鑰驗證,然后可以的話,就公鑰解密。 乙方通過公鑰加密,甲方可以用私鑰解密,其他的不能解密。
新聞熱點
疑難解答