JAVA 中解密RSA算法JS加密實(shí)例詳解
有這樣一個(gè)需求,前端登錄的用戶名密碼,密碼必需加密,但不可使用MD5,因?yàn)楹笈_(tái)要檢測(cè)密碼的復(fù)雜度,那么在保證安全的前提下將密碼傳到后臺(tái)呢,答案就是使用RSA非對(duì)稱加密算法解決 。
java代碼
需要依賴 commons-codec 包
RSACoder.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
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
|
import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; /** * Created by lake on 17-4-12. */ public class RSACoder { 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" ; public static byte [] decryptBASE64(String key) { return Base64.decodeBase64(key); } public static String encryptBASE64( byte [] bytes) { return Base64.encodeBase64String(bytes); } /** * 用私鑰對(duì)信息生成數(shù)字簽名 * * @param data 加密數(shù)據(jù) * @param privateKey 私鑰 * @return * @throws Exception */ public static String sign( byte [] data, String privateKey) throws Exception { // 解密由base64編碼的私鑰 byte [] keyBytes = decryptBASE64(privateKey); // 構(gòu)造PKCS8EncodedKeySpec對(duì)象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取私鑰匙對(duì)象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 用私鑰對(duì)信息生成數(shù)字簽名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); } /** * 校驗(yàn)數(shù)字簽名 * * @param data 加密數(shù)據(jù) * @param publicKey 公鑰 * @param sign 數(shù)字簽名 * @return 校驗(yàn)成功返回true 失敗返回false * @throws Exception */ public static boolean verify( byte [] data, String publicKey, String sign) throws Exception { // 解密由base64編碼的公鑰 byte [] keyBytes = decryptBASE64(publicKey); // 構(gòu)造X509EncodedKeySpec對(duì)象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取公鑰匙對(duì)象 PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); // 驗(yàn)證簽名是否正常 return signature.verify(decryptBASE64(sign)); } public static byte [] decryptByPrivateKey( byte [] data, String key) throws Exception{ // 對(duì)密鑰解密 byte [] keyBytes = decryptBASE64(key); // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對(duì)數(shù)據(jù)解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 解密<br> * 用私鑰解密 * * @param data * @param key * @return * @throws Exception */ public static byte [] decryptByPrivateKey(String data, String key) throws Exception { return decryptByPrivateKey(decryptBASE64(data),key); } /** * 解密<br> * 用公鑰解密 * * @param data * @param key * @return * @throws Exception */ public static byte [] decryptByPublicKey( byte [] data, String key) throws Exception { // 對(duì)密鑰解密 byte [] keyBytes = decryptBASE64(key); // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); // 對(duì)數(shù)據(jù)解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 加密<br> * 用公鑰加密 * * @param data * @param key * @return * @throws Exception */ public static byte [] encryptByPublicKey(String data, String key) throws Exception { // 對(duì)公鑰解密 byte [] keyBytes = decryptBASE64(key); // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); // 對(duì)數(shù)據(jù)加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data.getBytes()); } /** * 加密<br> * 用私鑰加密 * * @param data * @param key * @return * @throws Exception */ public static byte [] encryptByPrivateKey( byte [] data, String key) throws Exception { // 對(duì)密鑰解密 byte [] keyBytes = decryptBASE64(key); // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對(duì)數(shù)據(jù)加密 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, Key> 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, Key> keyMap) throws Exception { Key key = keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); } /** * 初始化密鑰 * * @return * @throws Exception */ public static Map<String, Key> initKey() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator .getInstance(KEY_ALGORITHM); keyPairGen.initialize( 1024 ); KeyPair keyPair = keyPairGen.generateKeyPair(); Map<String, Key> keyMap = new HashMap( 2 ); keyMap.put(PUBLIC_KEY, keyPair.getPublic()); // 公鑰 keyMap.put(PRIVATE_KEY, keyPair.getPrivate()); // 私鑰 return keyMap; } } |
測(cè)試類
RSACoderTest.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
|
import org.junit.Before; import org.junit.Test; import java.security.Key; import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * Created by lake on 17-4-12. */ public class RSACoderTest { private String publicKey; private String privateKey; @Before public void setUp() throws Exception { Map<String, Key> keyMap = RSACoder.initKey(); publicKey = RSACoder.getPublicKey(keyMap); privateKey = RSACoder.getPrivateKey(keyMap); System.err.println( "公鑰: \n\r" + publicKey); System.err.println( "私鑰: \n\r" + privateKey); } @Test public void test() throws Exception { System.err.println( "公鑰加密——私鑰解密" ); String inputStr = "abc" ; byte [] encodedData = RSACoder.encryptByPublicKey(inputStr, publicKey); byte [] decodedData = RSACoder.decryptByPrivateKey(encodedData, privateKey); String outputStr = new String(decodedData); System.err.println( "加密前: " + inputStr + "\n\r" + "解密后: " + outputStr); assertEquals(inputStr, outputStr); } @Test public void testSign() throws Exception { System.err.println( "私鑰加密——公鑰解密" ); String inputStr = "sign" ; byte [] data = inputStr.getBytes(); byte [] encodedData = RSACoder.encryptByPrivateKey(data, privateKey); byte [] decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey); String outputStr = new String(decodedData); System.err.println( "加密前: " + inputStr + "\n\r" + "解密后: " + outputStr); assertEquals(inputStr, outputStr); System.err.println( "私鑰簽名——公鑰驗(yàn)證簽名" ); // 產(chǎn)生簽名 String sign = RSACoder.sign(encodedData, privateKey); System.err.println( "簽名:" + sign); // 驗(yàn)證簽名 boolean status = RSACoder.verify(encodedData, publicKey, sign); System.err.println( "狀態(tài):" + status); assertTrue(status); } } |
前端代碼
依賴 jsencrypt 項(xiàng)目
1
2
3
4
5
6
|
<script src= "bin/jsencrypt.min.js" ></script> <script type= "text/javascript" > var encrypt = new JSEncrypt(); encrypt.setPublicKey( 'java生成的公鑰' ); var encrypted = encrypt.encrypt( '加密的字符串' ); </script> |
說(shuō)明
前端生成加密的字符串encrypted,傳到后臺(tái),java使用私鑰進(jìn)行解密即可。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!