支付宝对接RSA加解签及ILLEGAL_SIGN踩坑
ILLEGAL_SIGN
踩坑记:需对sign值进行URLEncoder
编码
RSA加解签
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import java.io.*;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSA {
private static final String SIGN_TYPE_RSA = "RSA";
private static final String SIGN_TYPE_RSA2 = "RSA2";
private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
private static final int DEFAULT_BUFFER_SIZE = 8192;
/**
* RSA/RSA2 加签
* @param signType
* @param privateKey
* @param content
* @param charset
* @return
* @throws Exception
*/
public static String rsaSign(String signType, String privateKey, String content, String charset) throws Exception {
PrivateKey priKey = null;
Signature signature = null;
if (SIGN_TYPE_RSA.equals(signType)) {
priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes()));
signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
} else if (SIGN_TYPE_RSA2.equals(signType)) {
priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes()));
signature = java.security.Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
} else {
throw new Exception("不是支持的签名类型: signType=" + signType);
}
signature.initSign(priKey);
if (StringUtils.isEmpty(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
}
/**
* 验签方法
*
* @param content 参数的合成字符串格式: key1=value1&key2=value2&key3=value3
* @param signType
* @param sign
* @param publicKey
* @param content
* @param charset
* @return
*/
public static boolean rsaVerify(String signType, String sign, String publicKey, String content, String charset) throws Exception {
java.security.Signature signature = null;
PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));
if (SIGN_TYPE_RSA.equals(signType)) {
signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
} else if (SIGN_TYPE_RSA2.equals(signType)) {
signature = java.security.Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
} else {
throw new Exception("不是支持的签名类型: signType=" + signType);
}
signature.initVerify(pubKey);
if (StringUtils.isEmpty(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
private static PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
if (ins == null || StringUtils.isEmpty(algorithm)) {
return null;
}
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
byte[] encodedKey = readText(ins).getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
private static PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
StringWriter writer = new StringWriter();
io(new InputStreamReader(ins), writer, -1);
byte[] encodedKey = writer.toString().getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
}
private static String readText(InputStream ins) throws IOException {
Reader reader = new InputStreamReader(ins);
StringWriter writer = new StringWriter();
io(reader, writer, -1);
return writer.toString();
}
private static void io(Reader in, Writer out, int bufferSize) throws IOException {
if (bufferSize == -1) {
bufferSize = DEFAULT_BUFFER_SIZE >> 1;
}
char[] buffer = new char[bufferSize];
int amount;
while ((amount = in.read(buffer)) >= 0) {
out.write(buffer, 0, amount);
}
}
}
ILLEGAL_SIGN解决
private String getSign(String signType, String signKey, String content, String inputCharset) {
String sign = "";
if ("MD5".equalsIgnoreCase(signType)) {
sign = MD5.sign(content, signKey, inputCharset);
} else if ("RSA".equalsIgnoreCase(signType) || "RSA2".equalsIgnoreCase(signType)) {
try {
sign = RSA.rsaSign(signType, privateKey, content, inputCharset);
sign = URLEncoder.encode(sign, inputCharset); //解决ILLEGAL_SIGN
} catch (Exception e) {
}
}
return sign;
}
MD5加解签
import org.apache.commons.codec.digest.DigestUtils;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
public class MD5 {
/**
* 签名字符串
*
* @param text 需要签名的字符串
* @param key 密钥
* @param charset 编码格式
* @return 签名结果
*/
public static String sign(String text, String key, String charset) {
text = text + key;
return DigestUtils.md5Hex(getContentBytes(text, charset));
}
/**
* 签名字符串
*
* @param text 需要签名的字符串
* @param sign 签名结果
* @param key 密钥
* @param charset 编码格式
* @return 签名结果
*/
public static boolean verify(String text, String sign, String key, String charset) {
text = text + key;
String mySign = DigestUtils.md5Hex(getContentBytes(text, charset));
if (mySign.equals(sign)) {
return true;
} else {
return false;
}
}
/**
* @param content
* @param charset
* @return
* @throws SignatureException
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
}
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/19/alipay-access-rsa-add-verify-sign-and-illegal-sign/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
THE END
0
二维码
打赏
海报
支付宝对接RSA加解签及ILLEGAL_SIGN踩坑
ILLEGAL_SIGN踩坑记:需对sign值进行URLEncoder编码
RSA加解签
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUt……
文章目录
关闭
共有 0 条评论