前段时间做的银联支付,折腾了好久,拼凑的一些代码,有需要的朋友可以参考,本人.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> /// 取得证书的公钥 /// </summary> /// <param name="cerPath">证书的绝对路径</param> /// <returns></returns> public static String GetPublicKey(string cerPath) { X509Certificate2 cer = new X509Certificate2(cerPath); string publicKey = cer.PublicKey.Key.ToXmlString(false); return publicKey; } } }
下面是3DES的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography; namespace Kad.ThridParty.ChinaPayWap { /// <summary> /// 对称加密3DES加解密,代码来源于网络 /// </summary> internal class TripleDESHelper { /// <summary> /// 加密 /// </summary> /// <param name="toEncrypt">要加密的字符串,即明文</param> /// <param name="key">公共密钥</param> /// <param name="useHashing">是否使用MD5生成机密秘钥</param> /// <returns>加密后的字符串,即密文</returns> public static string Encrypt(string toEncrypt, string key, bool useHashing) { try { byte[] keyArray; byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt); if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = keyArray; tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } catch { } return string.Empty; } public static string Encrypt(byte[] toEncryptArray, string key, bool useHashing) { try { byte[] keyArray; //byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt); if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = keyArray; tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } catch { } return string.Empty; } /// <summary> /// 解密 /// </summary> /// <param name="toDecrypt">要解密的字符串,即密文</param> /// <param name="key">公共密钥</param> /// <param name="useHashing">是否使用MD5生成机密密钥</param> /// <returns>解密后的字符串,即明文</returns> public static string Decrypt(string toDecrypt, string key, bool useHashing) { try { byte[] keyArray; byte[] toEncryptArray = Convert.FromBase64String(toDecrypt); if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = keyArray; tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return UTF8Encoding.UTF8.GetString(resultArray); } catch { } return string.Empty; } public static string Decrypt(byte[] toEncryptArray, string key, bool useHashing) { try { byte[] keyArray; //byte[] toEncryptArray = Convert.FromBase64String(toDecrypt); if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = keyArray; tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return UTF8Encoding.UTF8.GetString(resultArray); } catch { } return string.Empty; } } }