rsa前段加密
准备工作:其实鄙人也没那么强啦,第三方包是必须的
bcprov-jdk15on-148.jar
commons-codec-1.7.jar
commons-lang-2.4.jar
log4j-1.2.15.jar
slf4j-api-1.6.1.jar
//关键工具类
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
|
package
com.web.utils;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileOutputStream;
import
java.io.ObjectInputStream;
import
java.io.ObjectOutputStream;
import
java.math.BigInteger;
import
java.security.KeyPair;
import
java.security.KeyFactory;
import
java.security.KeyPairGenerator;
import
java.security.Provider;
import
java.security.PublicKey;
import
java.security.PrivateKey;
import
java.security.SecureRandom;
import
java.security.NoSuchAlgorithmException;
import
java.security.InvalidParameterException;
import
java.security.interfaces.RSAPublicKey;
import
java.security.interfaces.RSAPrivateKey;
import
java.security.spec.RSAPublicKeySpec;
import
java.security.spec.RSAPrivateKeySpec;
import
java.security.spec.InvalidKeySpecException;
import
java.util.Date;
import
javax.crypto.Cipher;
import
org.apache.commons.io.IOUtils;
import
org.apache.commons.io.FileUtils;
import
org.apache.commons.codec.DecoderException;
import
org.apache.commons.codec.binary.Hex;
import
org.bouncycastle.jce.provider.BouncyCastleProvider;
import
org.slf4j.Logger;
import
org.slf4j.LoggerFactory;
import
org.apache.commons.lang.StringUtils;
import
org.apache.commons.lang.time.DateFormatUtils;
/**
* RSA算法加密/解密工具类。
*
* @author fuchun
* @version 1.0.0, 2010-05-05
*/
public
abstract
class
RSAUtils {
private
static
final
Logger LOGGER = LoggerFactory.getLogger(RSAUtils.
class
);
/** 算法名称 */
private
static
final
String ALGORITHOM =
"RSA"
;
/**保存生成的密钥对的文件名称。 */
private
static
final
String RSA_PAIR_FILENAME =
"/__RSA_PAIR.txt"
;
/** 密钥大小 */
private
static
final
int
KEY_SIZE =
1024
;
/** 默认的安全服务提供者 */
private
static
final
Provider DEFAULT_PROVIDER =
new
BouncyCastleProvider();
private
static
KeyPairGenerator keyPairGen =
null
;
private
static
KeyFactory keyFactory =
null
;
/** 缓存的密钥对。 */
private
static
KeyPair oneKeyPair =
null
;
private
static
File rsaPairFile =
null
;
static
{
try
{
keyPairGen = KeyPairGenerator.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
keyFactory = KeyFactory.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
}
catch
(NoSuchAlgorithmException ex) {
LOGGER.error(ex.getMessage());
}
rsaPairFile =
new
File(getRSAPairFilePath());
}
private
RSAUtils() {
}
/**
* 生成并返回RSA密钥对。
*/
private
static
synchronized
KeyPair generateKeyPair() {
try
{
keyPairGen.initialize(KEY_SIZE,
new
SecureRandom(DateFormatUtils.format(
new
Date(),
"yyyyMMdd"
).getBytes()));
oneKeyPair = keyPairGen.generateKeyPair();
saveKeyPair(oneKeyPair);
return
oneKeyPair;
}
catch
(InvalidParameterException ex) {
LOGGER.error(
"KeyPairGenerator does not support a key length of "
+ KEY_SIZE +
"."
, ex);
}
catch
(NullPointerException ex) {
LOGGER.error(
"RSAUtils#KEY_PAIR_GEN is null, can not generate KeyPairGenerator instance."
,
ex);
}
return
null
;
}
/**
* 返回生成/读取的密钥对文件的路径。
*/
private
static
String getRSAPairFilePath() {
String urlPath = RSAUtils.
class
.getResource(
"/"
).getPath();
return
(
new
File(urlPath).getParent() + RSA_PAIR_FILENAME);
}
/**
* 若需要创建新的密钥对文件,则返回 {@code true},否则 {@code false}。
*/
private
static
boolean
isCreateKeyPairFile() {
// 是否创建新的密钥对文件
boolean
createNewKeyPair =
false
;
if
(!rsaPairFile.exists() || rsaPairFile.isDirectory()) {
createNewKeyPair =
true
;
}
return
createNewKeyPair;
}
/**
* 将指定的RSA密钥对以文件形式保存。
*
* @param keyPair 要保存的密钥对。
*/
private
static
void
saveKeyPair(KeyPair keyPair) {
FileOutputStream fos =
null
;
ObjectOutputStream oos =
null
;
try
{
fos = FileUtils.openOutputStream(rsaPairFile);
oos =
new
ObjectOutputStream(fos);
oos.writeObject(keyPair);
}
catch
(Exception ex) {
ex.printStackTrace();
}
finally
{
IOUtils.closeQuietly(oos);
IOUtils.closeQuietly(fos);
}
}
/**
* 返回RSA密钥对。
*/
public
static
KeyPair getKeyPair() {
// 首先判断是否需要重新生成新的密钥对文件
if
(isCreateKeyPairFile()) {
// 直接强制生成密钥对文件,并存入缓存。
return
generateKeyPair();
}
if
(oneKeyPair !=
null
) {
return
oneKeyPair;
}
return
readKeyPair();
}
// 同步读出保存的密钥对
private
static
KeyPair readKeyPair() {
FileInputStream fis =
null
;
ObjectInputStream ois =
null
;
try
{
fis = FileUtils.openInputStream(rsaPairFile);
ois =
new
ObjectInputStream(fis);
oneKeyPair = (KeyPair) ois.readObject();
return
oneKeyPair;
}
catch
(Exception ex) {
ex.printStackTrace();
}
finally
{
IOUtils.closeQuietly(ois);
IOUtils.closeQuietly(fis);
}
return
null
;
}
/**
* 根据给定的系数和专用指数构造一个RSA专用的公钥对象。
*
* @param modulus 系数。
* @param publicExponent 专用指数。
* @return RSA专用公钥对象。
*/
public
static
RSAPublicKey generateRSAPublicKey(
byte
[] modulus,
byte
[] publicExponent) {
RSAPublicKeySpec publicKeySpec =
new
RSAPublicKeySpec(
new
BigInteger(modulus),
new
BigInteger(publicExponent));
try
{
return
(RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
}
catch
(InvalidKeySpecException ex) {
LOGGER.error(
"RSAPublicKeySpec is unavailable."
, ex);
}
catch
(NullPointerException ex) {
LOGGER.error(
"RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance."
, ex);
}
return
null
;
}
/**
* 根据给定的系数和专用指数构造一个RSA专用的私钥对象。
*
* @param modulus 系数。
* @param privateExponent 专用指数。
* @return RSA专用私钥对象。
*/
public
static
RSAPrivateKey generateRSAPrivateKey(
byte
[] modulus,
byte
[] privateExponent) {
RSAPrivateKeySpec privateKeySpec =
new
RSAPrivateKeySpec(
new
BigInteger(modulus),
new
BigInteger(privateExponent));
try
{
return
(RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
}
catch
(InvalidKeySpecException ex) {
LOGGER.error(
"RSAPrivateKeySpec is unavailable."
, ex);
}
catch
(NullPointerException ex) {
LOGGER.error(
"RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance."
, ex);
}
return
null
;
}
/**
* 根据给定的16进制系数和专用指数字符串构造一个RSA专用的私钥对象。
*
* @param modulus 系数。
* @param privateExponent 专用指数。
* @return RSA专用私钥对象。
*/
public
static
RSAPrivateKey getRSAPrivateKey(String hexModulus, String hexPrivateExponent) {
if
(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPrivateExponent)) {
if
(LOGGER.isDebugEnabled()) {
LOGGER.debug(
"hexModulus and hexPrivateExponent cannot be empty. RSAPrivateKey value is null to return."
);
}
return
null
;
}
byte
[] modulus =
null
;
byte
[] privateExponent =
null
;
try
{
modulus = Hex.decodeHex(hexModulus.toCharArray());
privateExponent = Hex.decodeHex(hexPrivateExponent.toCharArray());
}
catch
(DecoderException ex) {
LOGGER.error(
"hexModulus or hexPrivateExponent value is invalid. return null(RSAPrivateKey)."
);
}
if
(modulus !=
null
&& privateExponent !=
null
) {
return
generateRSAPrivateKey(modulus, privateExponent);
}
return
null
;
}
/**
* 根据给定的16进制系数和专用指数字符串构造一个RSA专用的公钥对象。
*
* @param modulus 系数。
* @param publicExponent 专用指数。
* @return RSA专用公钥对象。
*/
public
static
RSAPublicKey getRSAPublidKey(String hexModulus, String hexPublicExponent) {
if
(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPublicExponent)) {
if
(LOGGER.isDebugEnabled()) {
LOGGER.debug(
"hexModulus and hexPublicExponent cannot be empty. return null(RSAPublicKey)."
);
}
return
null
;
}
byte
[] modulus =
null
;
byte
[] publicExponent =
null
;
try
{
modulus = Hex.decodeHex(hexModulus.toCharArray());
publicExponent = Hex.decodeHex(hexPublicExponent.toCharArray());
}
catch
(DecoderException ex) {
LOGGER.error(
"hexModulus or hexPublicExponent value is invalid. return null(RSAPublicKey)."
);
}
if
(modulus !=
null
&& publicExponent !=
null
) {
return
generateRSAPublicKey(modulus, publicExponent);
}
return
null
;
}
/**
* 使用指定的公钥加密数据。
*
* @param publicKey 给定的公钥。
* @param data 要加密的数据。
* @return 加密后的数据。
*/
public
static
byte
[] encrypt(PublicKey publicKey,
byte
[] data)
throws
Exception {
Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
ci.init(Cipher.ENCRYPT_MODE, publicKey);
return
ci.doFinal(data);
}
/**
* 使用指定的私钥解密数据。
*
* @param privateKey 给定的私钥。
* @param data 要解密的数据。
* @return 原数据。
*/
public
static
byte
[] decrypt(PrivateKey privateKey,
byte
[] data)
throws
Exception {
Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
ci.init(Cipher.DECRYPT_MODE, privateKey);
return
ci.doFinal(data);
}
/**
* 使用给定的公钥加密给定的字符串。
* <p />
* 若 {@code publicKey} 为 {@code null},或者 {@code plaintext} 为 {@code null} 则返回 {@code
* null}。
*
* @param publicKey 给定的公钥。
* @param plaintext 字符串。
* @return 给定字符串的密文。
*/
public
static
String encryptString(PublicKey publicKey, String plaintext) {
if
(publicKey ==
null
|| plaintext ==
null
) {
return
null
;
}
byte
[] data = plaintext.getBytes();
try
{
byte
[] en_data = encrypt(publicKey, data);
return
new
String(Hex.encodeHex(en_data));
}
catch
(Exception ex) {
LOGGER.error(ex.getCause().getMessage());
}
return
null
;
}
/**
* 使用默认的公钥加密给定的字符串。
* <p />
* 若{@code plaintext} 为 {@code null} 则返回 {@code null}。
*
* @param plaintext 字符串。
* @return 给定字符串的密文。
*/
public
static
String encryptString(String plaintext) {
if
(plaintext ==
null
) {
return
null
;
}
byte
[] data = plaintext.getBytes();
KeyPair keyPair = getKeyPair();
try
{
byte
[] en_data = encrypt((RSAPublicKey)keyPair.getPublic(), data);
return
new
String(Hex.encodeHex(en_data));
}
catch
(NullPointerException ex) {
LOGGER.error(
"keyPair cannot be null."
);
}
catch
(Exception ex) {
LOGGER.error(ex.getCause().getMessage());
}
return
null
;
}
/**
* 使用给定的私钥解密给定的字符串。
* <p />
* 若私钥为 {@code null},或者 {@code encrypttext} 为 {@code null}或空字符串则返回 {@code null}。
* 私钥不匹配时,返回 {@code null}。
*
* @param privateKey 给定的私钥。
* @param encrypttext 密文。
* @return 原文字符串。
*/
public
static
String decryptString(PrivateKey privateKey, String encrypttext) {
if
(privateKey ==
null
|| StringUtils.isBlank(encrypttext)) {
return
null
;
}
try
{
byte
[] en_data = Hex.decodeHex(encrypttext.toCharArray());
byte
[] data = decrypt(privateKey, en_data);
return
new
String(data);
}
catch
(Exception ex) {
LOGGER.error(String.format(
"\"%s\" Decryption failed. Cause: %s"
, encrypttext, ex.getCause().getMessage()));
}
return
null
;
}
/**
* 使用默认的私钥解密给定的字符串。
* <p />
* 若{@code encrypttext} 为 {@code null}或空字符串则返回 {@code null}。
* 私钥不匹配时,返回 {@code null}。
*
* @param encrypttext 密文。
* @return 原文字符串。
*/
public
static
String decryptString(String encrypttext) {
if
(StringUtils.isBlank(encrypttext)) {
return
null
;
}
KeyPair keyPair = getKeyPair();
try
{
byte
[] en_data = Hex.decodeHex(encrypttext.toCharArray());
byte
[] data = decrypt((RSAPrivateKey)keyPair.getPrivate(), en_data);
return
new
String(data);
}
catch
(NullPointerException ex) {
LOGGER.error(
"keyPair cannot be null."
);
}
catch
(Exception ex) {
LOGGER.error(String.format(
"\"%s\" Decryption failed. Cause: %s"
, encrypttext, ex.getMessage()));
}
return
null
;
}
/**
* 使用默认的私钥解密由JS加密(使用此类提供的公钥加密)的字符串。
*
* @param encrypttext 密文。
* @return {@code encrypttext} 的原文字符串。
*/
public
static
String decryptStringByJs(String encrypttext) {
String text = decryptString(encrypttext);
if
(text ==
null
) {
return
null
;
}
return
StringUtils.reverse(text);
}
/** 返回已初始化的默认的公钥。*/
public
static
RSAPublicKey getDefaultPublicKey() {
KeyPair keyPair = getKeyPair();
if
(keyPair !=
null
) {
return
(RSAPublicKey)keyPair.getPublic();
}
return
null
;
}
/** 返回已初始化的默认的私钥。*/
public
static
RSAPrivateKey getDefaultPrivateKey() {
KeyPair keyPair = getKeyPair();
if
(keyPair !=
null
) {
return
(RSAPrivateKey)keyPair.getPrivate();
}
return
null
;
}
public
static
PublicKeyMap getPublicKeyMap() {
PublicKeyMap publicKeyMap =
new
PublicKeyMap();
RSAPublicKey rsaPublicKey = getDefaultPublicKey();
publicKeyMap.setModulus(
new
String(Hex.encodeHex(rsaPublicKey.getModulus().toByteArray())));
publicKeyMap.setExponent(
new
String(Hex.encodeHex(rsaPublicKey.getPublicExponent().toByteArray())));
return
publicKeyMap;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package
com.web.utils;
public
class
PublicKeyMap {
private
String modulus;
private
String exponent;
public
String getModulus() {
return
modulus;
}
public
void
setModulus(String modulus) {
this
.modulus = modulus;
}
public
String getExponent() {
return
exponent;
}
public
void
setExponent(String exponent) {
this
.exponent = exponent;
}
@Override
public
String toString() {
return
"PublicKeyMap [modulus="
+ modulus +
", exponent="
+ exponent
+
"]"
;
}
}
|
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
|
package
com.web.actions;
import
com.opensymphony.xwork2.ActionContext;
import
com.opensymphony.xwork2.ActionSupport;
import
com.web.utils.PublicKeyMap;
import
com.web.utils.RSAUtils;
public
class
UserAction
extends
ActionSupport{
private
static
final
long
serialVersionUID = 3859457733764601693L;
private
String password;
private
Object json;
public
String getPassword() {
return
password;
}
public
void
setPassword(String password) {
this
.password = password;
}
public
Object getJson() {
return
json;
}
public
void
setJson(Object json) {
this
.json = json;
}
/**
* 获取系数和指数
* @return
* @throws Exception
*/
public
String keyPair()
throws
Exception{
PublicKeyMap publicKeyMap = RSAUtils.getPublicKeyMap();
System.out.println(publicKeyMap);
setJson(publicKeyMap);
return
SUCCESS;
}
/**
* 登录
* @return
* @throws Exception
*/
public
String login()
throws
Exception{
String pwd = RSAUtils.decryptStringByJs(getPassword());
System.out.println(pwd);
ActionContext.getContext().put(
"pwd"
, pwd);
return
SUCCESS;
}
}
|
//struts.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!
DOCTYPE
stru<span></
span
>ts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<
struts
>
<
package
name
=
"default"
namespace
=
"/user"
extends
=
"json-default"
>
<
action
name
=
"login"
class
=
"com.web.actions.UserAction"
method
=
"login"
>
<
result
>/success.jsp</
result
>
</
action
>
<
action
name
=
"keyPair"
class
=
"com.web.actions.UserAction"
method
=
"keyPair"
>
<
result
type
=
"json"
>
<
param
name
=
"root"
>json</
param
>
</
result
>
</
action
>
</
package
>
</
struts
>
|
//前台显示index.jsp
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
|
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!
DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
title
>RSA</
title
>
<
script
type
=
"text/javascript"
src
=
"<s:url value="
js/jquery-1.8.0.min.js" />"></
script
>
<
script
type
=
"text/javascript"
src
=
"<s:url value="
js/security.js" />"></
script
>
<
script
type
=
"text/javascript"
>
$(function(){
$("#btn").click(function(){
$.getJSON('<
s:url
namespace
=
"/user"
action
=
"keyPair"
/>',function(data) {
var modulus = data.modulus, exponent = data.exponent;
var epwd = $('#password').val();
if (epwd.length != 256) {
var publicKey = RSAUtils.getKeyPair(exponent, '', modulus);
$('#password').val(RSAUtils.encryptedString(publicKey, epwd));
}
$("#login").submit();
});
});
});
</
script
>
</
head
>
<
body
>
<
form
id
=
"login"
name
=
"login"
action
=
"<s:url namespace="
/user"
action
=
"login"
/>" method="post">
密码:<
input
type
=
"password"
id
=
"password"
name
=
"password"
/>
<
input
id
=
"btn"
type
=
"button"
value
=
"提 交"
/>
</
form
>
</
body
>
</
html
>
|
//success.jsp成功
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<
span
></
span
><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!
DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
title
>成功!</
title
>
</
head
>
<
body
>
<
h1
>密码是:</
h1
>
<
h1
><
s:property
value
=
"#request.pwd"
/></
h1
>
</
body
>
</
html
>
|
以上是实现代码,希望能给各位朋友带来帮助
结果图如下:
index.jsp
success.js
控制台