java后端开发过程中,涉及比较私密性的业务或者数据传输都经常会用到加密还有数据验签操作,这边就居于这样的业务场景,我分享两个比较经常用到的加密和验签工具类。
1.请求参数分为head body head中保存签名
2.签名生成流程(body中的请求参数,按照一定规则拼接,然后用rsa私钥加密拼接后的字符串,然后拿这个加密后的串用被调用方指定的验签私钥生成验签)
3.body内容在通过rsa私钥加密
这个过程需要自己生成rsa公钥私钥一对,私钥用来加密body内容,公钥提供给对方解密用,被调用方提供私钥给我们生成签名
经常用到的请求内容加密工具类:
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BodyEncryptUtil {
private static final Logger logger = LoggerFactory.getLogger(BodyEncryptUtil.class);
private static String CHARSET = "UTF-8";
private static String ALGORITHM = "AES";
private static String MODE = "AES/ECB/PKCS5Padding";
/**
* 加密方法----对业务请求体加密
* @param data 要加密的明文
* @param key 私钥
* @return
*/
public static String encrypt(String data, String key) {
try {
byte[] dataBytes = data.getBytes(CHARSET);
byte[] keyBytes = key.getBytes(CHARSET);
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, ALGORITHM);
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.ENCRYPT_MODE, seckey);
byte[] result = cipher.doFinal(dataBytes);
return new String(Base64.encodeBase64(result));
} catch (Exception e) {
logger.error( " 请求业务参数加密出错,加密内容为:"+data,e);
throw new RuntimeException("encrypt fail!", e);
}
}
/**
* 解密方法----对业务请求体解密
* @param data
* @param key
* @return
*/
public static String decrypt(String data, String key) {
try {
byte[] dataBytes = Base64.decodeBase64(data.getBytes(CHARSET));
byte[] keyBytes = key.getBytes(CHARSET);
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, ALGORITHM);
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.DECRYPT_MODE, seckey);
byte[] result = cipher.doFinal(dataBytes);
return new String(result, CHARSET);
} catch (Exception e) {
logger.error( " 业务参数解密出错,加密内容为:"+data,e);
throw new RuntimeException("decrypt fail!", e);
}
}
}
经常用来生成验签和验证验签的工具类:
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SignUtil {
private static final Logger logger = LoggerFactory.getLogger(SignUtil.class);
private static final String ENCODING = "UTF-8";
private static final String SIGNATURE_ALGORITHM = "SHA256WithRSA";
/**
* SHA256WithRSA签名
* @param data
* @param privateKey
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
* @throws SignatureException
* @throws UnsupportedEncodingException
*/
public static byte[] sign256(String data, PrivateKey privateKey) {
try {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(data.getBytes(ENCODING));
return signature.sign();
} catch (Exception e) {
logger.error(" 获取签名出错: ",e);
}
return null;
}
/**
* 验证签名
* @param data
* @param sign
* @param publicKey
* @return
*/
public static boolean verify256(String data, byte[] sign, PublicKey publicKey){
if(data == null || sign == null || publicKey == null){
return false;
}
try {
Signature signetcheck = Signature.getInstance(SIGNATURE_ALGORITHM);
signetcheck.initVerify(publicKey);
signetcheck.update(data.getBytes("UTF-8"));
return signetcheck.verify(sign);
} catch (Exception e) {
logger.error(" 验证签名出错: ",e);
return false;
}
}
/**
* 生成签名 --------------------------生成签名方法
* @param content 用来生成签名的字符串
* @param privateKey 私钥
* @return
*/
public static String sign(String content, String privateKey) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey.getBytes()));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(content.getBytes(ENCODING));
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
} catch (Exception e) {
logger.error(" 生成签名出现错误:",e);
}
return null;
}
/**
* 验证签名--------------------------验证签名方法
* @param content 用来匹配到的明文
* @param sign 签名串
* @param publicKey 公钥
* @return
*/
public static boolean checkSign(String content, String sign, String publicKey){
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] encodedKey = Base64.decodeBase64(publicKey);
PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
Signature signetcheck = Signature.getInstance(SIGNATURE_ALGORITHM);
signetcheck.initVerify(pubKey);
signetcheck.update(content.getBytes("UTF-8"));
return signetcheck.verify(Base64.decodeBase64(sign));
}catch (Exception e) {
logger.error(" 验证签名出现错误:",e);
}
return false;
}
/**
* 二进制数据编码为BASE64字符串
* @param data
* @return
*/
public static String encodeBase64(byte[] bytes){
return new String(Base64.encodeBase64(bytes));
}
/**
* BASE64解码
* @param bytes
* @return
*/
public static byte[] decodeBase64(byte[] bytes) {
byte[] result = null;
try {
result = Base64.decodeBase64(bytes);
} catch (Exception e) {
return null;
}
return result;
}
}