以下功能使用证书进行签名和验证。
private static bool Sign_Verify(X509Certificate2 x509, byte[] random_data)
{
//
// Local variable definitions
//
bool isVerified = false;
byte[] buffer = Encoding.Default.GetBytes("Hello World ... !");
byte[] signature_Data = null;
byte[] signature_Hash = null;
//
// Retrieve the private key of the certificate selected.
//
RSACryptoServiceProvider privateKey
= x509.PrivateKey as RSACryptoServiceProvider;
if (null == privateKey)
{
Console.WriteLine("Invalid Private Key");
} // if
else
{
Console.WriteLine("Certificate has private key.");
} // else
HashAlgorithm hashAlgo = HashAlgorithm.Create("SHA256");
byte[] hash = hashAlgo.ComputeHash(random_data);
//
// Perform signing using the private key
try
{
signature_Hash = privateKey.SignHash(
hash,
CryptoConfig.MapNameToOID("SHA256"));
if (null == signature_Hash)
{
Console.WriteLine("Error: SignHash\n\n");
} // if
else
{
Console.WriteLine("Signature_Hash generated......\n\n");
} // else
} // try
catch (CryptographicException)
{
//e.StackTrace();
} // catch
//
// Retrieve the public key of the certificate selected.
//
RSACryptoServiceProvider publicKey
= x509.PublicKey.Key as RSACryptoServiceProvider;
if (null == publicKey)
{
Console.WriteLine("Invalid Public Key");
} // if
else
{
Console.WriteLine("Certificate has public key.");
} // else
isVerified = publicKey.VerifyHash(
hash,
CryptoConfig.MapNameToOID("SHA256"),
signature_Hash);
if (false == isVerified)
{
Console.WriteLine("Signature of Hash verification failed.");
} // if
else
{
Console.WriteLine("Signature of Hash verified successfully.");
} // else
return isVerified;
} // Sign_Verify
在HashAlgorithm.Create(“SHA256”)中; ,我们硬编码签名哈希算法的名称。如何获取证书的签名哈希算法的名称而不是硬编码呢?
答案 0 :(得分:2)
似乎没有简单的方法可以从.NET中的证书中获取签名哈希算法。你能做的是先获得签名算法OID
var mapField = typeof(Org.BouncyCastle.Cms.CmsSignedData).Assembly.GetType("Org.BouncyCastle.Cms.CmsSignedHelper").GetField("digestAlgs", BindingFlags.Static | BindingFlags.NonPublic);
var map = (System.Collections.IDictionary) mapField.GetValue(null);
然后你需要以某种方式将这个OID(这可以是例如带有RSA加密的SHA256)映射到OID或只是哈希算法的名称,而不加密(只是SHA256)。您可以自己构建此类地图,也可以使用现有地图,例如Bouncy Castle库中有一个。不幸的是它包含在内部类中,所以你必须使用一些反射来实现它。因此,首先添加对Bouncy Castle的引用(通过nuget),然后:
var hashAlgName = (string)map[cert.SignatureAlgorithm.Value];// returns "SHA256" for OID of sha256 with RSA.
var hashAlg = HashAlgorithm.Create(hashAlgName); // your SHA256
这将获取内部CmsSignedHelper类的私有digestAlgs字段的值,该字段仅包含您需要的地图。
然后你做:
{{1}}