RSA加签解签方法
一、RSA簽名的過程
(1)A生成一對密鑰(公鑰和私鑰),私鑰不公開,A自己保留。公鑰為公開的,任何人可以獲取。
(2)A用自己的私鑰對消息加簽,形成簽名,并將加簽的消息和消息本身一起傳遞給B。
(3)B收到消息后,在獲取A的公鑰進行驗簽,如果驗簽出來的內容與消息本身一致,證明消息是A回復的。
在這個過程中,只有2次傳遞過程,第一次是A傳遞加簽的消息和消息本身給B,第二次是B獲取A的公鑰,即使都被敵方截獲,也沒有危險性,因為只有A的私鑰才能對消息進行簽名,即使知道了消息內容,也無法偽造帶簽名的回復給B,防止了消息內容的篡改。
二、具體使用方法
1.通過RSA秘鑰生成工具生成一對公鑰和私鑰
?
2.定義加密解密和加簽驗簽方法名
//加密解密算法 private static final String ALGORITHM_RSA = "RSA"; ? //加簽驗簽算法 private static final String ALGORITHM_SHA1WITHRSA = "SHA1withRSA"; ? private static final String CHARSET = "UTF-8";?
3.加密解密方法
(1)初始化公鑰私鑰
/*** 初始化公鑰私鑰,將公鑰私鑰放入map中* @return* @throws NoSuchAlgorithmException*/ public static Map<String, Object> initKey() throws NoSuchAlgorithmException {//獲得對象 KeyPairGenerator 參數 RSA 1024個字節KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_RSA);keyPairGenerator.initialize(1024);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();//將公私鑰對象存入map中,PUBLIC_KEY和PRIVATE_KEY為你自動生成的公私鑰Map<String, Object> keyMap = new HashMap<>(2);keyMap.put(PUBLIC_KEY,rsaPublicKey);keyMap.put(PRIVATE_KEY,rsaPrivateKey);return keyMap; }(2)獲取規范公鑰和規范私鑰
public static String getPublicKey(Map<String, Object> keyMap) throws Exception {Key key = (Key) keyMap.get(PUBLIC_KEY);return Base64.encodeBase64String(key.getEncoded()); } ? /*** 將原始私鑰進行處理,獲取規范私鑰* @param keyMap* @return 返回規范私鑰* @throws Exception*/ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {Key key = (Key) keyMap.get(PRIVATE_KEY); ?return Base64.encodeBase64String(key.getEncoded()); }(3)鍵值對轉換成url方法
加簽過程中需要通過formatSignContent()函數進行格斯轉換,將鍵值對格式轉換為url參數格式
/*** 格式轉換,將map中鍵值對轉換為url參數格式* @param params 傳遞參數的鍵值對,用map保存* @return 參數的url表示方法,例如:key1=111&key2=222*/ private static String formatSignContent(Map<String, String> params) {//利用TreeMap將鍵值對排序Map<String, String> sortedParams = new TreeMap<String, String>();sortedParams.putAll(params);StringBuilder content = new StringBuilder();int index = 0;for (Object key : sortedParams.keySet()){Object value = sortedParams.get(key.toString());if (value != null && StringUtils.isNotBlank(value.toString())) {content.append(index == 0 ? "" : "&").append(key).append("=").append(value);index++;}}return content.toString(); }(4)加簽方法
A通過自己的私鑰對原始數據進行加簽,生成加簽數據sign,期間需要格式轉換
/*** RSA加簽方法* @param paramsMap 原始數據鍵值對格式* @param privateKey 私鑰* @return 返回加簽數據* @throws Exception*/ private static String signWithRSA(Map<String,String> paramsMap, String privateKey) throws Exception {//將Map鍵值對轉換為url參數格式String content = formatSignContent(paramsMap);//指定加簽算法Signature signature = Signature.getInstance(ALGORITHM_SHA1WITHRSA);signature.initSign(getPrivateKey(privateKey));signature.update(content.getBytes("utf-8"));byte[] signed = signature.sign();return Base64.encodeBase64String(signed); }(5)驗簽方法
B通過A的公鑰和加簽數據sign以及傳遞的參數map進行解簽
/*** RSA驗簽方法* 將傳遞的Map鍵值對轉換為url參數形式* @param paramsMap 傳遞過來的鍵值對* @param publicKey 規范公鑰* @param sign 加簽后的數據* @return 驗簽結果* @throws Exception*/ private static boolean checkSignWithRSA(Map<String,String> paramsMap, String publicKey, String sign) throws Exception {String content = formatSignContent(paramsMap);Signature signature = Signature.getInstance("SHA1WithRSA");signature.initVerify(getPublicKey(publicKey));signature.update(content.getBytes("utf-8"));return signature.verify(Base64.decodeBase64(sign)); }(6)實際使用示例
/**驗證加簽驗簽流程* 1.A通過自己的私鑰對原數據map進行加簽,加簽后的數據sign* 2.A將加簽數據sign和原始數據map發送給另外一方B* 3.B通過加簽數據sign和傳遞過來的數據map進行通過A的公鑰進行解簽* RSA加簽驗簽方法* @return 是否正確* @throws Exception*/ public static boolean verifySingCheck() throws Exception {Map<String, Object> keyMap = initKey();//得到原始公鑰、私鑰存儲的mapString publicKey = getPublicKey(keyMap);//獲取規范公鑰String privateKey = getPrivateKey(keyMap);//獲取規范私鑰 ?Map<String,String> map = new HashMap<>();map.put("key1","111");map.put("key2","222"); ?//傳遞過程發生了改變Map<String,String> map2 = new HashMap<>();map2.put("key1","111222");map2.put("key2","222"); ?String sign = signWithRSA(map,privateKey);boolean check = checkSignWithRSA(map,publicKey,sign);//boolean check = checkSignWithRSA(map2,publicKey,sign);//傳遞過程發生了改變System.out.println("簽名結果,sign:"+sign);System.out.println("驗簽結果,result:"+check);return check; }總結
- 上一篇: sharding jdbc根据年月分表
- 下一篇: shiro框架采取MD5+salt方式加