原文及更多文章请见个人博客:http://heartlifes.com
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类
package com.wonders.test; 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://www.cnblogs.com/heartlifes/p/6970981.html
相关资源:JAVA上百实例源码以及开源项目