package com.szwl.model.utils; import com.szwl.model.utils.constants.Algorithm; import com.szwl.model.utils.constants.CommonConst; import com.szwl.model.utils.exceptions.JPException; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; /** * RSA加解密的工具类 * @author chenyf * @date 2018-12-15 */ public class RSAUtil { public static final String DEFAULT_ENCRYPT_ALGORITHM = "RSA/ECB/PKCS1Padding"; public static final String SIGNATURE_ALGORITHM_SHA1 = "SHA1withRSA"; public static final String SIGNATURE_ALGORITHM_MD5 = "MD5withRSA"; public static final int KEY_SIZE = 1024; public static final String PUBLIC_KEY = "publicKey"; public static final String PRIVATE_KEY = "privateKey"; /** /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 116; /** /** * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; /** * 生成公私密钥对 * @return * @throws Exception */ public static Map genKeyPair() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(Algorithm.RSA); keyPairGen.initialize(KEY_SIZE); KeyPair keyPair = keyPairGen.generateKeyPair(); final Map keyMap = new HashMap(2); keyMap.put(PUBLIC_KEY, CodeUtil.base64Encode(keyPair.getPublic().getEncoded())); keyMap.put(PRIVATE_KEY, CodeUtil.base64Encode(keyPair.getPrivate().getEncoded())); return keyMap; } /** * 生成RSA签名串 * @param data 需要生成签名串的数据 * @param mchPrivateKey 商户私钥 * @return * @throws JPException */ public static String sign(String data, String mchPrivateKey, boolean isSha) throws JPException { try { byte[] dataBytes = data.getBytes(CommonConst.ENCODING_UTF_8); byte[] keyBytes = CodeUtil.base64Decode(mchPrivateKey); String algorithm = isSha ? SIGNATURE_ALGORITHM_SHA1 : SIGNATURE_ALGORITHM_MD5; PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); PrivateKey priKey = KeyFactory.getInstance(Algorithm.RSA).generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(algorithm); signature.initSign(priKey); signature.update(dataBytes); return HEXUtil.encode(CodeUtil.base64Encode(signature.sign())); }catch (Throwable e){ throw new JPException("生成RSA签名失败", e); } } /** * 验证RSA签名串 * @param data 需要验签的数据 * @param jpPublicKey 汇聚公钥 * @param sign 汇聚返回的签名串 * @return * @throws JPException */ public static boolean verify(String data, String jpPublicKey, String sign, boolean isSha) throws JPException { try { byte[] dataBytes = data.getBytes(CommonConst.ENCODING_UTF_8); byte[] signBytes = CodeUtil.base64Decode(HEXUtil.decode(sign)); String algorithm = isSha ? SIGNATURE_ALGORITHM_SHA1 : SIGNATURE_ALGORITHM_MD5; PublicKey publicK = getPublicKey(jpPublicKey); Signature signature = Signature.getInstance(algorithm); signature.initVerify(publicK); signature.update(dataBytes); return signature.verify(signBytes); }catch (Throwable e){ throw new JPException("RSA验签失败", e); } } /** * 使用RSA进行加密 * @param data 需要加密的数据 * @param jpPublicKey 汇聚公钥 * @return */ public static String encrypt(String data, String jpPublicKey) throws JPException { try{ byte[] dataBytes = data.getBytes(CommonConst.ENCODING_UTF_8); dataBytes = doCipher(dataBytes, jpPublicKey, true); return HEXUtil.encode(CodeUtil.base64Encode(dataBytes)); }catch(Throwable e){ throw new JPException("RSA加密失败", e); } } /** * 使用RSA进行解密 * @param data 需要解密的数据 * @param mchPrivateKey 商户私钥 * @return */ public static String decrypt(String data, String mchPrivateKey) throws JPException { try{ byte[] dataBytes = CodeUtil.base64Decode(HEXUtil.decode(data)); dataBytes = doCipher(dataBytes, mchPrivateKey, false); return new String(dataBytes, CommonConst.ENCODING_UTF_8); }catch(Throwable e){ throw new JPException("RSA解密失败", e); } } private static byte[] doCipher(byte[] dataBytes, String keyStr, boolean isEncrypt) throws Exception{ Key key; Cipher cipher; int maxBlock; if(isEncrypt){ maxBlock = MAX_ENCRYPT_BLOCK; key = getPublicKey(keyStr); cipher = Cipher.getInstance(DEFAULT_ENCRYPT_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, key); }else{ maxBlock = MAX_DECRYPT_BLOCK; byte[] keyBytes = CodeUtil.base64Decode(keyStr); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(Algorithm.RSA); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); } int offSet = 0, i = 0, inputLen = dataBytes.length; byte[] cache; ByteArrayOutputStream out = new ByteArrayOutputStream(); try{ // 对数据分段加密/解密 while (inputLen - offSet > 0) { if (inputLen - offSet > maxBlock) { cache = cipher.doFinal(dataBytes, offSet, maxBlock); } else { cache = cipher.doFinal(dataBytes, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * maxBlock; } return out.toByteArray(); } finally { out.close(); } } private static PublicKey getPublicKey(String publicKey) throws Exception{ byte[] keyBytes = CodeUtil.base64Decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(Algorithm.RSA); return keyFactory.generatePublic(x509KeySpec); } }