package org.springblade.pay.utils;

import cn.hutool.core.codec.Base64;
import com.alibaba.druid.util.StringUtils;

import java.nio.charset.StandardCharsets;
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.Map;
import java.util.TreeMap;
public class RsaUtil extends CzcbRasUtil {

	/**
	 * 加密算法RSA
	 */
	public static final String KEY_ALGORITHM = "RSA";

	/**
	 * 签名算法
	 */
	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";



	/**
	 * <p>
	 * 公钥验签
	 * </p>

	 * @param publicKey
	 *            公钥(BASE64编码)
	 * @return
	 * @throws Exception
	 */
	public static boolean validateSignByPublicKey(Map<String,Object> map,  String publicKey, String signedData) throws Exception {
		String paramStr= paramToStr(map);
		System.out.println(paramStr);
		byte[] keyBytes = Base64.decode(publicKey);
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		PublicKey publicK = keyFactory.generatePublic(keySpec);
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initVerify(publicK);
		signature.update(paramStr.getBytes("utf-8"));
		return signature.verify(Base64.decode(signedData));
	}


	/**
	 * <p>
	 * 私钥签名
	 * </p>
	 *
	 *            源数据
	 * @param privateKey
	 *            私钥(BASE64编码)
	 * @return
	 * @throws Exception
	 */
	public static String signByPrivateKey(Map<String,Object> map, String privateKey) throws Exception {
		String dataStr=paramToStr(map);
		return RSAWithSoftware.signByPrivateKey(dataStr, privateKey);
	}




	private static String paramToStr(Map<String, Object> paramMap){
		StringBuilder str=new StringBuilder();
		//组装签名参数
		Map<String, Object> resultMap = new TreeMap<String, Object>();

		resultMap.putAll(paramMap);


		for(String key : resultMap.keySet()){
			if("sign_type".equals(key)||"sign".equals(key)){
				continue;
			}

			if(paramMap.get(key)==null || StringUtils.isEmpty(paramMap.get(key).toString())){
				continue;
			}

			str.append(key);
			str.append("=");
			str.append(paramMap.get(key).toString());
			str.append("&");
		}
		return str.deleteCharAt(str.length()-1).toString();
	}


}
