liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
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
package com.xiaopeng.common.core.utils;
 
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
 
/**
 * RSA 加密解密工具类
 * <p>
 * 支持功能:
 * 1. 公钥加密、私钥解密(OAEP 填充模式)
 * 2. 私钥签名、公钥验签
 * 3. 密钥对生成
 * 4. Base64 编码/解码
 * <p>
 * 注意事项:
 * - RSA 使用 OAEP 填充模式,更安全,默认密钥长度 2048 位,最大加密数据长度为 190 字节
 * - 超长数据需要分段加密或使用对称加密(如 AES)
 * - OAEP 填充使用 SHA-256 和 MGF1 算法
 * - 使用 ThreadLocal 缓存 Cipher 实例,提升高并发性能
 */
public class RSAUtil {
 
    private static final String RSA_ALGORITHM = "RSA";
    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
    private static final String TRANSFORMATION = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
    private static final int KEY_SIZE = 2048;
 
    /**
     * 缓存 Cipher 实例,提高高并发性能
     * Cipher 不是线程安全的,每个线程使用自己的实例
     */
    private static final ThreadLocal<Cipher> ENCRYPT_CIPHER = ThreadLocal.withInitial(() -> {
        try {
            return Cipher.getInstance(TRANSFORMATION);
        } catch (Exception e) {
            throw new RuntimeException("初始化加密 Cipher 失败", e);
        }
    });
 
    private static final ThreadLocal<Cipher> DECRYPT_CIPHER = ThreadLocal.withInitial(() -> {
        try {
            return Cipher.getInstance(TRANSFORMATION);
        } catch (Exception e) {
            throw new RuntimeException("初始化解密 Cipher 失败", e);
        }
    });
 
    private static final ThreadLocal<java.security.Signature> SIGNATURE = ThreadLocal.withInitial(() -> {
        try {
            return java.security.Signature.getInstance(SIGNATURE_ALGORITHM);
        } catch (Exception e) {
            throw new RuntimeException("初始化 Signature 失败", e);
        }
    });
 
    /**
     * 生成 RSA 密钥对
     *
     * @return 密钥对
     */
    public static KeyPair generateKeyPair() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
            keyPairGenerator.initialize(KEY_SIZE);
            return keyPairGenerator.generateKeyPair();
        } catch (Exception e) {
            throw new RuntimeException("生成密钥对失败", e);
        }
    }
 
    /**
     * 获取公钥 Base64 字符串
     *
     * @param keyPair 密钥对
     * @return Base64 编码的公钥
     */
    public static String getPublicKey(KeyPair keyPair) {
        return Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
    }
 
    /**
     * 获取私钥 Base64 字符串
     *
     * @param keyPair 密钥对
     * @return Base64 编码的私钥
     */
    public static String getPrivateKey(KeyPair keyPair) {
        return Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
    }
 
    /**
     * 使用公钥加密
     *
     * @param data       待加密数据
     * @param publicKey  Base64 编码的公钥
     * @return Base64 编码的密文
     */
    public static String encryptByPublicKey(String data, String publicKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PublicKey key = keyFactory.generatePublic(keySpec);
 
            Cipher cipher = ENCRYPT_CIPHER.get();
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("公钥加密失败", e);
        }
    }
 
    /**
     * 使用私钥解密
     *
     * @param data       Base64 编码的密文
     * @param privateKey Base64 编码的私钥
     * @return 明文
     */
    public static String decryptByPrivateKey(String data, String privateKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PrivateKey key = keyFactory.generatePrivate(keySpec);
 
            Cipher cipher = DECRYPT_CIPHER.get();
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(data));
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("私钥解密失败", e);
        }
    }
 
    /**
     * 使用私钥加密
     *
     * @param data       待加密数据
     * @param privateKey Base64 编码的私钥
     * @return Base64 编码的密文
     */
    public static String encryptByPrivateKey(String data, String privateKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PrivateKey key = keyFactory.generatePrivate(keySpec);
 
            Cipher cipher = ENCRYPT_CIPHER.get();
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("私钥加密失败", e);
        }
    }
 
    /**
     * 使用公钥解密
     *
     * @param data      Base64 编码的密文
     * @param publicKey Base64 编码的公钥
     * @return 明文
     */
    public static String decryptByPublicKey(String data, String publicKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PublicKey key = keyFactory.generatePublic(keySpec);
 
            Cipher cipher = DECRYPT_CIPHER.get();
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(data));
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("公钥解密失败", e);
        }
    }
 
    /**
     * 使用私钥签名(SHA256withRSA)
     *
     * @param data       待签名的数据
     * @param privateKey Base64 编码的私钥
     * @return Base64 编码的签名
     */
    public static String sign(String data, String privateKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PrivateKey key = keyFactory.generatePrivate(keySpec);
 
            java.security.Signature signature = SIGNATURE.get();
            signature.initSign(key);
            signature.update(data.getBytes(StandardCharsets.UTF_8));
            byte[] signBytes = signature.sign();
            return Base64.getEncoder().encodeToString(signBytes);
        } catch (Exception e) {
            throw new RuntimeException("签名失败", e);
        }
    }
 
    /**
     * 使用公钥验签(SHA256withRSA)
     *
     * @param data      原始数据
     * @param publicKey Base64 编码的公钥
     * @param sign      Base64 编码的签名
     * @return 验签结果
     */
    public static boolean verify(String data, String publicKey, String sign) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PublicKey key = keyFactory.generatePublic(keySpec);
 
            java.security.Signature signature = SIGNATURE.get();
            signature.initVerify(key);
            signature.update(data.getBytes(StandardCharsets.UTF_8));
            return signature.verify(Base64.getDecoder().decode(sign));
        } catch (Exception e) {
            throw new RuntimeException("验签失败", e);
        }
    }
 
    /**
     * 分段加密(用于超长数据)
     * <p>
     * 注意:实际项目中,超长数据建议使用 AES + RSA 混合加密
     *
     * @param data      待加密数据
     * @param publicKey Base64 编码的公钥
     * @return Base64 编码的密文
     */
    public static String encryptByPublicKeySegment(String data, String publicKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PublicKey key = keyFactory.generatePublic(keySpec);
 
            Cipher cipher = ENCRYPT_CIPHER.get();
            cipher.init(Cipher.ENCRYPT_MODE, key);
 
            byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
            int maxLength = 190; // 2048 位密钥 OAEP 模式最大加密长度
            byte[][] segments = splitArray(dataBytes, maxLength);
 
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < segments.length; i++) {
                byte[] encrypted = cipher.doFinal(segments[i]);
                if (i > 0) {
                    result.append(",");
                }
                result.append(Base64.getEncoder().encodeToString(encrypted));
            }
            return result.toString();
        } catch (Exception e) {
            throw new RuntimeException("分段加密失败", e);
        }
    }
 
    /**
     * 分段解密
     *
     * @param data       加密的数据(逗号分隔的 Base64 字符串)
     * @param privateKey Base64 编码的私钥
     * @return 明文
     */
    public static String decryptByPrivateKeySegment(String data, String privateKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PrivateKey key = keyFactory.generatePrivate(keySpec);
 
            Cipher cipher = DECRYPT_CIPHER.get();
            cipher.init(Cipher.DECRYPT_MODE, key);
 
            String[] segments = data.split(",");
            StringBuilder result = new StringBuilder();
            for (String segment : segments) {
                byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(segment));
                result.append(new String(decrypted, StandardCharsets.UTF_8));
            }
            return result.toString();
        } catch (Exception e) {
            throw new RuntimeException("分段解密失败", e);
        }
    }
 
    /**
     * 将字节数组分段
     */
    private static byte[][] splitArray(byte[] array, int chunkSize) {
        int chunks = (array.length + chunkSize - 1) / chunkSize;
        byte[][] result = new byte[chunks][];
        for (int i = 0; i < chunks; i++) {
            int start = i * chunkSize;
            int end = Math.min(start + chunkSize, array.length);
            result[i] = new byte[end - start];
            System.arraycopy(array, start, result[i], 0, end - start);
        }
        return result;
    }
 
    /**
     * 测试示例
     */
    public static void main(String[] args) {
        // 1. 生成密钥对
//        KeyPair keyPair = generateKeyPair();
//        String publicKey = getPublicKey(keyPair);
//        String privateKey = getPrivateKey(keyPair);
//
//        System.out.println("公钥: " + publicKey);
//        System.out.println("私钥: " + privateKey);
//        System.out.println();
//
//        // 2. 测试加密解密
//        String originalData = "Hello RSA 加密测试!123456789";
//        System.out.println("原始数据: " + originalData);
//
//        // 公钥加密,私钥解密
//        String encrypted = encryptByPublicKey(originalData, publicKey);
//        System.out.println("加密后: " + encrypted);
//
//        String decrypted = decryptByPrivateKey(encrypted, privateKey);
//        System.out.println("解密后: " + decrypted);
//        System.out.println();
//
//        // 3. 测试签名验签
//        String signature = sign(originalData, privateKey);
//        System.out.println("签名: " + signature);
//
//        boolean verified = verify(originalData, publicKey, signature);
//        System.out.println("验签结果: " + verified);
//
//        // 4. 测试私钥加密,公钥解密
//        String encryptedByPrivate = encryptByPrivateKey(originalData, privateKey);
//        System.out.println("私钥加密: " + encryptedByPrivate);
//
//        String decryptedByPublic = decryptByPublicKey(encryptedByPrivate, publicKey);
//        System.out.println("公钥解密: " + decryptedByPublic);
//
//        // 5. 测试分段加密(长数据)
//        String longData = "这是一段很长的数据,需要分段加密。".repeat(10);
//        String encryptedSegment = encryptByPublicKeySegment(longData, publicKey);
//        System.out.println("分段加密长度: " + encryptedSegment.length());
//
//        String decryptedSegment = decryptByPrivateKeySegment(encryptedSegment, privateKey);
//        System.out.println("分段解密结果: " + (longData.equals(decryptedSegment) ? "成功" : "失败"));
    }
}