转自:http://www.open-open.com/lib/view/open1397274257325.html
如基本的单向加密算法:
BASE64 严格地说,属于编码格式,而非加密算法
MD5(Message Digest algorithm 5,信息摘要算法)
SHA(Secure Hash Algorithm,安全散列算法)
HMAC(Hash Message Authentication Code,散列消息鉴别码)
复杂的对称加密(DES、PBE)、非对称加密算法:
DES(Data Encryption Standard,数据加密算法)
PBE(Password-based encryption,基于密码验证)
RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)
DH(Diffie-Hellman算法,**一致协议)
DSA(Digital Signature Algorithm,数字签名)
ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)
如基本的单向加密算法:
BASE64 严格地说,属于编码格式,而非加密算法
MD5(Message Digest algorithm 5,信息摘要算法)
SHA(Secure Hash Algorithm,安全散列算法)
HMAC(Hash Message Authentication Code,散列消息鉴别码)
复杂的对称加密(DES、PBE)、非对称加密算法:
DES(Data Encryption Standard,数据加密算法)
PBE(Password-based encryption,基于密码验证)
RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)
DH(Diffie-Hellman算法,**一致协议)
DSA(Digital Signature Algorithm,数字签名)
ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)
本篇内容简要介绍BASE64、MD5、SHA、HMAC几种方法。
MD5、SHA、HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法。我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。
BASE64
按 照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
常见于邮件、http加密,截取http信息,你就会发现登录操作的用户名、密码字段通过BASE64加密的。
通过java代码实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* 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);
}
|
主要就是BASE64Encoder、BASE64Decoder两个类,我们只需要知道使用对应的方法即可。另,BASE加密后产生的字节位数是8的倍数,如果不够位数以=符号填充。
MD5
MD5 -- message-digest algorithm 5 (信息-摘要算法)缩写,广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过MD5后都能生成唯一的MD5值。好比现在的ISO校验,都 是MD5校验。怎么用?当然是把ISO经过MD5后产生MD5的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD5的串。就是用来验证文 件是否一致的。
通过java代码实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/**
* 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();
}
|
通常我们不直接使用上述MD5加密。通常将MD5产生的字节数组交给BASE64再加密一把,得到相应的字符串。
SHA
SHA(Secure Hash Algorithm,安全散列算法),数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域。虽然,SHA与MD5通过碰撞法都被**了, 但是SHA仍然是公认的安全加密算法,较之MD5更为安全。
通过java代码实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/**
* 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
HMAC(Hash Message Authentication Code,散列消息鉴别码,基于**的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和**产生一个固定长度的值作为认证标识,用这个 标识鉴别消息的完整性。使用一个**生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的**进行鉴别认证 等。
通过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
|
/**
* 初始化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
|
import
java.security.MessageDigest;
import
javax.crypto.KeyGenerator;
import
javax.crypto.Mac;
import
javax.crypto.SecretKey;
import
sun.misc.BASE64Decoder;
import
sun.misc.BASE64Encoder;
/**
* 基础加密组件
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
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
|
import
static
org.junit.Assert.*;
import
org.junit.Test;
/**
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
public
class
CoderTest {
@Test
public
void
test()
throws
Exception {
String inputStr =
"简单加密"
;
System.err.println(
"原文:\n"
+ inputStr);
byte
[] inputData = inputStr.getBytes();
String code = Coder.encryptBASE64(inputData);
System.err.println(
"BASE64加密后:\n"
+ code);
byte
[] output = Coder.decryptBASE64(code);
String outputStr =
new
String(output);
System.err.println(
"BASE64解密后:\n"
+ outputStr);
// 验证BASE64加密解密一致性
assertEquals(inputStr, outputStr);
// 验证MD5对于同一内容加密是否一致
assertArrayEquals(Coder.encryptMD5(inputData), Coder
.encryptMD5(inputData));
// 验证SHA对于同一内容加密是否一致
assertArrayEquals(Coder.encryptSHA(inputData), Coder
.encryptSHA(inputData));
String key = Coder.initMacKey();
System.err.println(
"Mac**:\n"
+ key);
// 验证HMAC对于同一内容,同一**加密是否一致
assertArrayEquals(Coder.encryptHMAC(inputData, key), Coder.encryptHMAC(
inputData, key));
BigInteger md5 =
new
BigInteger(Coder.encryptMD5(inputData));
System.err.println(
"MD5:\n"
+ md5.toString(
16
));
BigInteger sha =
new
BigInteger(Coder.encryptSHA(inputData));
System.err.println(
"SHA:\n"
+ sha.toString(
32
));
BigInteger mac =
new
BigInteger(Coder.encryptHMAC(inputData, inputStr));
System.err.println(
"HMAC:\n"
+ mac.toString(
16
));
}
}
|
控制台输出:
原文: 简单加密 BASE64加密后: 566A5Y2V5Yqg5a+G BASE64解密后: 简单加密 Mac**: uGxdHC+6ylRDaik++leFtGwiMbuYUJ6mqHWyhSgF4trVkVBBSQvY/a22xU8XT1RUemdCWW155Bke pBIpkd7QHg== MD5: -550b4d90349ad4629462113e7934de56 SHA: 91k9vo7p400cjkgfhjh0ia9qthsjagfn HMAC: 2287d192387e95694bdbba2fa941009a
注意
编译时,可能会看到如下提示:
引用
警告:sun.misc.BASE64Decoder 是 Sun 的专用 API,可能会在未来版本中删除
import sun.misc.BASE64Decoder;
^
警告:sun.misc.BASE64Encoder 是 Sun 的专用 API,可能会在未来版本中删除
import sun.misc.BASE64Encoder;
^
BASE64Encoder 和BASE64Decoder是非官方JDK实现类。虽然可以在JDK里能找到并使用,但是在API里查不到。JRE 中 sun 和 com.sun 开头包的类都是未被文档化的,他们属于 java, javax 类库的基础,其中的实现大多数与底层平台有关,一般来说是不推荐使用的。
BASE64的加密解密是双向的,可以求反解。
MD5、SHA以及HMAC是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。其中HMAC算法有一个**,增强了数据传输过程中的安全性,强化了算法外的不可控因素。
单向加密的用途主要是为了校验数据在传输过程中是否被修改。
接下来我们介绍对称加密算法,最常用的莫过于DES数据加密算法。
DES
DES-Data Encryption Standard,即数据加密算法。是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中 Key为8个字节共64位,是DES算法的工作**;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密 或解密。
DES算法把64位的明文输入块变为64位的密文输出块,它所使用的**也是64位。
通过java代码实现如下:Coder类见
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
|
import
java.security.Key;
import
java.security.SecureRandom;
import
javax.crypto.Cipher;
import
javax.crypto.KeyGenerator;
import
javax.crypto.SecretKey;
import
javax.crypto.SecretKeyFactory;
import
javax.crypto.spec.DESKeySpec;
/**
* DES安全编码组件
*
* <pre>
* 支持 DES、DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)
* DES key size must be equal to 56
* DESede(TripleDES) key size must be equal to 112 or 168
* AES key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
* Blowfish key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
* RC2 key size must be between 40 and 1024 bits
* RC4(ARCFOUR) key size must be between 40 and 1024 bits
* 具体内容 需要关注 JDK Document http://.../docs/technotes/guides/security/SunProviders.html
* </pre>
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
public
abstract
class
DESCoder
extends
Coder {
/**
* ALGORITHM 算法 <br>
* 可替换为以下任意一种算法,同时key值的size相应改变。
*
* <pre>
* DES key size must be equal to 56
* DESede(TripleDES) key size must be equal to 112 or 168
* AES key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
* Blowfish key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
* RC2 key size must be between 40 and 1024 bits
* RC4(ARCFOUR) key size must be between 40 and 1024 bits
* </pre>
*
* 在Key toKey(byte[] key)方法中使用下述代码
* <code>SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);</code> 替换
* <code>
* DESKeySpec dks = new DESKeySpec(key);
* SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
* SecretKey secretKey = keyFactory.generateSecret(dks);
* </code>
*/
public
static
final
String ALGORITHM =
"DES"
;
/**
* 转换**<br>
*
* @param key
* @return
* @throws Exception
*/
private
static
Key toKey(
byte
[] key)
throws
Exception {
DESKeySpec dks =
new
DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(dks);
// 当使用其他对称加密算法时,如AES、Blowfish等算法时,用下述代码替换上述三行代码
// SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
return
secretKey;
}
/**
* 解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[] decrypt(
byte
[] data, String key)
throws
Exception {
Key k = toKey(decryptBASE64(key));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, k);
return
cipher.doFinal(data);
}
/**
* 加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[] encrypt(
byte
[] data, String key)
throws
Exception {
Key k = toKey(decryptBASE64(key));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k);
return
cipher.doFinal(data);
}
/**
* 生成**
*
* @return
* @throws Exception
*/
public
static
String initKey()
throws
Exception {
return
initKey(
null
);
}
/**
* 生成**
*
* @param seed
* @return
* @throws Exception
*/
public
static
String initKey(String seed)
throws
Exception {
SecureRandom secureRandom =
null
;
if
(seed !=
null
) {
secureRandom =
new
SecureRandom(decryptBASE64(seed));
}
else
{
secureRandom =
new
SecureRandom();
}
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
kg.init(secureRandom);
SecretKey secretKey = kg.generateKey();
return
encryptBASE64(secretKey.getEncoded());
}
}
|
延续上一个类的实现,我们通过MD5以及SHA对字符串加密生成**,这是比较常见的**生成方式。
再给出一个测试类:
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
|
import
static
org.junit.Assert.*;
import
org.junit.Test;
/**
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
public
class
DESCoderTest {
@Test
public
void
test()
throws
Exception {
String inputStr =
"DES"
;
String key = DESCoder.initKey();
System.err.println(
"原文:\t"
+ inputStr);
System.err.println(
"**:\t"
+ key);
byte
[] inputData = inputStr.getBytes();
inputData = DESCoder.encrypt(inputData, key);
System.err.println(
"加密后:\t"
+ DESCoder.encryptBASE64(inputData));
byte
[] outputData = DESCoder.decrypt(inputData, key);
String outputStr =
new
String(outputData);
System.err.println(
"解密后:\t"
+ outputStr);
assertEquals(inputStr, outputStr);
}
}
|
得到的输出内容如下:
原文: DES **: f3wEtRrV6q0= 加密后: C6qe9oNIzRY= 解密后: DES
由控制台得到的输出,我们能够比对加密、解密后结果一致。这是一种简单的加密解密方式,只有一个**。
其实DES有很多同胞兄弟,如DESede(TripleDES)、AES、Blowfish、RC2、RC4(ARCFOUR)。这里就不过多阐述了,大同小异,只要换掉ALGORITHM换成对应的值,同时做一个代码替换SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);就可以了,此外就是**长度不同了。
1
2
3
4
5
6
7
8
|
/**
* DES key size must be equal to 56
* DESede(TripleDES) key size must be equal to 112 or 168
* AES key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
* Blowfish key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
* RC2 key size must be between 40 and 1024 bits
* RC4(ARCFOUR) key size must be between 40 and 1024 bits
**/
|
除了DES,我们还知道有DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法——PBE
PBE
PBE——Password-based encryption(基于密码加密)。其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。是一种简便的加密方式。
通过java代码实现如下:Coder类见
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
|
import
java.security.Key;
import
java.util.Random;
import
javax.crypto.Cipher;
import
javax.crypto.SecretKey;
import
javax.crypto.SecretKeyFactory;
import
javax.crypto.spec.PBEKeySpec;
import
javax.crypto.spec.PBEParameterSpec;
/**
* PBE安全编码组件
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
public
abstract
class
PBECoder
extends
Coder {
/**
* 支持以下任意一种算法
*
* <pre>
* PBEWithMD5AndDES
* PBEWithMD5AndTripleDES
* PBEWithSHA1AndDESede
* PBEWithSHA1AndRC2_40
* </pre>
*/
public
static
final
String ALGORITHM =
"PBEWITHMD5andDES"
;
/**
* 盐初始化
*
* @return
* @throws Exception
*/
public
static
byte
[] initSalt()
throws
Exception {
byte
[] salt =
new
byte
[
8
];
Random random =
new
Random();
random.nextBytes(salt);
return
salt;
}
/**
* 转换**<br>
*
* @param password
* @return
* @throws Exception
*/
private
static
Key toKey(String password)
throws
Exception {
PBEKeySpec keySpec =
new
PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(keySpec);
return
secretKey;
}
/**
* 加密
*
* @param data 数据
* @param password 密码
* @param salt 盐
* @return
* @throws Exception
*/
public
static
byte
[] encrypt(
byte
[] data, String password,
byte
[] salt)
throws
Exception {
Key key = toKey(password);
PBEParameterSpec paramSpec =
new
PBEParameterSpec(salt,
100
);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
return
cipher.doFinal(data);
}
/**
* 解密
*
* @param data 数据
* @param password 密码
* @param salt 盐
* @return
* @throws Exception
*/
public
static
byte
[] decrypt(
byte
[] data, String password,
byte
[] salt)
throws
Exception {
Key key = toKey(password);
PBEParameterSpec paramSpec =
new
PBEParameterSpec(salt,
100
);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
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
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import
static
org.junit.Assert.*;
import
org.junit.Test;
/**
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
public
class
PBECoderTest {
@Test
public
void
test()
throws
Exception {
String inputStr =
"abc"
;
System.err.println(
"原文: "
+ inputStr);
byte
[] input = inputStr.getBytes();
String pwd =
"efg"
;
System.err.println(
"密码: "
+ pwd);
byte
[] salt = PBECoder.initSalt();
byte
[] data = PBECoder.encrypt(input, pwd, salt);
System.err.println(
"加密后: "
+ PBECoder.encryptBASE64(data));
byte
[] output = PBECoder.decrypt(data, pwd, salt);
String outputStr =
new
String(output);
System.err.println(
"解密后: "
+ outputStr);
assertEquals(inputStr, outputStr);
}
}
|
控制台输出:
原文: abc 密码: efg 加密后: iCZ0uRtaAhE= 解密后: abc
后续我们会介绍非对称加密算法,如RSA、DSA、DH、ECC等。
接下来我们介绍典型的非对称加密算法——RSA
RSA
这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。
这种加密算法的特点主要是**的变化,上文我们看到DES只有一个**。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥 匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。
流程分析:
甲方构建**对儿,将公钥公布给乙方,将私钥保留。
甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。
乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。
按如上步骤给出序列图,如下:
通过java代码实现如下:Coder类见
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
|
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;
/**
* RSA安全编码组件
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
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 pkcs8KeySpec =
new
PKCS8EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私钥对信息生成数字签名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return
encryptBASE64(signature.sign());
}
/**
* 校验数字签名
*
* @param data
* 加密数据
* @param publicKey
* 公钥
* @param sign
* 数字签名
*
* @return 校验成功返回true 失败返回false
* @throws Exception
*
*/
public
static
boolean
verify(
byte
[] data, String publicKey, String sign)
throws
Exception {
// 解密由base64编码的公钥
byte
[] keyBytes = decryptBASE64(publicKey);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec =
new
X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证签名是否正常
return
signature.verify(decryptBASE64(sign));
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[] decryptByPrivateKey(
byte
[] data, String key)
throws
Exception {
// 对**解密
byte
[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec =
new
PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
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
[] decryptByPublicKey(
byte
[] data, String key)
throws
Exception {
// 对**解密
byte
[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec =
new
X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据解密
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(
byte
[] data, String key)
throws
Exception {
// 对公钥解密
byte
[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec =
new
X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return
cipher.doFinal(data);
}
/**
* 加密<br>
* 用私钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[] encryptByPrivateKey(
byte
[] data, String key)
throws
Exception {
// 对**解密
byte
[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec =
new
PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据加密
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 keyPairGen = KeyPairGenerator
.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(
1024
);
KeyPair keyPair = keyPairGen.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;
}
}
|
再给出一个测试类:
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
|
import
static
org.junit.Assert.*;
import
org.junit.Before;
import
org.junit.Test;
import
java.util.Map;
/**
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
public
class
RSACoderTest {
private
String publicKey;
private
String privateKey;
@Before
public
void
setUp()
throws
Exception {
Map<String, Object> 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
[] data = inputStr.getBytes();
byte
[] encodedData = RSACoder.encryptByPublicKey(data, 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(
"私钥签名——公钥验证签名"
);
// 产生签名
String sign = RSACoder.sign(encodedData, privateKey);
System.err.println(
"签名:\r"
+ sign);
// 验证签名
boolean
status = RSACoder.verify(encodedData, publicKey, sign);
System.err.println(
"状态:\r"
+ status);
assertTrue(status);
}
}
|
控制台输出:
公钥: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm 1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB 私钥: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3 GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV /MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3 QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X nfpFpBJ2dw== 公钥加密——私钥解密 加密前: abc 解密后: abc 公钥: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF 9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB 私钥: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh 9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW 9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2 I2k1Afmrwyw= 私钥加密——公钥解密 加密前: sign 解密后: sign 私钥签名——公钥验证签名 签名: ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+ mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucv*n i3wwbYWs9wSzIf0UjlM= 状态: true
简要总结一下,使用公钥加密、私钥解密,完成了乙方到甲方的一次数据传递,通过私钥加密、公钥解密,同时通过私钥签名、公钥验证签名,完成了一次甲方到乙方的数据传递与验证,两次数据传递完成一整套的数据交互!
类似数字签名,数字信封是这样描述的:
数字信封
数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。
流程:
信息发送方采用对称**来加密信息,然后再用接收方的公钥来加密此对称**(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称**,然后使用对称**再解开信息。
接下来我们分析DH加密算法,一种适基于**一致协议的加密算法。
DH
Diffie- Hellman算法(D-H算法),**一致协议。是由公开**密码体制的奠基人Diffie和Hellman所提出的一种思想。简单的说就是允许两名用 户在公开媒体上交换信息以生成"一致"的、可以共享的**。换句话说,就是由甲方产出一对**(公钥、私钥),乙方依照甲方公钥产生乙方**对(公钥、私 钥)。以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地**(SecretKey)对数据加密。这样,在互通了本地** (SecretKey)算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单 单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯!该算法源于中国的同余定理——中国馀数定理。
流程分析:
1.甲方构建**对儿,将公钥公布给乙方,将私钥保留;双方约定数据加密算法;乙方通过甲方公钥构建**对儿,将公钥公布给甲方,将私钥保留。
2.甲方使用私钥、乙方公钥、约定数据加密算法构建本地**,然后通过本地**加密数据,发送给乙方加密后的数据;乙方使用私钥、甲方公钥、约定数据加密算法构建本地**,然后通过本地**对数据解密。
3.乙方使用私钥、甲方公钥、约定数据加密算法构建本地**,然后通过本地**加密数据,发送给甲方加密后的数据;甲方使用私钥、乙方公钥、约定数据加密算法构建本地**,然后通过本地**对数据解密。
通过java代码实现如下:Coder类见
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
|
import
java.security.Key;
import
java.security.KeyFactory;
import
java.security.KeyPair;
import
java.security.KeyPairGenerator;
import
java.security.PublicKey;
import
java.security.spec.PKCS8EncodedKeySpec;
import
java.security.spec.X509EncodedKeySpec;
import
java.util.HashMap;
import
java.util.Map;
import
javax.crypto.Cipher;
import
javax.crypto.KeyAgreement;
import
javax.crypto.SecretKey;
import
javax.crypto.interfaces.DHPrivateKey;
import
javax.crypto.interfaces.DHPublicKey;
import
javax.crypto.spec.DHParameterSpec;
/**
* DH安全编码组件
*
* @author 梁栋
* @version 1.0
* @since 1.0
*/
public
abstract
class
DHCoder
extends
Coder {
public
static
final
String ALGORITHM =
"DH"
;
/**
* 默认**字节数
*
* <pre>
* DH
* Default Keysize 1024
* Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
* </pre>
*/
private
static
final
int
KEY_SIZE =
1024
;
/**
* DH加密下需要一种对称加密算法对数据加密,这里我们使用DES,也可以使用其他对称加密算法。
*/
public
static
final
String SECRET_ALGORITHM =
"DES"
;
private
static
final
String PUBLIC_KEY =
"DHPublicKey"
;
private
static
final
String PRIVATE_KEY =
"DHPrivateKey"
;
/**
* 初始化甲方**
*
* @return
* @throws Exception
*/
public
static
Map<String, Object> initKey()
throws
Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator
.getInstance(ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 甲方公钥
DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
// 甲方私钥
DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap =
new
HashMap<String, Object>(
2
);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return
keyMap;
}
/**
* 初始化乙方**
*
* @param key
* 甲方公钥
* @return
* @throws Exception
*/
public
static
Map<String, Object> initKey(String key)
throws
Exception {
// 解析甲方公钥
byte
[] keyBytes = decryptBASE64(key);
X509EncodedKeySpec x509KeySpec =
new
X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
// 由甲方公钥构建乙方**
DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams();
KeyPairGenerator keyPairGenerator = KeyPairGenerator
.getInstance(keyFactory.getAlgorithm());
keyPairGenerator.initialize(dhParamSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 乙方公钥
DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
// 乙方私钥
DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap =
new
HashMap<String, Object>(
2
);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return
keyMap;
}
/**
* 加密<br>
*
* @param data
* 待加密数据
* @param publicKey
* 甲方公钥
* @param privateKey
* 乙方私钥
* @return
* @throws Exception
*/
public
static
byte
[] encrypt(
byte
[] data, String publicKey,
String privateKey)
throws
Exception {
// 生成本地**
SecretKey secretKey = getSecretKey(publicKey, privateKey);
// 数据加密
Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return
cipher.doFinal(data);
}
/**
* 解密<br>
*
* @param data
* 待解密数据
* @param publicKey
* 乙方公钥
* @param privateKey
* 乙方私钥
* @return
* @throws Exception
*/
public
static
byte
[] decrypt(
byte
[] data, String publicKey,
String privateKey)
throws
Exception {
// 生成本地**
SecretKey secretKey = getSecretKey(publicKey, privateKey);
// 数据解密
Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return
cipher.doFinal(data);
}
/**
* 构建**
*
* @param publicKey
* 公钥
* @param privateKey
* 私钥
* @return
* @throws Exception
*/
private
static
SecretKey getSecretKey(String publicKey, String privateKey)
throws
Exception {
// 初始化公钥
byte
[] pubKeyBytes = decryptBASE64(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
X509EncodedKeySpec x509KeySpec =
new
X509EncodedKeySpec(pubKeyBytes);
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
// 初始化私钥
byte
[] priKeyBytes = decryptBASE64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec =
new
PKCS8EncodedKeySpec(priKeyBytes);
Key priKey = keyFactory.generatePrivate(pkcs8KeySpec);
KeyAgreement keyAgree = KeyAgreement.getInstance(keyFactory
.getAlgorithm());
keyAgree.init(priKey);
keyAgree.doPhase(pubKey,
true
);
// 生成本地**
SecretKey secretKey = keyAgree.generateSecret(SECRET_ALGORITHM);
return
secretKey;
}
/**
* 取得私钥
*
* @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());
}
/**
* 取得公钥
* </
|