RSA签名验签通用类
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RsaUtils {
private static final Logger logger = LoggerFactory.getLogger(RsaUtils.class);
private static final int DEFAULT_BUFFER_SIZE = 8192;
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
*
* RSA2签名
* @param content 待签名的字符串
* @param privateKey rsa私钥字符串
* @param charset 字符集编码
* @return 签名结果
*/
public static String rsaSign(String content, String privateKey, String charset) {
try {
PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(priKey);
if (StringUtils.isBlank(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
} catch (Exception e) {
logger.error("RSA签名异常:{}", e.getMessage(), e);
return null;
}
}
/**
* RSA2验签
*
* @param content 被签名的内容
* @param sign 签名后的结果
* @param publicKey rsa公钥
* @param charset 字符集编码
* @return 验签结果
*/
public static boolean doCheck(String content, String sign, String publicKey, String charset) {
try {
PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initVerify(pubKey);
signature.update(getContentBytes(content, charset));
return signature.verify(Base64.decodeBase64(sign.getBytes()));
} catch (Exception e) {
logger.error("RSA验签异常:{}", e.getMessage(), e);
return false;
}
}
/**
*
* RSA公钥加密
* @param content 待加密的内容
* @param publicKey 公钥
* @param charset 字符集编码
* @return 密文
*/
public static String rsaEncrypt(String content, String publicKey, String charset) {
ByteArrayOutputStream out = null;
try {
PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
int inputLen = content.getBytes().length;
out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(content.getBytes(charset), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(content.getBytes(charset), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
return Base64.encodeBase64String(encryptedData);
} catch (Exception e) {
logger.error("RSA公钥加密异常:{}", e.getMessage(), e);
return null;
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
logger.error("RSA公钥加密IOException异常:{}", e.getMessage(), e);
}
}
}
}
/**
*
* RSA私钥解密
* @param content 加密字符串
* @param privateKey 私钥
* @param charset 字符集编码
* @return 明文
*/
public static String rsaDecrypt(String content, String privateKey, String charset) {
ByteArrayOutputStream out = null;
try {
PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));
// RSA解密
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, priKey);
byte[] dataBytes = Base64.decodeBase64(content);
int inputLen = dataBytes.length;
out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
// 解密后的内容
return new String(decryptedData, charset);
} catch (Exception e) {
logger.error("RSA私钥解密异常:{}", e.getMessage(), e);
return null;
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
logger.error("RSA私钥解密IOException异常:{}", e.getMessage(), e);
}
}
}
}
/**
*
* 获取私钥对象
* @param algorithm 签名方式
* @param ins 私钥流
* @return
* @throws Exception
*/
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, "utf-8", true).getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
/**
*
* 获取公钥对象
* @param algorithm 签名方式
* @param ins 公钥流
* @return
* @throws NoSuchAlgorithmException
*/
private static PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) {
try {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
StringWriter writer = new StringWriter();
io(new InputStreamReader(ins), writer, true, true);
byte[] encodedKey = writer.toString().getBytes();
// 先base64解码
encodedKey = Base64.decodeBase64(encodedKey);
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
} catch (InvalidKeySpecException e) {
logger.error("获取公钥对象InvalidKeySpecException异常:{}", e.getMessage(), e);
} catch (NoSuchAlgorithmException e) {
logger.error("获取公钥对象NoSuchAlgorithmException异常:{}", e.getMessage(), e);
}
return null;
}
/**
*
* 生成RSA公、私钥对
* @return 公私钥对map
* @throws Exception
*/
public static Map<String, String> generateRSAKeyPairs() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, String> keyMap = new HashMap<String, String>(2);
keyMap.put("publicKey", Base64.encodeBase64String(publicKey.getEncoded()));
keyMap.put("privateKey", Base64.encodeBase64String(privateKey.getEncoded()));
return keyMap;
}
/**
*
* 获取字符串对应编码的字节
* @param content 字符串内容
* @param charset 字符集编码
* @return
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) throws UnsupportedEncodingException {
if (StringUtils.isEmpty(charset)) {
return content.getBytes();
}
return content.getBytes(charset);
}
/**
*
* 将指定输入流的所有文本全部读出到一个字符串中
* @param in 输入流
* @param charset 字符集编码
* @param closeIn 是否关闭流
* @return
* @throws IOException
*/
private static String readText(InputStream in, String charset, boolean closeIn) throws IOException {
Reader reader = charset == null ? new InputStreamReader(in) : new InputStreamReader(in, charset);
return readText(reader, closeIn);
}
/**
*
* 将指定<code>Reader</code>的所有文本全部读出到一个字符串中
* @param in 输入流
* @param closeIn 是否关闭流
* @return
* @throws IOException
*/
private static String readText(Reader in, boolean closeIn) throws IOException {
StringWriter out = new StringWriter();
io(in, out, closeIn, true);
return out.toString();
}
/**
*
* 从输入流读取内容,写入到输出流中
* @param in 输入流
* @param out 输出流
* @param closeIn 是否关闭流
* @param closeOut 是否关闭流
* @throws IOException
*/
private static void io(Reader in, Writer out, boolean closeIn, boolean closeOut) {
int bufferSize = DEFAULT_BUFFER_SIZE >> 1;
char[] buffer = new char[bufferSize];
int amount;
try {
while ((amount = in.read(buffer)) >= 0) {
out.write(buffer, 0, amount);
}
out.flush();
} catch (Exception e) {
logger.error("从输入流读取内容,写入到输出流中异常:{}", e.getMessage(), e);
} finally {
if (closeIn) {
try {
in.close();
} catch (IOException e) {
logger.error("从输入流读取内容,写入到输出流中异常:{}", e.getMessage(), e);
}
}
if (closeOut) {
try {
out.close();
} catch (IOException e) {
logger.error("从输入流读取内容,写入到输出流中异常:{}", e.getMessage(), e);
}
}
}
}
/**
*
* 除去数组中的空值和签名参数
* @param params 签名参数对象
* @return 去掉空值与签名参数后的新签名参数组
*/
public static Map<String, String> paraFilter(Map<String, String> params) {
Map<String, String> result = new HashMap<String, String>();
if (params == null || params.size() <= 0) {
return result;
}
for (String key : params.keySet()) {
String value = params.get(key);
if (value == null || value.equals("") || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type")) {
continue;
}
result.put(key, value);
}
return result;
}
/**
*
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
* @param params 需要排序并参与字符拼接的参数对象
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
}