package com.fshows.proxy.util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
/**
* RSA的签名及验签
*
*/
public class MyRsaUtil {
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 map
* 包含 sign_type、privateKey、charset
* @return
* @throws Exception
*/
public static String rsaSign(Map map, String privateKey, String charset) throws Exception {
PrivateKey priKey = null;
java.security.Signature signature = null;
String signType = "RSA";
String content = getSignContent(map);
map.put("content", content);
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));
}
/**
* 验签方法
*
* 参数的合成字符串格式: key1=value1&key2=value2&key3=value3...
* @param publicKey
* @param charset
* @return
*/
public static boolean rsaCheck(Map map, String publicKey, String charset) throws Exception {
java.security.Signature signature = null;
String sign = (String)map.get("sign");
String signType = "RSA";
String content = getSignCheckContentV1(map);
System.out.println(">>生成签名的参数为:" + content);
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()));
}
public static String getSignCheckContentV1(Map<String, String> params) {
if (params == null) {
return null;
} else {
params.remove("sign");
params.remove("sign_type");
params.remove("charset");
params.remove("publicKey");
StringBuffer content = new StringBuffer();
List<String> keys = new ArrayList(params.keySet());
Collections.sort(keys);
for(int i = 0; i < keys.size(); ++i) {
String key = (String)keys.get(i);
String value = (String)params.get(key);
content.append((i == 0 ? "" : "&") + key + "=" + value);
}
return content.toString();
}
}
public 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));
}
public 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));
}
/**
* 把参数合成成字符串
*
* @param sortedParams
* @return
*/
public static String getSignContent(Map<String, String> sortedParams) {
StringBuffer content = new StringBuffer();
// app_id,method,charset,sign_type,version,bill_type,timestamp,bill_date
// String[] sign_param = sortedParams.get("sign_param").split(",");// 生成签名所需的参数
// List<String> keys = new ArrayList<String>();
// for (int i = 0; i < sign_param.length; i++) {
// keys.add(sign_param[i]);
// }
List<String> keys = new ArrayList(sortedParams.keySet());
Collections.sort(keys);
int index = 0;
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = sortedParams.get(key);
if (StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value)) {
content.append((index == 0 ? "" : "&") + key + "=" + value);
index++;
}
}
return content.toString();
}
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);
}
}
}
测试类:
package com.fshows.proxy.util;
import com.google.common.collect.Maps;
import java.util.Map;
public class MyRsaTest {
//static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKLPSayxU0VNbM9oe7xfwlAsTN0993nueKh+M8ml2bdwx9exaz7oyDEy0zEpQlMGUf1v8208XJk2JzQ4VKHgJpBjR6sllcmkwEqawIBRdj+QR2xAMdhfTGbHNWVEBddmIgI7MD8uWqLWfQ4JfTpCDfn0NXh/4tbLeYAnxkhWu0ejAgMBAAECgYA87vfT+koAFgozVhd5WR2QhAQAicClker2pMUdI0Vosn0Y7P4GfXjvcOY58Acyq5rkD5I7v+uoK+xgTvTd4NaNej/ptxCkx5wAOw9SBM13LVVUpcuDgb73EmzYFwFJYtql+UEvIwqpLe9Fk/aYkOjoQtpVH5p9VcxD0m020GVggQJBAN4D1Z1U+JOkQO/vbqRINez+/kfxoVh9JOHpZ6w+Ja9smivw/MF33IPd7GGRRTZCKgdnBa8QJrMCfXHImqGu5s0CQQC7u1wOPYUqe/oQL54TDQPY7JAWTtAwB/FkAOasuSlngwysesnP+jFxQpSuI++fvIUoD9ORXqjpcJCAYBudCogvAkAnQzpV1p8XTScGx6sjdnnC7d1+T6cfBRKuuR5SgbMccPJa7wVkGZRv5aFWJ+C7lbvlDz0cFpkhc0FIDBf8m/fJAkEAhyXeo7HOSENwRm7BUd2ww12qbSTX43wUX3X2mqnCEO7bFOBgoQTwyySvfJ4KR+ijw6+BE8odt9B9dq25s1h9qQJBANDnb/ha0LDt1L3DefniaSUcO4hTi4KyX7GqL4hm3GRc0VO8dKY+g/7lmszqb++F9+7WLgph0uYXaVMFHU2a/PE=";
// static String publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiz0mssVNFTWzPaHu8X8JQLEzdPfd57niofjPJpdm3cMfXsWs+6MgxMtMxKUJTBlH9b/NtPFyZNic0OFSh4CaQY0erJZXJpMBKmsCAUXY/kEdsQDHYX0xmxzVlRAXXZiICOzA/Llqi1n0OCX06Qg359DV4f+LWy3mAJ8ZIVrtHowIDAQAB";
static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJXcI2q/AFyrQC9OzkoiYcQ7ThVSAy/YaJypVl3zYVAzKlYKJdViiDgjQ3zuDq6OMgZc3SeZi5b7ozcYJ/5NomDtrcjN61hpzWUhfIphIBxYhnWVRYhSKv70rFpKERWzD1GoG/kKI1AiYXFq+ugHG9vFxxg05+h1t0rLf0cO4SZDAgMBAAECgYAETIRXk5MXFXKJ6ODSD5puXqUmx2t/+91EYTcxCsJH4q/cN/5N2L2/noNZGhshtsKInDFb6XOvqRhNhEvhZ6i4w9YH5Mo8pK9Fw/UBRJHYVusRnMuqPomVqPLTNkEttNq84J1Sw421B4UxFcrzz1Z8nq1qMZ8aQjN7YFIl8W2ZwQJBANDEA9kIyXexflOAWNsVTKlYkstfwOb+EvVkCg3scWtwSJq9EFHNfkLs9uZvFDObsT+1KprvKiXmitNUsEsxVo0CQQC3xDkiWRqH6F4x1EPUDWkuK6KI6BakY+hiWS06dLcRF7f7pCsNPcZEdpMqqzNgzg+tAo71TS9tiS6RA5u5ZmQPAkAdv8D4nYrwFof06DZBSgC5pRiOCKAZip0zAMV6BHaJI+AExOpdbdYPPWtVnQCY9hfFB1EB8RDlg7vGr6vLm0VFAkEAmJ3iRWBy5ERbVk7PNiEdJTcf+Uum4kgHCwa8xTuBfjSQm/CvwIN5UgqYFmuwc8kuw6TITXkY1oODpPO2NLeQiQJBAM59Zu3CFECXCozawtrT6+L88Q/wK/Z4wfoQ/EYuj7nUAf3bwquWKB6lcByosOHxJBL9YtPVBYd38tkrNmEXR/I=";
static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCV3CNqvwBcq0AvTs5KImHEO04VUgMv2GicqVZd82FQMypWCiXVYog4I0N87g6ujjIGXN0nmYuW+6M3GCf+TaJg7a3IzetYac1lIXyKYSAcWIZ1lUWIUir+9KxaShEVsw9RqBv5CiNQImFxavroBxvbxccYNOfodbdKy39HDuEmQwIDAQAB";
public static void main(String[] args) throws Exception {
Map map = Maps.newHashMap();
map.put("app_id", "123");
map.put("method", "test");
String result = MyRsaUtil.rsaSign(map, privateKey, "utf-8");
System.out.println(result);
System.out.println("----------------");
Map map2 = Maps.newHashMap();
map2.put("app_id", "123");
map2.put("method", "test");
map2.put("sign", result);
boolean flag = MyRsaUtil.rsaCheck(map2, publicKey, "utf-8");
System.out.println(flag);
}
}