内容:Pfx证书,同时包含了公钥信息和私钥信息。
作用:保证了数据在传输过程中的安全性。
用法:私钥请求的数据进行签名,公钥对响应的数据进行验证签名。
代码:
第一步:将请求的数据进行ascii字典序,并添加Dictionary字典集合中。注意了(SortedDictionary<(Of <(TKey, TValue>)>) 和 SortedList<(Of <(TKey, TValue>)>) 都不是按照ascii排序的)正真的ascii字典序在下面:
string[] keys = { "requestNo", "version", "transId", "agentId","cityId", "registerAddress", "regNo", "regMoney", "regAddress", "spIcp", "remarks", "cardNoCipher", "cardName", "cardBankNo"};//要请求数据变量名
Array.Sort(keys, string.CompareOrdinal); //对请求数据变量名ascii排序
Dictionary<string, string> dictReq = new Dictionary<string, string>();//实例化字典集合对象
for (int i = 0; i <14; i++) //遍历keys数组
{
string formData = Request.Form[keys[i]];//获取请求数据变量名获取对应的表单内的值。
if (!String.IsNullOrEmpty(formData)) //判断取出的值是否为空
{
dictReq.Add(keys[i], formData); //如果不为空,将变量名和值添加到dictReq字典集合中
}
}
ascii字典序
第二步:将请求的数据进行签名。(证书存放路径:F:/API/cer/test.pdf 私钥密码 123456 接口请求路径:
http://192.168.1.104:8010/interface)
string privateKeyUrl = "F:/API/cer/test.pdf";//私钥证书路径
string privateKeyPwd = "123456"//私钥证书密码
string signData = signature(dictReq, privateKeyUrl, privateKeyPwd);//请求数据签名
/// <summary>
/// 签名
/// </summary>
/// <param name="dictReq">签名数据</param>
/// <param name="privateKey">私钥</param>
/// <param name="privateKeyPwd">私钥密码</param>
/// <returns>返回post请求数据</returns>
public string signature(Dictionary<string, string> dictReq, string privateKey, string privateKeyPwd)
{
string postData = ""; //url编码的post请求数据
string signStr = ""; //待签名数据
foreach (KeyValuePair<string, string> kvp in dictReq) //遍历键值对
{
if (kvp.Value == "") continue;//如果值为空,不参与签名
if (kvp.Key != "signature") postData += kvp.Key + "=" + HttpUtility.UrlEncode(kvp.Value) + "&"; //拼接url编码的
post请求数据
if (kvp.Value != "") signStr += kvp.Key + "=" + kvp.Value + "&"; //拼接待签名数据
}
string signatureData = SignData(signStr.TrimEnd('&'),privateKey,privateKeyPwd);//签名
return postData.TrimEnd('&') + "&signature=" + HttpUtility.UrlEncode(signatureData);返回post请求数据
}
/// <summary>
/// 将数据SHA1签名
/// </summary>
/// <param name="content">待签名字符串</param>
/// <param name="privateKey">私钥证书</param>
/// <param name="privateKeyPwd">私钥密码</param>
/// <returns>已签名base64编码数据</returns>
public string SignData(string content,string privateKey,string privateKeyPwd)
{
X509Certificate2 cert = new X509Certificate2(privateKey,privateKeyPwd, X509KeyStorageFlags.MachineKeySet);//加载证
书实体
RSACryptoServiceProvider rsapri = (RSACryptoServiceProvider)cert.PrivateKey; //获取私钥证书
RSAPKCS1SignatureFormatter f = new RSAPKCS1SignatureFormatter(rsapri);
byte[] result;
f.SetHashAlgorithm("SHA1");
SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
result = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(content));
return System.Convert.ToBase64String(f.CreateSignature(result)).ToString();
}
签名
第三步:发送POST请求,获取返回结果(Post,Form)
string postUrl = "http://192.168.1.104:8010/interface";//post请求地址
string resultData = TransSubmit(signData, postUrl);//发送POST请求,获取返回结果(Post,Form)
/// <summary>
/// 发送POST请求,获取返回结果(Post,Form)
/// </summary>
/// <param name="postData">请求数据</param>
/// <param name="postUrl">请求地址</param>
/// <returns>响应结果</returns>
public string TransSubmit(string postData,string postUrl)
{
Encoding code = Encoding.GetEncoding("utf-8");
byte[] bytesRequestData = code.GetBytes(postData);
string str = "";
WebRequest webRequest = WebRequest.Create(postUrl);
HttpWebRequest myReq = webRequest as HttpWebRequest;
myReq.Method = "post";
myReq.ContentType = "application/x-www-form-urlencoded";
myReq.ContentLength = bytesRequestData.Length;
Stream requestStream = myReq.GetRequestStream();
requestStream.Write(bytesRequestData, 0, bytesRequestData.Length);
requestStream.Close();
HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
Stream myStream = HttpWResp.GetResponseStream();
StreamReader Reader = new StreamReader(myStream);
str = Reader.ReadToEnd();
return str;
}
post请求
第四步:对响应的数据验证签名。
string sign = GetUrlStrValue(resultData, "signature"); //截取响应结果的签名字符串
string sourceData = resultData.Substring(0, resultData.IndexOf("signature")-1); //响应的数据字符
string PublicKey = MyRsaUtil.GetPublicKey(privateKeyUrl,privateKeyPwd );//获取公钥证书
bool verifySign = MyRsaUtil.SignatureDeformatter(sourceData, sign, PublicKey);//公钥证书验证签名(为true,则验证签名成功
。为false ,则验证签名失败)
if (verifySign)
{
Response.Write("请求内容:" + signData);
Response.Write("响应内容:"+resultData);
}
else
{
Response.Write("验证签名失败");
}
/// <summary>
/// 截取路径字符串变量值
/// </summary>
/// <param name="sourceStr">路径字符串</param>
/// <param name="strof">变量名</param>
/// <returns>变量值</returns>
public string GetUrlStrValue(string sourceStr,string strof) {
sourceStr=sourceStr.Substring(sourceStr.IndexOf(strof+"="),sourceStr.Length-sourceStr.IndexOf(strof+"="));
sourceStr = sourceStr + "&";
sourceStr = sourceStr.Substring(sourceStr.IndexOf("=") + 1, sourceStr.IndexOf("&") - sourceStr.IndexOf("=") - 1);
return sourceStr;
}
/// <summary>
/// 获取证书公钥
/// </summary>
/// <param name="pfxFileName">证书路径</param>
/// <param name="password">证书密码</param>
/// <returns>证书公钥</returns>
public string GetPublicKey(string pfxFileUrl, string password)
{
X509Certificate2 _certificate = GetCertificateFromPfxFile(pfxFileName, password);
return _certificate.PublicKey.Key.ToXmlString(false);
}
/// <summary>
/// 验证签名
/// </summary>
/// <param name="sourceData">响应的数据</param>
/// <param name="strEncryptString">签名</param>
/// <param name="publicKey">公钥</param>
/// <returns>true or false</returns>
public bool SignatureDeformatter(string sourceData, string sign,string publicKey)
{
try
{
byte[] rgbHash = Encoding.UTF8.GetBytes(sourceData);
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(publicKey);
bool result = key.VerifyData(rgbHash, "SHA1", Convert.FromBase64String(strEncryptString));
return result;
}
catch
{
return false;
}
}
验证签名