银联支付sdk乱塞全局加解密算法,导致的支付宝加解密类乱码的问题

本文转自我的博客,转载请申明地址:http://www.heartlifes.com/archives/4/

背景:###

1.现在版本的支付宝wap支付需要到支付宝后台获取一个token,该字段是加密返回的,需要调用RSA类进行解密 2.银联APP支付是直接给sdk包,然后调用sdk包做tn获取的,内部调用是个黑盒,开发是看不到的

现象:###

1.在不调用银联APP SDK进行初始化的情况下,支付宝WAP支付整体流程都是正确的,token能拿到,也能正常解密 2.在进行一次银联支付后,即银联SDK初始化后,支付宝WAP支付开始一直报错,现象为token加密字符串能获取,但是解密一直是乱码

原因:###

查看银联SDK后,发现在其CertUtil中有个init()静态方法,其调用方法中,有以下两行坑爹代码:

Security.insertProviderAt(new BouncyCastleProvider(), 1);
Security.addProvider(new BouncyCastleProvider());

这两行代码是什么意思呢? 在Security全局上下文环境,将BouncyCastleProvider这个算法类,直接变成默认算法类 导致了什么结果呢? 当你调用支付宝提供的RSA类的时候,默认的算法类从JDK自带的SUN RSA,变成了这个BouncyCastleProvider提供的RSA算法,直接导致和支付宝的加密算法不匹配,于是报错乱码。

解决:###

修改RSA类如下,手动指定算法的provider类

public class RSA {
	public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
	/**
	 * RSA验签名检查
	 * 
	 * @param content
	 *            待签名数据
	 * @param sign
	 *            签名值
	 * @param ali_public_key
	 *            支付宝公钥
	 * @param input_charset
	 *            编码格式
	 * @return 布尔值
	 */
	public static boolean verify(String content, String sign,
			String ali_public_key, String input_charset) {
		try {
			Provider provider = Security.getProvider("SunRsaSign");
			KeyFactory keyFactory = KeyFactory.getInstance("RSA", provider);
			byte[] encodedKey = Base64.decode(ali_public_key);
			PublicKey pubKey = keyFactory
					.generatePublic(new X509EncodedKeySpec(encodedKey));
			java.security.Signature signature = java.security.Signature
					.getInstance(SIGN_ALGORITHMS, provider);
			signature.initVerify(pubKey);
			signature.update(content.getBytes(input_charset));
			boolean bverify = signature.verify(Base64.decode(sign));
			return bverify;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	/**
	 * 解密
	 * 
	 * @param content
	 *            密文
	 * @param private_key
	 *            商户私钥
	 * @param input_charset
	 *            编码格式
	 * @return 解密后的字符串
	 */
	public static String decrypt(String content, String private_key,
			String input_charset) throws Exception {
		System.out.println("alipay decrypt content..." + content);
		System.out.println("alipay decrypt key..." + private_key);
		PrivateKey prikey = getPrivateKey(private_key);
		Provider provider = Security.getProvider("SunJCE");
		Cipher cipher = Cipher.getInstance("RSA", provider);
		cipher.init(Cipher.DECRYPT_MODE, prikey);
		InputStream ins = new ByteArrayInputStream(Base64.decode(content));
		ByteArrayOutputStream writer = new ByteArrayOutputStream();
		// rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
		byte[] buf = new byte[128];
		int bufl;
		while ((bufl = ins.read(buf)) != -1) {
			byte[] block = null;
			if (buf.length == bufl) {
				block = buf;
			} else {
				block = new byte[bufl];
				for (int i = 0; i < bufl; i++) {
					block[i] = buf[i];
				}
			}
			writer.write(cipher.doFinal(block));
		}
		return new String(writer.toByteArray(), input_charset);
	}
	/**
	 * 得到私钥
	 * 
	 * @param key
	 *            密钥字符串(经过base64编码)
	 * @throws Exception
	 */
	public static PrivateKey getPrivateKey(String key) throws Exception {
		byte[] keyBytes;
		keyBytes = Base64.decode(key);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		Provider provider = Security.getProvider("SunRsaSign");
		KeyFactory keyFactory = KeyFactory.getInstance("RSA", provider);
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}
}

最后吐槽一下银联的SDK,拜托大哥你以后代码写的不要那么暴力,稍微低调点OK?这么修改全局参数,直接会导致工程中其它加解密类全部趴窝

转载于:https://my.oschina.net/u/2420155/blog/481211

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值