验签加密MD5withRSA +AES

import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;


import com.alibaba.fastjson.JSONObject;
import sun.misc.BASE64Decoder;

public class SignatureUtils {

	
	
	/**
	 * MD5withRSA 客户端调用使用签名认证-数字签名
	 * @param params 参数
	 * @param secret 客户端手里的私钥  (私钥 和 公钥 是一对,要么由客户端生成,要么由服务端生成)
	 * @return
	 */
	public static String getSign(Map<String, String> params, String secret) throws Exception {
		Set<String> keySet = params.keySet();
		// 使用treeset 排序
		TreeSet<String> sortSet = new TreeSet<String>();
		sortSet.addAll(keySet);
		StringBuilder keyvalueStr = new StringBuilder();
		Iterator<String> it = sortSet.iterator();
		while (it.hasNext()) {
			String key = it.next();
			String value = params.get(key);
			keyvalueStr.append(key).append("=").append(value).append("&");
		}
		//获取私钥
		PrivateKey privateKey = getPrivateKey(secret);
		// 1.通过getInstance方法取得MD5withRSA实例  2.通过MD5进行数字摘要 ,3.使用RSA算法进行非对称加密
		Signature signature = Signature.getInstance("MD5withRSA");
		//使用私钥对signature初始化
		signature.initSign(privateKey);
		//keyvalueStr待摘要串
		signature.update(keyvalueStr.substring(0,keyvalueStr.length()-1).getBytes());
		//取得对应内容的数字签名串
		String sign = BytesConvertUtils.bytesToHexString(signature.sign());
		return sign;
	}
	
	
	/**
	 * PKCS8格式私钥 客户端使用私钥加密
	 * @return
	 */
	private static PrivateKey getPrivateKey(String key) throws Exception {
		PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(key));
		KeyFactory keyf = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyf.generatePrivate(priPKCS8);
		return privateKey;
	}
	
	
	
	/**
	 * MD5withRSA 使用公钥验证客户端的数字签名是否正确 防止连接数据被篡改
	 * @param params 服务端的参数
	 * @param sign 服务端的签名串
	 * @param publicSecret 公钥 (私钥 和 公钥 是一对,要么由客户端生成,要么由服务端生成)
	 * @return
	 * @throws Exception
	 */
	public static boolean validate(Map<String, String> params, String sign, String publicSecret) throws Exception {
		Set<String> keySet = params.keySet();
		// 使用treeset排序(默认自然排序按照首字母顺序,一种自带Comparator自定义来排序)
		TreeSet<String> sortSet = new TreeSet<String>();
		sortSet.addAll(keySet);
		Iterator<String> it = sortSet.iterator();
		StringBuilder keyvalueStr = new StringBuilder();
		while (it.hasNext()) {
			String key = it.next();
			String value = params.get(key);
			keyvalueStr.append(key).append("=").append(value).append("&");
		}
		//获取公钥
		PublicKey publicKey = getPublicKey(publicSecret);
		// 1.通过getInstance方法取得MD5withRSA实例  2.通过MD5进行数字摘要 ,3.使用RSA算法进行非对称加密
		Signature signature = Signature.getInstance("MD5withRSA");
		//使用公钥对signature初始化
		signature.initVerify(publicKey);
		//keyvalueStr待摘要串
		signature.update(keyvalueStr.substring(0,keyvalueStr.length()-1).getBytes());
		//对数字签名进行校验
		return signature.verify(BytesConvertUtils.hexStringToBytes(sign));
	}
	
	/**
	 * 公钥 服务器端使用公钥解密
	 * @return
	 */
	private static PublicKey getPublicKey(String key) throws Exception {
		X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(key));
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(bobPubKeySpec);
		return publicKey;
	}

	
	/**
	 * 测试 MD5withRSA 加密 和 解密
	 * @param args
	 */
	public static void main(String[] args) {
		/* 客户端生成签名 */
//		String privateSecret = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtFf8rpkRsy66BOwpS96VBNwxMj3ubwJd424YijNt/hVqChEZp537mhdO3hIJb4AyXXa7UmJKirw1aQ5wQ4KMiwIDAQABAkEAmNWIOp9WNLgAxXMufDGhsIC64I1Dp6gl0TvYaCa1rIElHUCAvT8jj3F0juYjNOKE6UOZ/mEMtNihmEfwezb34QIhANs78pVlgD46bUDu3i6tmvHZa5mhUHXbzTHrZduiv9WfAiEA0pZpv+BAlQ7i6iVuqMwVU+5eRKhomaz5H9fPJcmjaZUCIDeGCTwZBs+70Gu/k3nS8gkKfZvdJRmUX3WjHprvrxIVAiA30HnyyyMS3sExwf4UaxL0DeeaVvByWrAkynQy1cCkCQIgLb/ADZzVWkWkBE1tPAv2QwHOBrCJkRi5Lg9Qc8w/N5Q=";
		String privateSecret ="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQCJnIoDN1LlWWolWy3vgSMfGuaMk2fwtoOjllKQNuehJiwF1wCtSIkzZuUMKz7a3tmmd8Rg8LYqMQ3oTp0dOsp09pl76iNvww45Sm+blJ0dvCOH4yLmBikZtMeXoyzIAx6Jn2foQFLQx/rbWMky8IllfPaFlHipwJhd7m+zP3/ROetNBnHRZEWBj5E4SV27O6kxPPERQw36Z8crc5sAzpAdmPDfUkumVUDUFeZ2AxfUBuvRi5E4S0Qgh87RVVZ8VMU/QYYaOmVWDlTe36iWOVIvuS5qwdvRU4LrLy0J4LRF2EfgawPtYc+nX3b7B+aXE5l+yyo2n/NQU1F8KoU9iFAgMBAAECggEADcukNxO4ldq+vkCBolz64moBduln/n8qSH0j9TtlCNx7f6T2DUoKkgwBHguo/bmTQSBuIGWc9cpSufmnosHRYa+uqnfvol43Fx7garpAuU57XkPUyoscxSyWudmMavX4wlaEbz4wjw9Ptt/UHEBebBlcNVrcIMxmUJNaFsMtzRISoSw9VwLXE8jKc3Kd21ygiJUAsUxGQkS2e5YIxztKaWZFma1U4NadF7VkDM8JvLUB0s89Sum2XAr6IBRjrLn39COGEfFbQWaKJuJBUzL/zVWxAKGRybrjCA8+2HfW4FFOJMsRfBF/UbdwcfBKlZMxx/HsUqq91bshMK/0EUM/wQKBgQD2Kmp3ZDeDyNJNY6vNEDsny6XEzPTm/Q67shNLteb2ei9lazYEtAcv3cNgR92wO42Lej6NWsvJ3JLhULmh6NnqBDwgHECaNYNqzDy4oHuTmEafsRZUPdBBIOj/2Piuoe4OdD+BwiDAP0WeOOcErTNj9D6gscnCDqQZCbKRelt9fQKBgQDYWDNYOxTO//LBUfSKSM8WZ/HT/1funRSdBMaZgPQ6FqkLLL39CSzo/Bd4lEtVf3518BKf+djp+xDsy3L285W1sa5gU9AmJEGNoobjRUzmO+su3CATWdFzqsDgANPZuawqLuvM9myVJYaIuxLy3T2hLCeu7bPPQp9b3Ro4h6nVqQKBgQCW9nYqV9RPxlVqTmiqrnyIsDQt17+M9L4XT2LT+G720wHEAZa0Fa+epDJQFmKW1D6+va4kw/zcA6Az+2yMJZ+WCxjQXGMl7xFz6mKGmyyN3EHbZx+Zc/sGJeeeF3KSrg2u4Y2cxu+M1oCcQqsyTAGLF9tccwuXLaFnFXJkExSOhQKBgAwJLCIWd1vkxV6X7qDa2BqJAd0ncX7m4kSyBVJ46B1rMVBb1t4C6qqzi6K7rU0+YIyzJHYd8kFiJFjoIKc4efW3wtm9D/FvRu5YQmTWcCbG4piiym4JKyviLgTIRwDv4XIfViL6+qN5iPiGX9F/GXSj/jkvJDe9nxv/Ovw2H+6xAoGBAIG8pAIhstGXZEGnpFQwZrhPmzfVf1KlwrLvSysxnYsDIm7+Xj9/u4s3O+GFvGbAEl6YannN4GOJv5vLHegiedhuMxIil3ydjow5J6wa4wO+OMXAhNQfMD5K22yXZslUdkNTeaqQqxwmwA7bCUf2vLATrDkjmFS1YXY4ORy2u1gF";
		Map<String, String> params = new HashMap<String,String>();
		List<String> coins = new ArrayList<>();
		coins.add("ADC");
		coins.add("SDG");
		params.put("coins", JSONObject.toJSONString(coins));
		params.put("randomStr", "2E21EEGREG33");
		params.put("timestamp", String.valueOf(1620375990));
		String sing = null;
		try {
			sing = getSign(params,privateSecret);
			System.out.println("客户端生成的数字签名为:"+ sing);
		} catch (Exception e) {
			e.printStackTrace();
		}
		/*  服务端验证数字签名 */
		String publicSecret = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALRX/K6ZEbMuugTsKUvelQTcMTI97m8CXeNuGIozbf4VagoRGaed+5oXTt4SCW+AMl12u1JiSoq8NWkOcEOCjIsCAwEAAQ==";
		try {
			if(validate(params, sing, publicSecret)){
				System.out.println("签名验证通过");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

通过MD5withRSA 公钥验签,私钥加签,通过秘钥AES解密

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto; 


  /* 获取认证信息
     * 1.验签
     * 2.验签失败,直接返回
     * 3.验签成功,参数解密,调用接口
     *
     * @param vo
     * @return
     */
    @ApiOperation(value = "获取认证信息", notes = "获取认证信息")
    @PostMapping("/getAuthenticationInfo")
    public Map<String, Object> getAuthenticationInfo(@RequestBody @Valid AuthenticationInfoRequestVo vo) {
        log.info("获取认证信息接口 请求参数为:{}", JSONObject.toJSONString(vo));
        Map<String, String> params = new HashMap<String, String>(12);
        params.put("ciphertext", vo.getCiphertext());
        params.put("randomStr", vo.getRandomStr());
        params.put("timestamp", String.valueOf(vo.getTimestamp()));
        //验签
        //查询公钥
        Map<String, Object> publicKeyMap = this.puHuiYunService.getPuHuiYunPublicKey(PRIMARY_ID);
        if (RemoteCallResultCheck.isFail(publicKeyMap)) {
            log.error("查询公钥失败");
            return ApiRes.getInstance(ResultEnum.PU_HUI_YUN_NOT_EXISTS_PUBLIC_KEY_FAIL);
        }
        String publicSecret = RemoteCallResultCheck.getKeyByDataByData(publicKeyMap, "puhuiyunPublicKey", String.class);
        try {
            boolean signResult = SignatureUtils.validate(params, vo.getSign(), publicSecret);
            if (!signResult) {
                log.error("获取认证信息接口 验签失败");
                return ApiRes.getInstance(ResultEnum.PU_HUI_YUN_SIGN_FAIL);
            }
        } catch (Exception e) {
            log.error("获取认证信息接口 验签失败,异常为:{}", e);
            return ApiRes.getInstance(ResultEnum.PU_HUI_YUN_SIGN_FAIL);
        }
        //验签成功 解密
        String requestBody = "";
        //获取AES秘钥
        String aesSecretKey = RemoteCallResultCheck.getKeyByDataByData(publicKeyMap, "aesSecretKey", String.class);
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, Base64.decode(aesSecretKey));
        try {
            requestBody = aes.decryptStr(vo.getCiphertext(), CharsetUtil.CHARSET_UTF_8);
            log.info("获取认证信息接口 解密={}", vo.getCiphertext());
        } catch (Exception e) {
            log.error("获取认证信息接口  解密失败:", e);
        }
        if (StringUtils.isBlank(requestBody)) {
            return ApiRes.getInstance(ResultEnum.PARAMETER_ERROR);
        }
        JSONObject json = JSONObject.parseObject(requestBody);
        String phone = (String) json.get("phone");
        //feign调用接口
        String privateSecret = RemoteCallResultCheck.getKeyByDataByData(publicKeyMap, "seaPrivateKey", String.class);
        if (StringUtils.isBlank(privateSecret)) {
            log.error("查询私钥为空");
            return ApiRes.getInstance(ResultEnum.PU_HUI_YUN_NOT_EXISTS_PRIVATE_KEY_FAIL);
        }
        Map<String, Object> userAuthInfo = userAuthService.getUserAuthInfoByMobile(phone);
        if (RemoteCallResultCheck.isFail(userAuthInfo)) {
            log.error("根据手机号获取认证信息未认证{}",userAuthInfo);
            return userAuthInfo;
        }
        UserAuthInfoDto userAuthInfoDto = RemoteCallResultCheck.getData(userAuthInfo, UserAuthInfoDto.class);
        //AES 加密
        String ciphertext = aes.encryptHex(JSON.toJSONString(userAuthInfoDto));
        Map<String, String> result = new HashMap<String, String>(12);
        result.put("ciphertext", ciphertext);
        result.put("randomStr", IDUtil.nextUUID());
        result.put("timestamp", String.valueOf(System.currentTimeMillis()));
        String sign = null;
        try {
            log.info("根据手机号获取认证信息生成数字签名,入参={}", result);
            sign = SignatureUtils.getSign(result, privateSecret);
            result.put("sign", sign);
            log.info("根据手机号获取认证信息生成的数字签名为:" + sign);
        } catch (Exception e) {
            log.error("根据手机号获取认证信息接口 加签失败",e);
            return ApiRes.getInstance(ResultEnum.PU_HUI_YUN_ADD_SIGN_FAIL);
        }
        return ApiRes.getInstance(ResultEnum.SUCCESS, result);
    }

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值