今日在做微信支付对接相关事宜,需要用到证书做签名
C#相关读取证书,获得证书私钥,再去做RSA256签名,代码如下
public static class WeChartPaySecurityHelper
{
/// <summary>
/// 调用签名方法 sha256方式
/// </summary>
/// <param name="contentForSign">代签名串</param>
/// <param name="priKeyFile">证书文件地址</param>
/// <param name="keyPwd">证书密钥(商户ID)</param>
/// <returns></returns>
public static string Sign(string contentForSign, string priKeyFile, string keyPwd)
{
var rsa = GetPrivateKey(priKeyFile, keyPwd);
// Create a new RSACryptoServiceProvider
var rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
var paras = rsa.ExportParameters(true);
rsaClear.ImportParameters(paras);
using (var sha256 = new SHA256CryptoServiceProvider())
{
var signData = rsaClear.SignData(Encoding.UTF8.GetBytes(contentForSign), sha256);
return Convert.ToBase64String(signData);
}
}
public static bool VerifySign(string contentForSign, string signedData,string pubKeyFile)
{
var rsa = GetPublicKey(pubKeyFile);
using (var sha256 = new SHA256CryptoServiceProvider())
{
return rsa.VerifyData(Encoding.UTF8.GetBytes(contentForSign), sha256, HexToBytes(signedData));
}
}
/// <summary>
/// 获取签名证书私钥
/// </summary>
/// <param name="priKeyFile">证书文件</param>
/// <param name="keyPwd">证书密钥</param>
/// <returns></returns>
private static RSACryptoServiceProvider GetPrivateKey(string priKeyFile, string keyPwd)
{
var pc = new X509Certificate2(priKeyFile, keyPwd, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
return (RSACryptoServiceProvider)pc.PrivateKey;
}
/// <summary>
/// 获取验签证书
/// </summary>
/// <param name="pubKeyFile"></param>
/// <returns></returns>
private static RSACryptoServiceProvider GetPublicKey(string pubKeyFile)
{
var pc = new X509Certificate2(pubKeyFile);
return (RSACryptoServiceProvider)pc.PublicKey.Key;
}
public static byte[] HexToBytes(string text)
{
if (text.Length % 2 != 0)
throw new ArgumentException("text 长度为奇数。");
List<byte> lstRet = new List<byte>();
for (int i = 0; i < text.Length; i = i + 2)
{
lstRet.Add(Convert.ToByte(text.Substring(i, 2), 16));
}
return lstRet.ToArray();
}
/// <summary>
/// bytes转换hex
/// </summary>
/// <param name="data">bytes</param>
/// <returns>转换后的hex字符串</returns>
public static string BytesToHex(byte[] data)
{
StringBuilder sbRet = new StringBuilder(data.Length * 2);
for (int i = 0; i < data.Length; i++)
{
sbRet.Append(Convert.ToString(data[i], 16).PadLeft(2, '0'));
}
return sbRet.ToString();
}
public static string EncodeBase64(string code_type, string code)
{
string encode = "";
byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code);
try
{
encode = Convert.ToBase64String(bytes);
}
catch
{
encode = code;
}
return encode;
}
///解码
public static string DecodeBase64(string code_type, string code)
{
string decode = "";
byte[] bytes = Convert.FromBase64String(code);
try
{
decode = Encoding.GetEncoding(code_type).GetString(bytes);
}
catch
{
decode = code;
}
return decode;
}
}
原文地址https://www.cnblogs.com/frankyou/p/8405012.html
原文可以进行读取证书私钥并进行sha1加密,但是进行256加密会报“”签名算法错误“
排查原因如下:
public string Sign(string contentForSign,string priKeyFile, string keyPwd)
{
var rsa = GetPrivateKey(priKeyFile,keyPwd);
// Create a new RSACryptoServiceProvider
var rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
var paras = rsa.ExportParameters(true);
rsaClear.ImportParameters(paras);
using (var sha256 = new SHA256CryptoServiceProvider())
{
var signData = rsa.SignData(Encoding.UTF8.GetBytes(contentForSign), sha256);
return BytesToHex(signData);
}
}
这个代码上面已经说明强制使用256的办法 需要重置RSACryptoServiceProvider ,这个代码上已经实例了rsaClear 并写入参数,可是下面加密还是使用的原先rsa,替换成rsaClear.signData 就可以强行加密Sha256
本文代码已做修正,测试和java签名及验签工具结果一致