package com.nova.sankuai.infra.utils; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; import com.alipay.api.domain.UserVo; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.*; 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; /** * @Description RSA非对称加密算法工具类 * @Author CWR * @Date 2022/3/21 20:26 */ @Component public class RsaSecretUtils { private static final String RSA = "RSA"; private static final String RSA_ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding"; private static final String SIGN_ALGORITHMS = "SHA1WithRSA"; /** * base64公钥 */ @Value("${loginrsa.key-pair.public}") private String publicKeyBase64; /** * base64私钥 */ @Value("${loginrsa.key-pair.private}") private String privateKeyBase64; /** * 生成秘钥对 * * @return * @throws Exception */ public KeyPair getKeyPair() throws Exception { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA); keyPairGenerator.initialize(2048); return keyPairGenerator.generateKeyPair(); } /** * 获取公钥(Base64编码) * * @param keyPair 秘钥对 * @return */ public String getPublicKey(KeyPair keyPair) { PublicKey publicKey = keyPair.getPublic(); byte[] bytes = publicKey.getEncoded(); return Base64Utils.encode(bytes); } /** * 获取私钥(Base64编码) * * @param keyPair 秘钥对 * @return */ public String getPrivateKey(KeyPair keyPair) { PrivateKey privateKey = keyPair.getPrivate(); byte[] bytes = privateKey.getEncoded(); return Base64Utils.encode(bytes); } // /** * 将Base64编码后的公钥转换成PublicKey对象 * * @param pubStr base64公钥 * @return * @throws Exception */ public static PublicKey string2PublicKey(String pubStr) throws Exception { // byte[] keyBytes = Base64Utils.decode(pubStr); // X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // KeyFactory keyFactory = KeyFactory.getInstance(RSA); // return keyFactory.generatePublic(keySpec); try { byte[] buffer = Base64Utils.decode(pubStr); KeyFactory keyFactory = KeyFactory.getInstance(RSA); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); return keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("公钥非法"); } catch (NullPointerException e) { throw new Exception("公钥数据为空"); } } /** * 将Base64编码后的私钥转换成PrivateKey对象 * * @param priStr base64私钥 * @return * @throws Exception */ public static PrivateKey string2PrivateKey(String priStr) throws Exception { byte[] keyBytes = Base64Utils.decode((priStr)); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA); return keyFactory.generatePrivate(keySpec); } /** * 公钥加密 * * @param content 内容 * @return * @throws Exception */ public byte[] publicEncrypt(byte[] content) throws Exception { PublicKey publicKey = string2PublicKey(this.publicKeyBase64); Cipher cipher = Cipher.getInstance(RSA); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(content); } /** * 公钥加密 * * @param content 明文 * @param publicKeyBase64 公钥base64 * @return */ public static byte[] publicEncrypt(byte[] content, String publicKeyBase64) { // PublicKey publicKey = string2PublicKey(publicKeyBase64); // Cipher cipher = Cipher.getInstance(RSA); // cipher.init(Cipher.ENCRYPT_MODE, publicKey); // return cipher.doFinal(content); try { Cipher cipher = Cipher.getInstance(RSA); // 编码前设定编码方式及密钥 PublicKey publicKey = string2PublicKey(publicKeyBase64); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int keyBit = getKeySize(publicKey); int inputLen = content.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; int step = keyBit / 8 - 11; for (int i = 0; inputLen - offSet > 0; offSet = i * step) { byte[] cache; if (inputLen - offSet > step) { cache = cipher.doFinal(content, offSet, step); } else { cache = cipher.doFinal(content, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); ++i; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 公钥加密 * * @param content 明文 * @param publicKeyBase64 公钥base64 * @return */ public static byte[] yqgPublicEncrypt(byte[] content, String publicKeyBase64) { try { Cipher cipher = Cipher.getInstance(RSA_ECB_PKCS1_PADDING); // 编码前设定编码方式及密钥 PublicKey publicKey = string2PublicKey(publicKeyBase64); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int keyBit = getKeySize(publicKey); int inputLen = content.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; int step = keyBit / 8 - 11; for (int i = 0; inputLen - offSet > 0; offSet = i * step) { byte[] cache; if (inputLen - offSet > step) { cache = cipher.doFinal(content, offSet, step); } else { cache = cipher.doFinal(content, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); ++i; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 公钥解密 */ public byte[] publicDecrypt(byte[] content) throws Exception { PublicKey publicKey = string2PublicKey(this.publicKeyBase64); Cipher cipher = Cipher.getInstance(RSA); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(content); } /** * 私钥解密 * * @param content 加密内容 * @param privateKey 私钥 * @return * @throws Exception */ public byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance(RSA); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(content); } /** * 私钥解密 * * @param content 密文 * @param privateKeyBase64 私钥base64 * @return * @throws Exception */ public static byte[] privateDecrypt(byte[] content, String privateKeyBase64) throws Exception { // PrivateKey privateKey = string2PrivateKey(privateKeyBase64); // Cipher cipher = Cipher.getInstance(RSA); // cipher.init(Cipher.DECRYPT_MODE, privateKey); // return cipher.doFinal(content); try { Cipher cipher = Cipher.getInstance(RSA); PrivateKey privateKey = string2PrivateKey(privateKeyBase64); cipher.init(Cipher.DECRYPT_MODE, privateKey); int keyBit = getKeySize(privateKey); int inputLen = content.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; int step = keyBit / 8; for (int i = 0; inputLen - offSet > 0; offSet = i * step) { byte[] cache; if (inputLen - offSet > step) { cache = cipher.doFinal(content, offSet, step); } else { cache = cipher.doFinal(content, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); ++i; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } catch (Exception e) { return null; } } /** * 洋钱罐私钥解密 * * @param content 密文 * @param privateKeyBase64 私钥base64 * @return */ public static byte[] yqgPrivateDecrypt(byte[] content, String privateKeyBase64) { try { Cipher cipher = Cipher.getInstance(RSA_ECB_PKCS1_PADDING); PrivateKey privateKey = string2PrivateKey(privateKeyBase64); cipher.init(Cipher.DECRYPT_MODE, privateKey); int keyBit = getKeySize(privateKey); int inputLen = content.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; int step = keyBit / 8; for (int i = 0; inputLen - offSet > 0; offSet = i * step) { byte[] cache; if (inputLen - offSet > step) { cache = cipher.doFinal(content, offSet, step); } else { cache = cipher.doFinal(content, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); ++i; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } catch (Exception e) { return null; } } /** * 私钥解密 * * @param content 加密内容 * @return * @throws Exception */ public byte[] privateDecrypt(byte[] content) throws Exception { Cipher cipher = Cipher.getInstance(RSA); PrivateKey privateKey = string2PrivateKey(this.privateKeyBase64); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(content); } /** * 私钥加密 */ public byte[] privateEncrypt(byte[] content) throws Exception { Cipher cipher = Cipher.getInstance(RSA); PrivateKey privateKey = string2PrivateKey(this.privateKeyBase64); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(content); } /** * 使用己方私钥对数据进行加签 * * @param encryptByte 数据 * @param privateKeyBase64 己方私钥Base64 * @return 加密后的签名 */ public static String rsaSign(byte[] encryptByte, String privateKeyBase64) { try { PrivateKey privateKey = string2PrivateKey(privateKeyBase64); Signature signature = Signature.getInstance(SIGN_ALGORITHMS); // Signature signature = Signature.getInstance("RSA/ECB/PKCS1 Padding"); signature.initSign(privateKey); signature.update(encryptByte); byte[] signed = signature.sign(); return Base64Utils.encode(signed); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 使用对方公钥对数据进行验签 * * @param encryptByte 数据 * @param bs 签名 * @param publicKeyBase64 对方公钥base64 * @return 是否篡改了数据 */ public static boolean rsaSignCheck(byte[] encryptByte, byte[] bs, String publicKeyBase64) { try { PublicKey publicKey = string2PublicKey(publicKeyBase64); Signature signature = Signature.getInstance(SIGN_ALGORITHMS); signature.initVerify(publicKey); signature.update(encryptByte); return signature.verify(bs); } catch (Exception e) { e.printStackTrace(); } return false; } public static void main(String[] args) throws Exception { // 私钥 String privateKey = "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"; // 公钥 String publicKey = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA+E33AcNuMBwJd/EH5o0j9xNkkGPu+l6R6R1m9CIN5GaVU18U9JyLTC7r7fjLqCvVSkgqiCJV6XJpAqoXAmKak0s0IfmxIcAiTucmN958TWYNeWjFVc/DtEYgIskVUunaBph8onwxVTKHQXx3FmdxeBlFZqVT1XfZ7QYouSAhBYI2ESz711tHzRe1BGdkBcctKYIKU4u5hLYpM24cU+c5TjNI9EdMXQLH3hAs6Cg98CJcxUAKVNztsj5rXiGUOaTJCZpdCSzfkgN6rFVV9jiDCghgLmQoLM0m5GVoGVchpiZQv+sVG3kTe37npE7T+jCzcVMdjj+FiANJSX27VyN9xJuBapyOCHgbto0EV4uLbtntEmP6ppwpXQW5xoPWn+5GF43MuiyWVHi93WtJ66hXyG72/9wKATzfS/bv/mvc6sysn3SA+NbfJt3vfmop5J0pFKSGI7KuBFtYXd9fyULYVAgDlqLiAXRahp5k4azbu+AnHfDCSAMuPCqhSKZChu+cAVWJCVtFOxc+kHicUQmkPXsiuE76fo0RZ+2z8XIqiuskVNKt7p3q7vZ0+zD13hBRVKQPbKFhCtLBUiO2XTPo+Qkx9ssJvbDfhoknkHHnizSBF/L4H3k0WSZNxs8gxocVSvXwd1/kUA5VZlZ8RvqjpX8whv+2q7YVutUUPzJCbfECAwEAAQ=="; System.out.println("私钥:" + privateKey); System.out.println("公钥:" + publicKey); ObjectMapper objectMapper = new ObjectMapper(); UserVo userVo = new UserVo(); userVo.setSite("10"); userVo.setAlipayUserId("50"); userVo.setSiteUserId("15"); String json = objectMapper.writeValueAsString(userVo); System.out.println("明文:" + json); // 使用公钥加密 byte[] encryptBytes = yqgPublicEncrypt(json.getBytes(StandardCharsets.UTF_8), publicKey); String encryptString = Base64Utils.encode(encryptBytes); System.out.println("密文:" + encryptString); // 篡改密文 UserVo userVo1 = new UserVo(); userVo.setSite("10"); userVo.setAlipayUserId("50"); userVo.setSiteUserId("15"); String json1 = objectMapper.writeValueAsString(userVo); System.out.println("篡改后明文:" + json1); // 使用公钥加密 byte[] encryptBytes1 = publicEncrypt(json.getBytes(StandardCharsets.UTF_8), publicKey); String encryptString1 = Base64Utils.encode(encryptBytes1); System.out.println("篡改后密文:" + encryptString); // 解密 byte[] decryptBytes = yqgPrivateDecrypt(Base64Utils.decode(encryptString), privateKey); String decryptString = new String(decryptBytes); // 解密后明文 System.out.println("解密后明文:" + decryptString); // // 加签 String sign = rsaSign(encryptBytes, privateKey); System.out.println("签名:" + sign); // // 验签 boolean pass = rsaSignCheck(Base64Utils.decode(encryptString), Base64Utils.decode(sign), publicKey); System.out.println("是否一致:" + pass); } /** * 获取公钥长度 * * @param publicKey 公钥 * @return */ public static int getKeySize(PublicKey publicKey) { RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; return rsaPublicKey.getModulus().bitLength(); } /** * 获取私钥长度 * * @param privateKey 私钥 * @return */ public static int getKeySize(PrivateKey privateKey) { RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey; return rsaPrivateKey.getModulus().bitLength(); } /** * 字节数组转Base64编码 * * @param bytes * @return */ public static String byte2Base64(byte[] bytes) { BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(bytes); } /** * Base64编码转字节数组 * * @param base64Key * @return * @throws IOException */ public byte[] base642Byte(String base64Key) throws IOException { BASE64Decoder decoder = new BASE64Decoder(); return decoder.decodeBuffer(base64Key); } /** * 支付宝公钥加密 * * @param content 内容 * @return * @throws Exception */ public String alipayPublicEncrypt(String content) throws Exception { //获得RSA对象 RSA rsa = new RSA(privateKeyBase64, publicKeyBase64); //公钥加密 String encrypt = rsa.encryptBase64(StrUtil.bytes(content, CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey); return encrypt; } }