RSA和AES加密解密
恶作剧 java
# 加密算法介绍
AES:对称加密算法,使用相同密钥进行加密解密,密钥长度为128位 192位 256位,适合处理大量数据
RSA:非对称加密算法,有一对密钥 分为公钥和私钥,公钥加密 私钥解密,密钥长度通常为2048,适合用于数字签名
# 区别
| 特性 | AES | RSA |
|---|---|---|
| 加密类型 | 对称加密 | 非对称加密 |
| 密钥管理 | 加解密用同一个密钥 | 公钥加密,私钥解密 |
| 加密速度 | 较快 | 较慢 |
| 密钥长度 | 128位、192位、256位 | 2048位 |
| 安全性 | 密钥必须保密 | 公钥可公开,私钥必须保密 |
| 场景 | 数据加密、文件加密 | 数字签名、身份验签 |
# AES使用
AES分组模式:
- ECB:每块明文独立加密。方式简单安全性低。
- CBC:每块明文加密前与前一个密文块进行异或操作。指定一个偏移量IV确保每次加密得到不同密文
- CFB:将前一块密文作为输入 生成伪随机数,然后与明文块异或操作。
AES填充方式:
AES分组通常为16字节(128位),但是明文可能并不正好为16倍数,通常要进行填充。
- PKCS5Padding:填充的每个值为剩余填充的字节数
- PKCS7Padding:与PKCS5Padding类似,但是可用于大于8字节分组的加密
- NoPadding:不进行填充,但要求输入的明文长度为分组大小的整倍数。
//密钥
private static String APP_KEY = "TEST123456";
/**
* 生成AES密钥
*/
public static void generateAesKey() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
System.out.println("AES密钥:" + Base64.getEncoder().encodeToString(secretKey.getEncoded()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 根据AES密钥生成Key对象
* @param keyBytes 原AES密钥
*/
public static Key getKey(byte[] keyBytes) {
int base = 16;
//判断密钥长度是否是16倍数,通常密钥长度为128位、192位 和256位
if (keyBytes.length % base != 0) {
//keyBytes 不是16倍数,填充新组
int groups = keyBytes.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
//keyBytes内容复制到temp中
System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
keyBytes = temp;
}
//指定加密算法,创建密钥对象
return new SecretKeySpec(keyBytes, "AES");
}
/**
* AES加密
* @param data 待加密的数据
* @return 加密后数据
*/
public static String aesEcbEncrypt(String data) {
try {
Key key = getKey(APP_KEY.getBytes());
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] bytes = cipher.doFinal(data.getBytes());
String encodeBody = new String(Base64.getEncoder().encode(bytes));
return encodeBody;
} catch (Exception e) {
System.out.println("加密失败:" + e);
return null;
}
}
/**
* AES解密
* @param data 待解密的数据
* @return 原始数据
*/
public static String aesEcbDecrypt(String data) {
try {
byte[] decode = Base64.getDecoder().decode(data.getBytes());
Key key = getKey(APP_KEY.getBytes());
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] bytes = cipher.doFinal(decode);
String decodeBody = new String(bytes);
return decodeBody;
} catch (Exception e) {
System.out.println("加密失败:" + e);
return null;
}
}
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
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
# RSA使用
/**
* RSA私钥
*/
private static String PRIVATE_KEY_STR = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAImdJE8Bt0rfmlDByOsav0eeOwX+4Wvzu53e52/ORwW1N7xCG5kGSExAfAcwyw4Owibd8/967pA4WNho03/tHjmFOH1SNPGf5flZNDldhVqjveqtyHYIpZnmNWYN6NoP6ZlbeQ8Z1F8m0biD0rZSgOgM+s73qd5yv9AM22uBtWrZAgMBAAECgYAjRJ61kN8E1WGbKM7xUh2LoUXHN5dWL1T6FNKDmP4ivFrYaKjiAvYsdKpUvXCM3cNsap3J8BuL4qUCcXsi4gZInXpBUOwaLCoOp4X0UJeV5PYfKHQP8JsfTd3RIZDKYhQ6vapKo3NtgA8CD6Pr7o2mj+UibjPZp2ZaI1D3HMbHsQJBAOT95r6W2dEAQFJsQtRr1MpBVIY61/a5m95RiPX7r/oKrAqt23ZLB0q5WlMh+NWWPSqA3heH0NToLnn4NraGFq8CQQCZ2DS8v6N6stVaHRNF6msjQaE2E0A7VSlc+5hVDAOxilp6eriFJLu7Oe2qeNcOa6gOf8Ifv2kzRacoRSScZPj3AkEA05PJBGYLITHzPHStFun+9VWBjHiIHH4Ih1SckHMZeJUturxCnzzZovA5hcBI0sf7Ae+JxQIHMQDKGIX/v4uLHwJALZGQ7WeGMM3PzEVYdBkfau4BplbFa82p1tTfJjHM1kW4zxaSmT1sLeTWtOveJ3NT8Bd/lI/JxVoYTSFN2tU9uQJBAIvidLrVhqd+TtZm1/UrgZn5HltBoqAHOg2USU5a7bGkfimFUVYb/92zDzuLEMjBAmXHIae6T85l2YMATtQtjag=";
/**
* RSA公钥
*/
private static String PUBLIC_KEY_STR = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJnSRPAbdK35pQwcjrGr9HnjsF/uFr87ud3udvzkcFtTe8QhuZBkhMQHwHMMsODsIm3fP/eu6QOFjYaNN/7R45hTh9UjTxn+X5WTQ5XYVao73qrch2CKWZ5jVmDejaD+mZW3kPGdRfJtG4g9K2UoDoDPrO96necr/QDNtrgbVq2QIDAQAB";
/**
* 生成RSA公私钥对
*/
public static void generatorRsaKey() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
//转换为base64编码
Base64.Encoder encoder = Base64.getEncoder();
System.out.println("privateKey=" + encoder.encodeToString(privateKey.getEncoded()));
System.out.println("publicKey=" + encoder.encodeToString(publicKey.getEncoded()));
}
/**
* 得到私钥
*
*/
public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
byte[] keyBytes;
//base64解码
keyBytes = Base64.getDecoder().decode(privateKeyStr.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
/**
* 得到公钥
*
*/
public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
byte[] keyBytes;
//base64解码
keyBytes = Base64.getDecoder().decode(publicKeyStr.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
/**
* 生成签名
*/
public static String generateSignature(String data) {
try {
PrivateKey privateKey = getPrivateKey(PRIVATE_KEY_STR);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data.getBytes());
byte[] signedData = signature.sign();
return Base64.getEncoder().encodeToString(signedData);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 验证签名
* @param data 原始数据
* @param signature 签名数据
*/
public static boolean verifySignature(String data, String signature) {
try {
PublicKey publicKey = getPublicKey(PUBLIC_KEY_STR);
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initVerify(publicKey);
sign.update(data.getBytes());
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return sign.verify(signatureBytes);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
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
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