RSA签名验证 本帖最后由 nuptgis 于 2014-03-11 21:38:44 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你例子中的publicKey用的是ASN.1 DER编码,因此不能直接用ImportCspBlob(它使用另外一种格式)。你可以用在线工具进行解码:http://lapo.it/asn1js/得出的结果类似:SEQUENCE(2 elem)--SEQUENCE(2 elem)----OBJECT IDENTIFIER 1.2.840.113549.1.1.1----NULL--BIT STRING(1 elem)----SEQUENCE(2 elem)------INTEGER(1024 bit) 1324925806459412787721713702712958489781723…------INTEGER 65537其中最后的65537就是publicKey中的Exponent,而那个1024bit的数据就是publicKey中的Modulus。如果是实时解码,可能你要写一个DER解析器。如果是一次性解码,可以投机直接裁出:byte[] bytes = Convert.FromBase64String(publicKey);if (bytes.Length != 0xa2){ throw new NotImplementedException();}if (!bytes.Skip(bytes.Length - 5).SequenceEqual(new byte[]{2,3,1,0,1})){ // 确认Exponent在最后,并且是65537 // 其中2表示ASN整数型,3表示整数数据的字节数,1,0,1就是0x101,就是65537 throw new NotImplementedException();}RSAParameters rsaParam = new RSAParameters(){ Exponent = new byte[]{ 1, 0, 1 }, //65537 Modulus = bytes.Skip(bytes.Length - 5 - 1024).Take(1024).ToArray(), // BCACFA...};RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();rsa.ImportParameters(rsaParam); public bool SignatureDeformatter(string p_strKeyPublic, string p_strHashbyteDeformatter, string p_strDeformatterData) { try { byte[] rgbHash = Convert.FromBase64String(p_strHashbyteDeformatter); RSACryptoServiceProvider key = new RSACryptoServiceProvider(); key.FromXmlString(p_strKeyPublic); RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key); deformatter.SetHashAlgorithm("MD5"); byte[] rgbSignature = Convert.FromBase64String(p_strDeformatterData); if (deformatter.VerifySignature(rgbHash, rgbSignature)) { return true; } return false; } catch { return false; } } 已解决, /// <summary> /// 验证签名 /// </summary> /// <param name="content">待签名字符串</param> /// <param name="signedString">POST过来的签名</param> /// <param name="publicKey">公钥</param> /// <param name="input_charset">编码格式</param> /// <returns></returns> public static bool verify(string content, string signedString, string publicKey, string input_charset) { bool result = false; try { Encoding code = Encoding.GetEncoding(input_charset); byte[] Data = code.GetBytes(content); byte[] data = Convert.FromBase64String(signedString); RSAParameters paraPub = ConvertFromPublicKey(publicKey); RSACryptoServiceProvider rsaPub = new RSACryptoServiceProvider(); rsaPub.ImportParameters(paraPub); SHA1 sh = new SHA1CryptoServiceProvider(); result = rsaPub.VerifyData(Data, sh, data); return result; } catch (Exception ex) { return false; } } #region 解析.net 生成的Pem private static RSAParameters ConvertFromPublicKey(string pemFileConent) { byte[] keyData = Convert.FromBase64String(pemFileConent); if (keyData.Length < 162) { throw new ArgumentException("pem file content is incorrect."); } byte[] pemModulus = new byte[128]; byte[] pemPublicExponent = new byte[3]; Array.Copy(keyData, 29, pemModulus, 0, 128); Array.Copy(keyData, 159, pemPublicExponent, 0, 3); RSAParameters para = new RSAParameters(); para.Modulus = pemModulus; para.Exponent = pemPublicExponent; return para; } 求教:画图板重绘问题。窗口最小化,再还原要点击画布才会显示原来画的 高灵活性表同步工具 ASP.net 关于屏蔽回车键的 问题 求c#免费打印控件 请问,c#中窗口如何锁定大小,显示时不能调整? 是哪个属性? 系统流程重组 高手请进,关于窗体的动态调用!!!! 如何获取网络占用率 用C#读取,加载access数据库!!! 谁能提供C#写并口的代码,管用的话200分如何? C# Process.WaitForExit();运行时界面锁死,怎么解决? C#绑定数据有趣现象!!!
http://lapo.it/asn1js/得出的结果类似:SEQUENCE(2 elem)
--SEQUENCE(2 elem)
----OBJECT IDENTIFIER 1.2.840.113549.1.1.1
----NULL
--BIT STRING(1 elem)
----SEQUENCE(2 elem)
------INTEGER(1024 bit) 1324925806459412787721713702712958489781723…
------INTEGER 65537
其中最后的65537就是publicKey中的Exponent,而那个1024bit的数据就是publicKey中的Modulus。如果是实时解码,可能你要写一个DER解析器。
如果是一次性解码,可以投机直接裁出:
byte[] bytes = Convert.FromBase64String(publicKey);if (bytes.Length != 0xa2)
{
throw new NotImplementedException();
}
if (!bytes.Skip(bytes.Length - 5).SequenceEqual(new byte[]{2,3,1,0,1}))
{
// 确认Exponent在最后,并且是65537
// 其中2表示ASN整数型,3表示整数数据的字节数,1,0,1就是0x101,就是65537
throw new NotImplementedException();
}RSAParameters rsaParam = new RSAParameters()
{
Exponent = new byte[]{ 1, 0, 1 }, //65537
Modulus = bytes.Skip(bytes.Length - 5 - 1024).Take(1024).ToArray(), // BCACFA...
};RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParam);
{ try
{ byte[] rgbHash = Convert.FromBase64String(p_strHashbyteDeformatter); RSACryptoServiceProvider key = new RSACryptoServiceProvider(); key.FromXmlString(p_strKeyPublic); RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key); deformatter.SetHashAlgorithm("MD5"); byte[] rgbSignature = Convert.FromBase64String(p_strDeformatterData); if (deformatter.VerifySignature(rgbHash, rgbSignature))
{ return true; } return false; } catch
{ return false; } }
/// <summary>
/// 验证签名
/// </summary>
/// <param name="content">待签名字符串</param>
/// <param name="signedString">POST过来的签名</param>
/// <param name="publicKey">公钥</param>
/// <param name="input_charset">编码格式</param>
/// <returns></returns>
public static bool verify(string content, string signedString, string publicKey, string input_charset)
{
bool result = false;
try
{
Encoding code = Encoding.GetEncoding(input_charset);
byte[] Data = code.GetBytes(content);
byte[] data = Convert.FromBase64String(signedString);
RSAParameters paraPub = ConvertFromPublicKey(publicKey);
RSACryptoServiceProvider rsaPub = new RSACryptoServiceProvider();
rsaPub.ImportParameters(paraPub); SHA1 sh = new SHA1CryptoServiceProvider();
result = rsaPub.VerifyData(Data, sh, data);
return result;
}
catch (Exception ex)
{
return false;
}
} #region 解析.net 生成的Pem
private static RSAParameters ConvertFromPublicKey(string pemFileConent)
{ byte[] keyData = Convert.FromBase64String(pemFileConent);
if (keyData.Length < 162)
{
throw new ArgumentException("pem file content is incorrect.");
}
byte[] pemModulus = new byte[128];
byte[] pemPublicExponent = new byte[3];
Array.Copy(keyData, 29, pemModulus, 0, 128);
Array.Copy(keyData, 159, pemPublicExponent, 0, 3);
RSAParameters para = new RSAParameters();
para.Modulus = pemModulus;
para.Exponent = pemPublicExponent;
return para;
}