日期:2014-05-17 浏览次数:20965 次
前段时间做的银联支付,折腾了好久,拼凑的一些代码,有需要的朋友可以参考,本人.Net新手,不保证准确性!
这个银联手机支付没有SDK提供,技术支持也没有.Net的,真心不好搞!
RSA加解密,这里有个麻烦就是私钥加密/公钥解密;
3DES加解密,这里有个问题是所用的密钥长度不一样,银联向我们发送报文时密钥用32字节长度的,我们.Net最多用24字节,办法是直接取密钥前24字节就行了;
下面是RSA算法的加解密,用到一个BigInteger类(http://www.codeproject.com/csharp/biginteger.asp):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography; namespace Kad.ThridParty.ChinaPayWap { /// <summary> /// 非对称RSA加解密,私钥加密/公钥解密 /// 仅用于银联Wap支付报文收发 /// By : EnVon(E旺) 2013-08-20 /// </summary> internal class RSAHelper { /// <summary> /// RSA加密(用私钥加密哟) /// </summary> /// <param name="key">私钥</param> /// <param name="data">待加密的数据</param> /// <returns></returns> public static byte[] Encrypt(String key, byte[] data) { //由密钥xml取得RSA对象 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(key); //取得加密时使用的2个参数 RSAParameters par = rsa.ExportParameters(true); BigInteger mod = new BigInteger(par.Modulus); BigInteger ep = new BigInteger(par.D); //计算填充长度 int mLen = par.Modulus.Length; int fLen = mLen - data.Length - 3; //组建bytes List<byte> lis = new List<byte>(); lis.Add(0x00); lis.Add(0x01);//兼容java for (int i = 0; i < fLen; i++) lis.Add(0xff); lis.Add(0x00); lis.AddRange(data); byte[] bytes = lis.ToArray(); //加密就这么简单? BigInteger m = new BigInteger(bytes); BigInteger c = m.modPow(ep, mod); return c.getBytes(); } /// <summary> /// RSA解密(用公钥解密哟) /// </summary> /// <param name="key">公钥</param> /// <param name="data">待解密的数据</param> /// <returns></returns> public static byte[] Decrypt(String key, byte[] data) { //由密钥xml取得RSA对象 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(key); //取得解密时使用的2个参数 RSAParameters par = rsa.ExportParameters(false); BigInteger mod = new BigInteger(par.Modulus); BigInteger ep = new BigInteger(par.Exponent); //解密? BigInteger m = new BigInteger(data); BigInteger c = m.modPow(ep, mod); byte[] bytes = c.getBytes(); //去掉填充域(头部可能填充了一段0xff) byte flag = 0; for (int i = 1/*我从1开始啦*/; i < bytes.Length; i++) { if (bytes[i] == flag && i != (bytes.Length - 1)) { byte[] retBytes = new byte[bytes.Length - i - 1]; Array.Copy(bytes, i + 1, retBytes, 0, retBytes.Length); return retBytes; } } return bytes; } /// <summary> /// 取得证书私钥 /// </summary> /// <param name="pfxPath">证书的绝对路径</param> /// <param name="password">访问证书的密码</param> /// <returns></returns> public static String GetPrivateKey(string pfxPath, string password) { X509Certificate2 pfx = new X509Certificate2(pfxPath, password, X509KeyStorageFlags.Exportable); string privateKey = pfx.PrivateKey.ToXmlString(true); return privateKey; } /// <summary> /// 取得证书的公