非对称加密算法 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);
}
}
|