|
|
@@ -0,0 +1,112 @@
|
|
|
+package com.jzg.quotation.ansheng.crawler.utils;
|
|
|
+
|
|
|
+import javax.crypto.Cipher;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.security.KeyFactory;
|
|
|
+import java.security.PublicKey;
|
|
|
+import java.security.spec.X509EncodedKeySpec;
|
|
|
+import java.util.Base64;
|
|
|
+
|
|
|
+/**
|
|
|
+ * RSA加密工具类
|
|
|
+ *
|
|
|
+ * @author YourName
|
|
|
+ * @date 2026-08-25
|
|
|
+ */
|
|
|
+public class RSAUtils {
|
|
|
+
|
|
|
+ private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+4Uy6zba9JeGu7LR7krxkQ+Ivt7MIl+jR/F0rCoPUDPlqvrKIQAeRlJ8txkLSskLAU9f2F2bjbUmzlBdrxVPz/mPIXA866SAd4ELTAdF3oltCa9yLPERLCLMEwUAjX2lUSS3gxAuXbIuPuVJQi1xQeV+VRiJulMFNjhlq86bRpsc7SZ0rMF3Ahc9WHxulcXofaDRLx+sTxzeTsZC3zCh5Dk2hnHaj7o2C/n8U6ZvfifKeB2kWZyoFlmgX8/6agSfkmdxuTw5CZk9qU/1k0ykg2N5whBfnaMbUD5P08KuU/eBIEriS7U7yQruVfovsgN+c2h4XPEcMG0WrqWZbRNpQIDAQAB";
|
|
|
+
|
|
|
+
|
|
|
+ private static volatile PublicKey publicKey;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取公钥
|
|
|
+ */
|
|
|
+ public static PublicKey getPublicKey() {
|
|
|
+ if (publicKey == null) {
|
|
|
+ synchronized (RSAUtils.class) {
|
|
|
+ if (publicKey == null) {
|
|
|
+ publicKey = parsePublicKey();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return publicKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析公钥
|
|
|
+ */
|
|
|
+ private static PublicKey parsePublicKey() {
|
|
|
+ try {
|
|
|
+ byte[] keyBytes = Base64.getDecoder().decode(PUBLIC_KEY);
|
|
|
+ X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
|
|
|
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
|
|
+ return keyFactory.generatePublic(spec);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("解析RSA公钥失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * RSA加密
|
|
|
+ *
|
|
|
+ * @param plaintext 明文
|
|
|
+ * @return Base64编码的密文
|
|
|
+ * @throws RuntimeException 加密失败时抛出
|
|
|
+ */
|
|
|
+ public static String encrypt(String plaintext) {
|
|
|
+ if (plaintext == null) {
|
|
|
+ throw new IllegalArgumentException("明文不能为null");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
|
|
+ cipher.init(Cipher.ENCRYPT_MODE, getPublicKey());
|
|
|
+
|
|
|
+ byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
|
|
|
+ return Base64.getEncoder().encodeToString(encrypted);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("RSA加密失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * RSA加密(带最大长度限制检查)
|
|
|
+ * RSA最大加密长度为 密钥长度/8 - 11(PKCS1Padding)
|
|
|
+ * 对于2048位密钥,最大加密长度为245字节
|
|
|
+ *
|
|
|
+ * @param plaintext 明文
|
|
|
+ * @return Base64编码的密文
|
|
|
+ * @throws IllegalArgumentException 明文过长时抛出
|
|
|
+ */
|
|
|
+ public static String encryptWithCheck(String plaintext) {
|
|
|
+ if (plaintext == null) {
|
|
|
+ throw new IllegalArgumentException("明文不能为null");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2048位密钥,PKCS1Padding最大加密长度为245字节
|
|
|
+ int maxLength = 245;
|
|
|
+ byte[] plainBytes = plaintext.getBytes(StandardCharsets.UTF_8);
|
|
|
+ if (plainBytes.length > maxLength) {
|
|
|
+ throw new IllegalArgumentException(
|
|
|
+ String.format("明文长度超过最大加密长度限制:当前%d字节,最大%d字节",
|
|
|
+ plainBytes.length, maxLength)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return encrypt(plaintext);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证公钥是否有效
|
|
|
+ */
|
|
|
+ public static boolean isPublicKeyValid() {
|
|
|
+ try {
|
|
|
+ return getPublicKey() != null;
|
|
|
+ } catch (Exception e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|