feat:钱包接口对接
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package com.cool.store.utils;
|
||||
|
||||
/**
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/11/13 12:15
|
||||
* @Version 1.0
|
||||
*/
|
||||
public class KeyFormatUtil {
|
||||
|
||||
/**
|
||||
* 将单行密钥转换为标准PEM多行格式
|
||||
*/
|
||||
public static String convertToPEMFormat(String singleLineKey, String keyType) {
|
||||
if (singleLineKey == null || singleLineKey.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("密钥不能为空");
|
||||
}
|
||||
|
||||
// 清理密钥,移除可能存在的头尾标记和空白
|
||||
String cleanedKey = cleanKey(singleLineKey);
|
||||
|
||||
// 定义头尾标记
|
||||
String header = getKeyHeader(keyType);
|
||||
String footer = getKeyFooter(keyType);
|
||||
|
||||
// 构建多行格式
|
||||
StringBuilder pemKey = new StringBuilder();
|
||||
pemKey.append(header).append("\n");
|
||||
|
||||
// 每64个字符换行
|
||||
for (int i = 0; i < cleanedKey.length(); i += 64) {
|
||||
int end = Math.min(i + 64, cleanedKey.length());
|
||||
pemKey.append(cleanedKey.substring(i, end)).append("\n");
|
||||
}
|
||||
|
||||
pemKey.append(footer);
|
||||
return pemKey.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理密钥字符串
|
||||
*/
|
||||
public static String cleanKey(String key) {
|
||||
return key.replaceAll("-----BEGIN.*-----", "")
|
||||
.replaceAll("-----END.*-----", "")
|
||||
.replaceAll("\\s", "") // 移除所有空白字符
|
||||
.trim();
|
||||
}
|
||||
|
||||
private static String getKeyHeader(String keyType) {
|
||||
switch (keyType.toUpperCase()) {
|
||||
case "PRIVATE":
|
||||
case "PRIVATE_KEY":
|
||||
return "-----BEGIN PRIVATE KEY-----";
|
||||
case "PUBLIC":
|
||||
case "PUBLIC_KEY":
|
||||
return "-----BEGIN PUBLIC KEY-----";
|
||||
case "RSA_PRIVATE":
|
||||
return "-----BEGIN RSA PRIVATE KEY-----";
|
||||
case "RSA_PUBLIC":
|
||||
return "-----BEGIN RSA PUBLIC KEY-----";
|
||||
default:
|
||||
throw new IllegalArgumentException("不支持的密钥类型: " + keyType);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getKeyFooter(String keyType) {
|
||||
switch (keyType.toUpperCase()) {
|
||||
case "PRIVATE":
|
||||
case "PRIVATE_KEY":
|
||||
return "-----END PRIVATE KEY-----";
|
||||
case "PUBLIC":
|
||||
case "PUBLIC_KEY":
|
||||
return "-----END PUBLIC KEY-----";
|
||||
case "RSA_PRIVATE":
|
||||
return "-----END RSA PRIVATE KEY-----";
|
||||
case "RSA_PUBLIC":
|
||||
return "-----END RSA PUBLIC KEY-----";
|
||||
default:
|
||||
throw new IllegalArgumentException("不支持的密钥类型: " + keyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,85 +112,4 @@ public class OpenSignatureUtil {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造签名串
|
||||
* @param params 参数Map
|
||||
* @return 构造好的签名串
|
||||
*/
|
||||
public static String buildSignString(Map<String, String> params) {
|
||||
return params.entrySet().stream()
|
||||
// 过滤空值字段
|
||||
.filter(entry -> entry.getValue() != null && !entry.getValue().trim().isEmpty())
|
||||
// 按参数名 ASCII 码升序排序
|
||||
.sorted(Map.Entry.comparingByKey())
|
||||
// 格式化为 key=value,值进行URL编码
|
||||
.map(entry -> {
|
||||
try {
|
||||
String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name());
|
||||
return entry.getKey() + "=" + encodedValue;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("URL编码失败", e);
|
||||
}
|
||||
})
|
||||
// 用 & 连接
|
||||
.collect(Collectors.joining("&"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用私钥对签名串进行 RSA-SHA256 签名
|
||||
* @param signString 待签名的字符串
|
||||
* @param privateKeyStr Base64编码的私钥
|
||||
* @return Base64编码的签名
|
||||
*/
|
||||
public static String signWithRsaSha256(String signString, String privateKeyStr) {
|
||||
try {
|
||||
// 1. 解码Base64私钥
|
||||
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
|
||||
|
||||
// 2. 创建PKCS8编码密钥规范
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
|
||||
|
||||
// 3. 获取RSA KeyFactory
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
|
||||
// 4. 生成私钥对象
|
||||
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
|
||||
|
||||
// 5. 创建Signature实例,使用SHA256withRSA算法
|
||||
Signature signature = Signature.getInstance("SHA256withRSA");
|
||||
signature.initSign(privateKey);
|
||||
|
||||
// 6. 更新要签名的数据
|
||||
signature.update(signString.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// 7. 执行签名
|
||||
byte[] digitalSignature = signature.sign();
|
||||
|
||||
// 8. 对签名结果进行Base64编码
|
||||
return Base64.getEncoder().encodeToString(digitalSignature);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("RSA-SHA256签名失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整的签名生成方法
|
||||
* @param params 参数Map
|
||||
* @param privateKeyStr 私钥字符串
|
||||
* @return 签名结果
|
||||
*/
|
||||
public static String generateSignature(Map<String, String> params, String privateKeyStr) {
|
||||
// 1. 构造签名串
|
||||
String signString = buildSignString(params);
|
||||
log.info("待签名串: {}", signString);
|
||||
|
||||
// 2. 使用私钥进行RSA-SHA256签名
|
||||
String signature = signWithRsaSha256(signString, privateKeyStr);
|
||||
log.info("生成签名: {}", signature);
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
package com.cool.store.utils;
|
||||
|
||||
import com.sun.deploy.net.URLEncoder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
|
||||
import sun.security.util.DerInputStream;
|
||||
import sun.security.util.DerValue;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.*;
|
||||
import java.util.*;
|
||||
/**
|
||||
* RSA签名工具类
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/11/12 22:57
|
||||
* @Version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class RsaSignUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 加签方法
|
||||
*/
|
||||
public static String generateSign(Map<String, Object> params, String privateKeyPEM) {
|
||||
// 移除可能存在的sign字段
|
||||
params.remove("sign");
|
||||
String afterSort = objectToSortedString(params);
|
||||
log.info("排序后的参数:{}", afterSort);
|
||||
String formattedPrivateKey = KeyFormatUtil.convertToPEMFormat(privateKeyPEM, "RSA_PRIVATE");
|
||||
return rsaPrivateKeySign(afterSort, privateKeyPEM, "SHA256withRSA");
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签方法
|
||||
*/
|
||||
public static boolean verifySign(Map<String, Object> params, String publicKeyPEM) {
|
||||
String sign = String.valueOf(params.get("sign"));
|
||||
params.remove("sign");
|
||||
String afterSort = objectToSortedString(params);
|
||||
return rsaPublicKeyVerify(afterSort, sign, publicKeyPEM, "SHA256withRSA");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询签名验证 - 主入口方法
|
||||
*/
|
||||
public static boolean querySignCrm(String publicKey, Map<String, Object> params) {
|
||||
return verifySign(params, publicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为排序后的字符串
|
||||
*/
|
||||
public static String objectToSortedString(Map<String, Object> obj) {
|
||||
return convertToSortedString(obj, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归将参数转换为排序字符串
|
||||
*/
|
||||
private static String convertToSortedString(Map<String, Object> params, String prefix) {
|
||||
// 按键排序
|
||||
List<String> keys = new ArrayList<>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
for (String key : keys) {
|
||||
Object value = params.get(key);
|
||||
if (value == null || "".equals(value) ||
|
||||
(value instanceof Number && ((Number) value).doubleValue() == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String currentKey = key;
|
||||
if (!prefix.isEmpty()) {
|
||||
currentKey = prefix + "[" + key + "]";
|
||||
}
|
||||
|
||||
if (value instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> nestedMap = (Map<String, Object>) value;
|
||||
String nestedString = convertToSortedString(nestedMap, currentKey);
|
||||
if (!nestedString.isEmpty()) {
|
||||
parts.add(nestedString);
|
||||
}
|
||||
} else if (value instanceof List) {
|
||||
List<?> list = (List<?>) value;
|
||||
List<String> elemStrs = new ArrayList<>();
|
||||
|
||||
for (Object element : list) {
|
||||
String elementStr;
|
||||
if (element instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> elementMap = (Map<String, Object>) element;
|
||||
String inner = convertToSortedString(elementMap, "");
|
||||
elementStr = "{" + inner + "}";
|
||||
} else if (element instanceof Double) {
|
||||
elementStr = String.format("%.0f", (Double) element);
|
||||
} else if (element instanceof Float) {
|
||||
elementStr = String.format("%.0f", (Float) element);
|
||||
} else {
|
||||
elementStr = String.valueOf(element);
|
||||
}
|
||||
elemStrs.add(elementStr);
|
||||
}
|
||||
|
||||
// 对元素字符串排序
|
||||
Collections.sort(elemStrs);
|
||||
|
||||
// URL编码并添加到parts
|
||||
for (String es : elemStrs) {
|
||||
String encodedValue = urlEncode(es);
|
||||
parts.add(currentKey + "[]=" + encodedValue);
|
||||
}
|
||||
} else if (value instanceof Double) {
|
||||
String strValue = String.format("%.0f", (Double) value);
|
||||
parts.add(currentKey + "=" + urlEncode(strValue));
|
||||
} else if (value instanceof Float) {
|
||||
String strValue = String.format("%.0f", (Float) value);
|
||||
parts.add(currentKey + "=" + urlEncode(strValue));
|
||||
} else {
|
||||
String strValue = String.valueOf(value);
|
||||
parts.add(currentKey + "=" + urlEncode(strValue));
|
||||
}
|
||||
}
|
||||
|
||||
return String.join("&", parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL编码(替换+为%20)
|
||||
*/
|
||||
private static String urlEncode(String value) {
|
||||
try {
|
||||
return URLEncoder.encode(value, StandardCharsets.UTF_8.name())
|
||||
.replace("+", "%20");
|
||||
} catch (Exception e) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA私钥加签
|
||||
*/
|
||||
public static String rsaPrivateKeySign(String text, String privateKeyPEM, String algorithm) {
|
||||
try {
|
||||
// 1. 解析私钥
|
||||
log.debug("Received private key PEM: {}", privateKeyPEM);
|
||||
PrivateKey privateKey = parsePrivateKey(privateKeyPEM);
|
||||
if (privateKey == null) {
|
||||
throw new RuntimeException("解析私钥失败");
|
||||
}
|
||||
|
||||
// 2. 创建签名实例
|
||||
Signature signature = Signature.getInstance(algorithm);
|
||||
signature.initSign(privateKey);
|
||||
signature.update(text.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// 3. 生成签名并Base64编码
|
||||
byte[] digitalSignature = signature.sign();
|
||||
return Base64.getEncoder().encodeToString(digitalSignature);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("加签失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA公钥验签
|
||||
*/
|
||||
public static boolean rsaPublicKeyVerify(String text, String signBase64,
|
||||
String publicKeyPEM, String algorithm) {
|
||||
try {
|
||||
// 1. 解码Base64签名
|
||||
byte[] signature = Base64.getDecoder().decode(signBase64);
|
||||
|
||||
// 2. 解析公钥
|
||||
PublicKey publicKey = parsePublicKey(publicKeyPEM);
|
||||
if (publicKey == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 验证签名
|
||||
Signature sig = Signature.getInstance(algorithm);
|
||||
sig.initVerify(publicKey);
|
||||
sig.update(text.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
return sig.verify(signature);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析PEM格式私钥(兼容PKCS#1和PKCS#8格式)
|
||||
*/
|
||||
private static PrivateKey parsePrivateKey(String privateKeyPEM) {
|
||||
try {
|
||||
String pemContent = privateKeyPEM
|
||||
.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||
.replace("-----END PRIVATE KEY-----", "")
|
||||
.replace("-----BEGIN RSA PRIVATE KEY-----", "")
|
||||
.replace("-----END RSA PRIVATE KEY-----", "")
|
||||
.replaceAll("\\s", "");
|
||||
|
||||
byte[] keyBytes = Base64.getDecoder().decode(pemContent);
|
||||
|
||||
// 尝试PKCS#8格式
|
||||
try {
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
return keyFactory.generatePrivate(keySpec);
|
||||
} catch (Exception e) {
|
||||
// 使用Bouncy Castle处理PKCS#1
|
||||
RSAPrivateKey rsaPrivKey = RSAPrivateKey.getInstance(keyBytes);
|
||||
return KeyFactory.getInstance("RSA").generatePrivate(
|
||||
new RSAPrivateKeySpec(rsaPrivKey.getModulus(), rsaPrivKey.getPrivateExponent()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("解析私钥失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析PKCS#1格式私钥
|
||||
*/
|
||||
private static PrivateKey parsePKCS1PrivateKey(byte[] keyBytes) {
|
||||
try {
|
||||
int length = keyBytes.length;
|
||||
byte[] pkcs8Header = new byte[] {
|
||||
0x30, (byte) 0x82,
|
||||
(byte) ((length + 26) >> 8), (byte) (length + 26), // 总长度
|
||||
0x02, 0x01, 0x00,
|
||||
0x30, 0x0D, 0x06, 0x09, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
|
||||
0x04, (byte) 0x82,
|
||||
(byte) (length >> 8), (byte) length // BIT STRING 长度
|
||||
};
|
||||
|
||||
byte[] pkcs8Key = new byte[pkcs8Header.length + keyBytes.length];
|
||||
System.arraycopy(pkcs8Header, 0, pkcs8Key, 0, pkcs8Header.length);
|
||||
System.arraycopy(keyBytes, 0, pkcs8Key, pkcs8Header.length, keyBytes.length);
|
||||
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8Key);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
return keyFactory.generatePrivate(keySpec);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("解析PKCS#1私钥失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析PEM格式公钥(兼容PKCS#1和PKCS#8格式)
|
||||
*/
|
||||
private static PublicKey parsePublicKey(String publicKeyPEM) {
|
||||
try {
|
||||
// 移除PEM头尾标记和空白字符
|
||||
String pemContent = publicKeyPEM
|
||||
.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.replace("-----END PUBLIC KEY-----", "")
|
||||
.replace("-----BEGIN RSA PUBLIC KEY-----", "")
|
||||
.replace("-----END RSA PUBLIC KEY-----", "")
|
||||
.replaceAll("\\s", "");
|
||||
|
||||
byte[] keyBytes = Base64.getDecoder().decode(pemContent);
|
||||
|
||||
// 先尝试PKCS#8格式
|
||||
try {
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
return keyFactory.generatePublic(keySpec);
|
||||
} catch (Exception e) {
|
||||
// 如果PKCS#8失败,尝试PKCS#1格式
|
||||
return parsePKCS1PublicKey(keyBytes);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析PKCS#1格式公钥
|
||||
*/
|
||||
private static PublicKey parsePKCS1PublicKey(byte[] keyBytes) {
|
||||
try {
|
||||
// PKCS#1 RSA公钥转换为PKCS#8格式
|
||||
byte[] pkcs8Prefix = new byte[] {
|
||||
0x30, (byte) 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, (byte) 0x86,
|
||||
0x48, (byte) 0x86, (byte) 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
|
||||
(byte) 0x82, 0x01, 0x0f, 0x00
|
||||
};
|
||||
|
||||
byte[] pkcs8Key = new byte[pkcs8Prefix.length + keyBytes.length];
|
||||
System.arraycopy(pkcs8Prefix, 0, pkcs8Key, 0, pkcs8Prefix.length);
|
||||
System.arraycopy(keyBytes, 0, pkcs8Key, pkcs8Prefix.length, keyBytes.length);
|
||||
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pkcs8Key);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
return keyFactory.generatePublic(keySpec);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package com.cool.store.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
*RSA-SHA256 验签工具类
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/11/12 15:15
|
||||
* @Version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class VerifySignatureUtils {
|
||||
|
||||
/**
|
||||
* 验证签名
|
||||
* @param params 参数Map(包含sign字段)
|
||||
* @param publicKeyStr Base64编码的公钥
|
||||
* @return 验签结果
|
||||
*/
|
||||
public static boolean verifySignature(Map<String, String> params, String publicKeyStr) {
|
||||
try {
|
||||
// 1. 从参数中提取签名(并移除,不参与签名串构造)
|
||||
String receivedSignature = params.get("sign");
|
||||
if (receivedSignature == null || receivedSignature.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("签名参数sign不能为空");
|
||||
}
|
||||
|
||||
// 2. 创建参数的副本,移除sign字段
|
||||
Map<String, String> paramsForSign = new HashMap<>(params);
|
||||
paramsForSign.remove("sign");
|
||||
|
||||
// 3. 构造签名串(与签名方相同的规则)
|
||||
String signString = buildSignString(paramsForSign);
|
||||
log.info("验签待签名串: {}", signString);
|
||||
|
||||
// 4. 验证签名
|
||||
return verifyRsaSha256(signString, receivedSignature, publicKeyStr);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("验签过程异常: ", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造签名串(与签名方相同的逻辑)
|
||||
*/
|
||||
private static String buildSignString(Map<String, String> params) {
|
||||
return params.entrySet().stream()
|
||||
.filter(entry -> entry.getValue() != null && !entry.getValue().trim().isEmpty())
|
||||
.sorted(Map.Entry.comparingByKey())
|
||||
.map(entry -> {
|
||||
try {
|
||||
String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name());
|
||||
return entry.getKey() + "=" + encodedValue;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("URL编码失败", e);
|
||||
}
|
||||
})
|
||||
.collect(Collectors.joining("&"));
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA-SHA256 验签
|
||||
*/
|
||||
private static boolean verifyRsaSha256(String data, String signature, String publicKeyStr) {
|
||||
try {
|
||||
// 1. 解码Base64公钥
|
||||
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
|
||||
|
||||
// 2. 创建X509编码密钥规范
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||
|
||||
// 3. 获取RSA KeyFactory
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
|
||||
// 4. 生成公钥对象
|
||||
PublicKey publicKey = keyFactory.generatePublic(keySpec);
|
||||
|
||||
// 5. 创建Signature实例
|
||||
Signature sig = Signature.getInstance("SHA256withRSA");
|
||||
sig.initVerify(publicKey);
|
||||
|
||||
// 6. 更新要验证的数据
|
||||
sig.update(data.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// 7. 解码收到的签名
|
||||
byte[] signatureBytes = Base64.getDecoder().decode(signature);
|
||||
|
||||
// 8. 执行验证
|
||||
return sig.verify(signatureBytes);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("RSA-SHA256验签失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user