非對稱加密算法 RSA過程 : 以甲乙雙方爲例
1、初始化密鑰 構建密鑰對,生成公鑰、私鑰保存到keymap中
KeyPairGenerator ---> KeyPair --> RSAPublicKey、RSAPrivateKey
2、甲方使用私鑰加密, 加密後在用私鑰對加密數據進行數據簽名,然後發送給乙方
RSACoder.encryptByPrivateKey(data, privateKey);
RSACoder.sign(encodedData, privateKey);
3、乙方則通過公鑰驗證簽名的加密數據,如果驗證正確則在通過公鑰對加密數據進行解密
RSACoder.verify(encodedData, publicKey, sign);
RSACoder.decryptByPublicKey(encodedData, publicKey);
4、乙方在通過公鑰加密發送給甲方
RSACoder.encryptByPublicKey(decodedData, publicKey);
5、甲方通過私鑰解密該數據
RSACoder.decryptPrivateKey(encodedData, privateKey);
流程圖如下:
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
package com.bank.utils; import java.security.MessageDigest; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public abstract class Coder
{ public static final String
KEY_SHA = "SHA" ; public static final String
KEY_MD5 = "MD5" ; /** *
MAC算法可選以下多種算法 * *
<pre> *
HmacMD5 *
HmacSHA1 *
HmacSHA256 *
HmacSHA384 *
HmacSHA512 *
</pre> */ public static final String
KEY_MAC = "HmacMD5" ; /** *
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(); } /** *
初始化HMAC密鑰 * *
@return *
@throws Exception */ public static String
initMacKey() throws Exception{ KeyGenerator
keyGenerator = KeyGenerator.getInstance(KEY_MAC); SecretKey
secretKey = keyGenerator.generateKey(); return encryptBASE64(secretKey.getEncoded()); } /** *
HMAC 加密 *
@param data *
@param key *
@return *
@throws Exception */ public static byte []
encryptHMAC( byte []
data, String key) throws Exception{ SecretKey
secretKey = new SecretKeySpec(decryptBASE64(key),
KEY_MAC); Mac
mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); return mac.doFinal(data); } } |
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
package com.bank.utils; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; public abstract class RSACoder extends Coder{ public static final String
KEY_ALGORITHM = "RSA" ; public static final String
SIGNATURE_ALGORITHM = "MD5withRSA" ; private static final String
PUBLIC_KEY = "RSAPublicKey" ; private static final String
PRIVATE_KEY = "RSAPrivatekey" ; /** *
用私鑰對信息生成數字簽名 *
@param data 加密數據 *
@param privateKey 私鑰 *
@return *
@throws Exception */ public static String
sign( byte []
data, String privateKey) throws Exception
{ //解密由base64編碼的私鑰 byte []
keyBytes = decryptBASE64(privateKey); PKCS8EncodedKeySpec
pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //取私鑰對象 PrivateKey
pKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //用私鑰生成數字簽名 Signature
signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(pKey); signature.update(data); return encryptBASE64(signature.sign()); } /** *
校驗數字簽名 *
@param data 加密數據 *
@param publicKey 公鑰 *
@param sign 數字簽名 *
@return *
@throws Exception */ public static boolean verify( byte []
data, String publicKey, String sign) throws Exception{ //解密有base64編碼的公鑰 byte []
keyBytes = decryptBASE64(publicKey); X509EncodedKeySpec
keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //取公鑰對象 PublicKey
pKey = keyFactory.generatePublic(keySpec); Signature
signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pKey); signature.update(data); //驗證簽名是否正常 return signature.verify(decryptBASE64(sign)); } /** *
解密 *
用私鑰解密 *
@param data 加密數據 *
@param key *
@return *
@throws Exception */ public static byte []
decryptPrivateKey( byte []
data, String key) throws Exception{ byte []
keyBytes = decryptBASE64(key); //取得私鑰 PKCS8EncodedKeySpec
encodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory
factory = KeyFactory.getInstance(KEY_ALGORITHM); Key
pKey = factory.generatePrivate(encodedKeySpec); //對數據解密 Cipher
cipher = Cipher.getInstance(factory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE,
pKey); 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
keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key
pKey = keyFactory.generatePublic(keySpec); //對數據解密 Cipher
cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE,
pKey); 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
keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key
pKey = keyFactory.generatePublic(keySpec); Cipher
cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE,
pKey); return cipher.doFinal(data); } /** *
用私鑰加密 *
@param data *
@param key *
@return *
@throws Exception */ public static byte []
encryptByPrivateKey( byte []
data, String key) throws Exception{ byte []
keyBytes = decryptBASE64(key); PKCS8EncodedKeySpec
keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key
privateKey = keyFactory.generatePrivate(keySpec); Cipher
cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE,
privateKey); return cipher.doFinal(data); } /** *
取得私鑰 *
@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()); } /** *
取得公鑰 *
@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()); } /** *
初始化密鑰 *
@return *
@throws Exception */ public static Map<String,
Object> initKey() throws Exception{ KeyPairGenerator
keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); 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(PRIVATE_KEY,
privateKey); keyMap.put(PUBLIC_KEY,
publicKey); return keyMap; } } |
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package com.bank.test; import java.util.Map; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.bank.utils.RSACoder; public class RSACoderTest
{ private String
publicKey; private String
privateKey; /* *
非對稱加密算法 RSA過程 : 以甲乙雙方爲例 *
1、初始化密鑰 構建密鑰對,生成公鑰、私鑰保存到keymap中 *
KeyPairGenerator ---> KeyPair --> RSAPublicKey、RSAPrivateKey *
2、甲方使用私鑰加密, 加密後在用私鑰對加密數據進行數據簽名,然後發送給乙方 *
RSACoder.encryptByPrivateKey(data, privateKey); *
RSACoder.sign(encodedData, privateKey); *
3、乙方則通過公鑰驗證簽名的加密數據,如果驗證正確則在通過公鑰對加密數據進行解密 *
RSACoder.verify(encodedData, publicKey, sign); *
RSACoder.decryptByPublicKey(encodedData, publicKey); * *
4、乙方在通過公鑰加密發送給甲方 *
RSACoder.encryptByPublicKey(decodedData, publicKey); *
5、甲方通過私鑰解密該數據 *
RSACoder.decryptPrivateKey(encodedData, privateKey); */ @Before public void setUp() throws Exception
{ Map<String
, Object> keyMap = RSACoder.initKey(); publicKey
= RSACoder.getPublicKey(keyMap); privateKey
= RSACoder.getPrivateKey(keyMap); System.out.println( "公鑰:\n" +
publicKey); System.out.println( "私鑰:\n" +
privateKey); } @Test public void test() throws Exception{ String
inputStr = "abc" ; byte []
data = inputStr.getBytes(); //每次的得到的字節數組是不一樣的。 //第二步
私鑰加密 byte []
encodedData = RSACoder.encryptByPrivateKey(data, privateKey); //私鑰進行數據簽名 String
sign = RSACoder.sign(encodedData, privateKey); //第三步
公鑰驗證數字簽名 boolean flag
= RSACoder.verify(encodedData, publicKey, sign); System.out.println( "flag:" +
flag); //用公鑰對數據解密 byte []
decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey); System.out.println( "data:" +
data + "加密數據:" +
encodedData + "
解密數據:" +
decodedData); System.out.println( "加密前數據-:" + new String(data)
+ "
解密後數據: " + new String(decodedData)); //第四步使用公鑰加密數據 encodedData
= RSACoder.encryptByPublicKey(decodedData, publicKey); //第五步
使用私鑰解密數據 decodedData
= RSACoder.decryptPrivateKey(encodedData, privateKey); System.out.println( "data:" +
data + "加密數據:" +
encodedData + "
解密數據:" +
decodedData); System.out.println( "加密前數據:" +
inputStr + "
解密後數據: " + new String(decodedData)); } @Test public void test1() throws Exception{ System.out.println( "私鑰加密-----公鑰解密" ); String
inputStr = "abc" ; byte []
data = inputStr.getBytes(); System.out.println( "data:" +
data); byte []
encodedData = RSACoder.encryptByPrivateKey(data, privateKey); byte []
decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey); String
outputStr = new String(
decodedData ); System.out.println( "加密前:" +
inputStr + "\n
解密後:" +
outputStr); Assert.assertEquals(inputStr,
outputStr); System.out.println( "私鑰簽名---公鑰驗證簽名" ); //產生簽名 String
sign = RSACoder.sign(encodedData, privateKey); System.out.println( "簽名:\r" +
sign); //驗證簽名 boolean flag
= RSACoder.verify(encodedData, publicKey, sign); System.out.println( "狀態:\r" +
flag); Assert.assertTrue(flag); } } |