RSA加密解密及數字簽名Java實現
RSA公鑰加密演算法是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。
RSA是目前最有影響力的公鑰加密演算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊,已被ISO推薦為公鑰資料加密演算法。
RSA演算法是一種非對稱密碼演算法,所謂非對稱,就是指該演算法需要一對金鑰,使用其中一個加密,則需要用另一個才能解密。
關於RSA演算法的原理,這裡就不再詳加介紹,網上各種資源一大堆。下面就開始介紹RSA加密解密JAVA類的具體實現。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
import java.security.MessageDigest;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class Coder {
public static final String KEY_SHA= "SHA" ;
public static final String KEY_MD5= "MD5" ;
/**
* BASE64解密
* @param key
* @return
* @throws Exception
*/
public static byte [] decryptBASE64(String key) throws Exception{
return ( new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64( byte [] key) throws Exception{
return ( new BASE64Encoder()).encodeBuffer(key);
}
/**
* MD5加密
* @param data
* @return
* @throws Exception
*/
public static byte [] encryptMD5( byte [] data) throws Exception{
MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
md5.update(data);
return md5.digest();
}
/**
* SHA加密
* @param data
* @return
* @throws Exception
*/
public static byte [] encryptSHA( byte [] data) throws Exception{
MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
sha.update(data);
return sha.digest();
}
}
|
先提供Coder編碼類,該類封裝了基本的Base64、md5和SHA加密解密演算法。Java對這些演算法的實現提供了很好的API封裝,開發人員只需呼叫這些API就可很簡單方便的實現資料的加密與解密。
下面提供RSA加密解密類,該類為Coder類子類,因為其中對RSA公私金鑰的儲存進行了一層Base64加密處理。
RSA加密解密類靜態常量
1
2
3
4
5
|
public static final String KEY_ALGORTHM= "RSA" ; //
public static final String SIGNATURE_ALGORITHM= "MD5withRSA" ;
public static final String PUBLIC_KEY = "RSAPublicKey" ; //公鑰
public static final String PRIVATE_KEY = "RSAPrivateKey" ; //私鑰
|
RSA加密解密的實現,需要有一對公私金鑰,公私金鑰的初始化如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* 初始化金鑰
* @return
* @throws Exception
*/
public static Map<String,Object> initKey() throws Exception{
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
keyPairGenerator.initialize( 1024 );
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//公鑰
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
//私鑰
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String,Object> keyMap = new HashMap<String, Object>( 2 );
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
|
從程式碼中可以看出金鑰的初始化長度為1024位,金鑰的長度越長,安全性就越好,但是加密解密所用的時間就會越多。而一次能加密的密文長度也與金鑰的長度成正比。一次能加密的密文長度為:金鑰的長度/8-11。所以1024bit長度的金鑰一次可以加密的密文為1024/8-11=117bit。所以非對稱加密一般都用於加密對稱加密演算法的金鑰,而不是直接加密內容。對於小檔案可以使用RSA加密,但加密過程仍可能會使用分段加密。
從map中獲取公鑰、私鑰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* 取得公鑰,並轉化為String型別
* @param keyMap
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap) throws Exception{
Key key = (Key) keyMap.get(PUBLIC_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 取得私鑰,並轉化為String型別
* @param keyMap
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
Key key = (Key) keyMap.get(PRIVATE_KEY);
return encryptBASE64(key.getEncoded());
}
|
對於RSA產生的公鑰、私鑰,我們可以有兩種方式可以對資訊進行加密解密。私鑰加密-公鑰解密 和 公鑰加密-私鑰解密。
私鑰加密
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* 用私鑰加密
* @param data 加密資料
* @param key 金鑰
* @return
* @throws Exception
*/
public static byte [] encryptByPrivateKey( byte [] data,String key) throws Exception{
//解密金鑰
byte [] keyBytes = decryptBASE64(key);
//取私鑰
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//對資料加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
|
私鑰解密
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/**
* 用私鑰解密<span style="color:#000000;"></span> * @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 keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//對資料解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* 用公鑰加密
* @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 keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//對資料解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/**
* 用公鑰解密
* @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 keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//對資料解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
|
關於數字簽名,先了解下何為數字簽名。數字簽名,就是隻有資訊的傳送者才能產生的別人無法偽造的一段數字串,這段數字串同時也是對資訊的傳送者傳送資訊真實性的一個有效證明。數字簽名是非對稱金鑰加密技術與數字摘要技術的應用。簡單地說,所謂數字簽名就是附加在資料單元上的一些資料,或是對資料單元所作的密碼變換。這種資料或變換允許資料單元的接收者用以確認資料單元的來源和資料單元的完整性並保護資料,防止被人(例如接收者)進行偽造。
數字簽名的主要功能如下:
保證資訊傳輸的完整性、傳送者的身份認證、防止交易中的抵賴發生。
數字簽名技術是將摘要資訊用傳送者的私鑰加密,與原文一起傳送給接收者。接收者只有用傳送者的公鑰才能解密被加密的摘要資訊,然後用對收到的原文產生一個摘要資訊,與解密的摘要資訊對比。如果相同,則說明收到的資訊是完整的,在傳輸過程中沒有被修改,否則說明資訊被修改過,因此數字簽名能夠驗證資訊的完整性。
數字簽名是個加密的過程,數字簽名驗證是個解密的過程。
3.驗證演算法。
通過RSA加密解密演算法,我們可以實現數字簽名的功能。我們可以用私鑰對資訊生成數字簽名,再用公鑰來校驗數字簽名,當然也可以反過來公鑰簽名,私鑰校驗。
私鑰簽名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/**
* 用私鑰對資訊生成數字簽名
* @param data //加密資料
* @param privateKey //私鑰
* @return
* @throws Exception
*/
public static String sign( byte [] data,String privateKey) throws Exception{
//解密私鑰
byte [] keyBytes = decryptBASE64(privateKey);
//構造PKCS8EncodedKeySpec物件
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
//指定加密演算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
//取私鑰匙物件
PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//用私鑰對資訊生成數字簽名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey2);
signature.update(data);
return encryptBASE64(signature.sign());
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/**
* 校驗數字簽名
* @param data 加密資料
* @param publicKey 公鑰
* @param sign 數字簽名
* @return
* @throws Exception
*/
public static boolean verify( byte [] data,String publicKey,String sign) throws Exception{
//解密公鑰
byte [] keyBytes = decryptBASE64(publicKey);
//構造X509EncodedKeySpec物件
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
//指定加密演算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
//取公鑰匙物件
PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey2);
signature.update(data);
//驗證簽名是否正常
return signature.verify(decryptBASE64(sign));
}
|
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/195110/viewspace-1814611/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- java使用RSA加密方式,實現數字簽名Java加密
- python實現aes加密解密,RSA簽名和驗籤,RSA加密解密,並呼叫介面Python加密解密
- 深入理解加密、解密、數字簽名和數字證書加密解密
- 安全基礎:數字信封、數字簽名、數字證書(加簽驗籤,加密解密)加密解密
- 加密與數字簽名加密
- 前後端java+vue 實現rsa 加解密與摘要簽名演算法後端JavaVue解密演算法
- Java安全之對稱加密、非對稱加密、數字簽名Java加密
- JAVA加解密19-數字簽名演算法DSAJava解密演算法
- 對稱加密、非對稱加密、RSA、訊息摘要、數字簽名、數字證書與HTTPS簡介加密HTTP
- 數字簽名(java) (轉)Java
- java/php/c#版rsa簽名以及java驗籤實現JavaPHPC#
- RSA加密解密(無資料大小限制,php、go、java互通實現)加密解密PHPGoJava
- 在VUE中使用RSA加密解密加簽解籤Vue加密解密
- Android 安全加密:數字簽名和數字證書Android加密
- Android安全加密:數字簽名和數字證書Android加密
- RSA加密與解密加密解密
- 一篇搞定RSA加密與SHA簽名|與Java完全同步加密Java
- 數字簽名
- 公鑰加密、數字簽名、訊息認證加密
- php rsa長文加密解密PHP加密解密
- 非對稱加密中,加解密和簽名加密解密
- Java 新增、驗證PDF 數字簽名Java
- 數字簽名原理
- Java 操作PPT數字簽名(一):新增、檢測、刪除簽名Java
- Java 新增數字簽名到Excel以及檢測、刪除簽名JavaExcel
- java RSA 解密Java解密
- RSA 非對稱加密&解密加密解密
- ActiveX控制元件數字簽名實踐(免費簽名)控制元件
- security.js RSA加密與java客戶端解密JS加密Java客戶端解密
- 詳解數字簽名的含義及作用
- 大話數字簽名
- Elgamal數字簽名原理GAM
- 加密、解密詳解及CA的實現加密解密
- PAT1048數字加密(java實現)加密Java
- 微信訊息體簽名及加解密功能詳細解析以及.net實現解密
- RSA加密解密示例程式碼加密解密
- Java 獲取PDF數字簽名證照資訊Java
- 使用Java加密與解密實現步驟Java加密解密