生活随笔
收集整理的這篇文章主要介紹了
RSA加密解密及数字签名Java实现--转
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
RSA公鑰加密算法是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。
? ??RSA是目前最有影響力的公鑰加密算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊,已被ISO推薦為公鑰數據加密算法。
????RSA算法是一種非對稱密碼算法,所謂非對稱,就是指該算法需要一對密鑰,使用其中一個加密,則需要用另一個才能解密。
? ? 關于RSA算法的原理,這里就不再詳加介紹,網上各種資源一大堆。下面就開始介紹RSA加密解密JAVA類的具體實現。
?
| 01 | import?java.security.MessageDigest; |
| 03 | import?sun.misc.BASE64Decoder; |
| 04 | import?sun.misc.BASE64Encoder; |
| 08 | ????public?static?final?String KEY_SHA="SHA"; |
| 09 | ????public?static?final?String KEY_MD5="MD5"; |
| 15 | ?????* @throws Exception |
| 17 | ????public?static?byte[] decryptBASE64(String key)?throws?Exception{ |
| 18 | ????????return?(new?BASE64Decoder()).decodeBuffer(key); |
| 25 | ?????* @throws Exception |
| 27 | ????public?static?String encryptBASE64(byte[] key)throws?Exception{ |
| 28 | ????????return?(new?BASE64Encoder()).encodeBuffer(key); |
| 35 | ?????* @throws Exception |
| 37 | ????public?static?byte[] encryptMD5(byte[] data)throws?Exception{ |
| 38 | ????????MessageDigest md5 = MessageDigest.getInstance(KEY_MD5); |
| 39 | ????????md5.update(data); |
| 40 | ????????return?md5.digest(); |
| 47 | ?????* @throws Exception |
| 49 | ????public?static?byte[] encryptSHA(byte[] data)throws?Exception{ |
| 50 | ????????MessageDigest sha = MessageDigest.getInstance(KEY_SHA); |
| 51 | ????????sha.update(data); |
| 52 | ????????return?sha.digest(); |
?????先提供Coder編碼類,該類封裝了基本的Base64、md5和SHA加密解密算法。Java對這些算法的實現提供了很好的API封裝,開發人員只需調用這些API就可很簡單方便的實現數據的加密與解密。
? ? 下面提供RSA加密解密類,該類為Coder類子類,因為其中對RSA公私密鑰的保存進行了一層Base64加密處理。
????RSA加密解密類靜態常量
?
| 1 | ???public?static?final?String KEY_ALGORTHM="RSA";// |
| 2 | public?static?final?String SIGNATURE_ALGORITHM="MD5withRSA"; |
| 4 | public?static?final?String PUBLIC_KEY =?"RSAPublicKey";//公鑰 |
| 5 | public?static?final?String PRIVATE_KEY =?"RSAPrivateKey";//私鑰 |
?
????RSA加密解密的實現,需要有一對公私密鑰,公私密鑰的初始化如下:
?
| 04 | ?????* @throws Exception |
| 06 | ????public?static?Map<String,Object> initKey()throws?Exception{ |
| 07 | ????????KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM); |
| 08 | ????????keyPairGenerator.initialize(1024); |
| 09 | ????????KeyPair keyPair = keyPairGenerator.generateKeyPair(); |
| 12 | ????????RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); |
| 14 | ????????RSAPrivateKey privateKey =? (RSAPrivateKey) keyPair.getPrivate(); |
| 16 | ????????Map<String,Object> keyMap =?new?HashMap<String, Object>(2); |
| 17 | ????????keyMap.put(PUBLIC_KEY, publicKey); |
| 18 | ????????keyMap.put(PRIVATE_KEY, privateKey); |
? ? ??從代碼中可以看出密鑰的初始化長度為1024位,密鑰的長度越長,安全性就越好,但是加密解密所用的時間就會越多。而一次能加密的密文長度也與密鑰的長度成正比。一次能加密的密文長度為:密鑰的長度/8-11。所以1024bit長度的密鑰一次可以加密的密文為1024/8-11=117bit。所以非對稱加密一般都用于加密對稱加密算法的密鑰,而不是直接加密內容。對于小文件可以使用RSA加密,但加密過程仍可能會使用分段加密。
? ? 從map中獲取公鑰、私鑰
?
| 02 | ?????* 取得公鑰,并轉化為String類型 |
| 05 | ?????* @throws Exception |
| 07 | ????public?static?String getPublicKey(Map<String, Object> keyMap)throws?Exception{ |
| 08 | ????????Key key = (Key) keyMap.get(PUBLIC_KEY);? |
| 09 | ????????return?encryptBASE64(key.getEncoded());???? |
| 13 | ?????* 取得私鑰,并轉化為String類型 |
| 16 | ?????* @throws Exception |
| 18 | ????public?static?String getPrivateKey(Map<String, Object> keyMap)?throws?Exception{ |
| 19 | ????????Key key = (Key) keyMap.get(PRIVATE_KEY);? |
| 20 | ????????return?encryptBASE64(key.getEncoded());???? |
? ? 對于RSA產生的公鑰、私鑰,我們可以有兩種方式可以對信息進行加密解密。私鑰加密-公鑰解密 和 公鑰加密-私鑰解密。
? ??私鑰加密
?
| 03 | ?????* @param data? 加密數據 |
| 06 | ?????* @throws Exception |
| 08 | ????public?static?byte[] encryptByPrivateKey(byte[] data,String key)throws?Exception{ |
| 10 | ????????byte[] keyBytes = decryptBASE64(key); |
| 12 | ????????PKCS8EncodedKeySpec pkcs8EncodedKeySpec =?new?PKCS8EncodedKeySpec(keyBytes); |
| 13 | ????????KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
| 14 | ????????Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); |
| 17 | ????????Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
| 18 | ????????cipher.init(Cipher.ENCRYPT_MODE, privateKey); |
| 20 | ????????return?cipher.doFinal(data); |
????私鑰解密
?
| 02 | ?????* 用私鑰解密<span style="color:#000000;"></span> * @param data? 加密數據 |
| 05 | ?????* @throws Exception |
| 07 | ????public?static?byte[] decryptByPrivateKey(byte[] data,String key)throws?Exception{ |
| 09 | ????????byte[] keyBytes = decryptBASE64(key); |
| 11 | ????????PKCS8EncodedKeySpec pkcs8EncodedKeySpec =?new?PKCS8EncodedKeySpec(keyBytes); |
| 12 | ????????KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
| 13 | ????????Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); |
| 15 | ????????Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
| 16 | ????????cipher.init(Cipher.DECRYPT_MODE, privateKey); |
| 18 | ????????return?cipher.doFinal(data); |
? ??公鑰加密
| 03 | ?????* @param data? 加密數據 |
| 06 | ?????* @throws Exception |
| 08 | ????public?static?byte[] encryptByPublicKey(byte[] data,String key)throws?Exception{ |
| 10 | ????????byte[] keyBytes = decryptBASE64(key); |
| 12 | ????????X509EncodedKeySpec x509EncodedKeySpec =?new?X509EncodedKeySpec(keyBytes); |
| 13 | ????????KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
| 14 | ????????Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); |
| 17 | ????????Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
| 18 | ????????cipher.init(Cipher.ENCRYPT_MODE, publicKey); |
| 20 | ????????return?cipher.doFinal(data); |
????私鑰加密
| 03 | ?????* @param data? 加密數據 |
| 06 | ?????* @throws Exception |
| 08 | ????public?static?byte[] decryptByPublicKey(byte[] data,String key)throws?Exception{ |
| 10 | ????????byte[] keyBytes = decryptBASE64(key); |
| 11 | ????????X509EncodedKeySpec x509EncodedKeySpec =?new?X509EncodedKeySpec(keyBytes); |
| 12 | ????????KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
| 13 | ????????Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); |
| 16 | ????????Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
| 17 | ????????cipher.init(Cipher.DECRYPT_MODE, publicKey); |
| 19 | ????????return?cipher.doFinal(data); |
? ??關于數字簽名,先了解下何為數字簽名。數字簽名,就是只有信息的發送者才能產生的別人無法偽造的一段數字串,這段數字串同時也是對信息的發送者發送信息真實性的一個有效證明。數字簽名是非對稱密鑰加密技術與數字摘要技術的應用。簡單地說,所謂數字簽名就是附加在數據單元上的一些數據,或是對數據單元所作的密碼變換。這種數據或變換允許數據單元的接收者用以確認數據單元的來源和數據單元的完整性并保護數據,防止被人(例如接收者)進行偽造。
? ? 數字簽名的主要功能如下:
?
????保證信息傳輸的完整性、發送者的身份認證、防止交易中的抵賴發生。
????數字簽名技術是將摘要信息用發送者的私鑰加密,與原文一起傳送給接收者。接收者只有用發送者的公鑰才能解密被加密的摘要信息,然后用對收到的原文產生一個摘要信息,與解密的摘要信息對比。如果相同,則說明收到的信息是完整的,在傳輸過程中沒有被修改,否則說明信息被修改過,因此數字簽名能夠驗證信息的完整性。
????數字簽名是個加密的過程,數字簽名驗證是個解密的過程。
數字簽名算法依靠公鑰加密技術來實現的。在公鑰加密技術里,每一個使用者有一對密鑰:一把公鑰和一把私鑰。公鑰可以自由發布,但私鑰則秘密保存;還有一個要求就是要讓通過公鑰推算出私鑰的做法不可能實現。 普通的數字簽名算法包括三種算法: 1.密碼生成算法; 2.標記算法;
???3.驗證算法。
? ??通過RSA加密解密算法,我們可以實現數字簽名的功能。我們可以用私鑰對信息生成數字簽名,再用公鑰來校驗數字簽名,當然也可以反過來公鑰簽名,私鑰校驗。
? ??私鑰簽名
?
| 03 | ?????* @param data? //加密數據 |
| 04 | ?????* @param privateKey??? //私鑰 |
| 06 | ?????* @throws Exception |
| 08 | ????public?static?String sign(byte[] data,String privateKey)throws?Exception{ |
| 10 | ????????byte[] keyBytes = decryptBASE64(privateKey); |
| 11 | ????????//構造PKCS8EncodedKeySpec對象 |
| 12 | ????????PKCS8EncodedKeySpec pkcs8EncodedKeySpec =?new?PKCS8EncodedKeySpec(keyBytes); |
| 14 | ????????KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
| 16 | ????????PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec); |
| 18 | ????????Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); |
| 19 | ????????signature.initSign(privateKey2); |
| 20 | ????????signature.update(data); |
| 22 | ????????return?encryptBASE64(signature.sign()); |
??? 公鑰校驗?
?
?
| 03 | ?????* @param data? 加密數據 |
| 04 | ?????* @param publicKey 公鑰 |
| 05 | ?????* @param sign? 數字簽名 |
| 07 | ?????* @throws Exception |
| 09 | ????public?static?boolean?verify(byte[] data,String publicKey,String sign)throws?Exception{ |
| 11 | ????????byte[] keyBytes = decryptBASE64(publicKey); |
| 12 | ????????//構造X509EncodedKeySpec對象 |
| 13 | ????????X509EncodedKeySpec x509EncodedKeySpec =?new?X509EncodedKeySpec(keyBytes); |
| 15 | ????????KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
| 17 | ????????PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec); |
| 19 | ????????Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); |
| 20 | ????????signature.initVerify(publicKey2); |
| 21 | ????????signature.update(data); |
| 23 | ????????return?signature.verify(decryptBASE64(sign)); |
? ? ???對于RSA如何加密文件、圖片等信息,加密的信息又如何保存,怎樣保存解密后的信息,以及操作過程中遇到的錯誤將如何處理,將在后面的文章中介紹給大家。? 原文:http://www.360doc.com/content/14/0324/16/834950_363341045.shtml
轉載于:https://www.cnblogs.com/davidwang456/p/3922528.html
總結
以上是生活随笔為你收集整理的RSA加密解密及数字签名Java实现--转的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。