我有一个X509Certificate2
包含公钥。我有一个RSACryptoServiceProvider
(来自调用SignedXml.CheckSignatureReturningKey
),也包含一个公钥。
我想知道一个是否来自另一个。我如何比较两者?
我有一个X509Certificate2
包含公钥。我有一个RSACryptoServiceProvider
(来自调用SignedXml.CheckSignatureReturningKey
),也包含一个公钥。
我想知道一个是否来自另一个。我如何比较两者?
RSA 算法的公钥参数是{e, n}
、指数和模数。在 .NET 中,这些可从RSAParameters
结构中获得。其他字段代表私钥。
因此,要比较 anX509Certificate2
和 anRSACryptoServiceProvider
的公钥相等性,您只需获取以下参数:
AsymmetricAlgorithm signingKey;
bool signatureIsVerified = signedXml.CheckSignatureReturningKey(out signingKey);
var certificateParameters =
((RSA)certificate.PublicKey.Key).ExportParameters(
includePrivateParameters: false);
var signingParameters = signingKey.ExportParameters(
includePrivateParameters: false);
bool areEqual =
ByteArrayEquals(certificateParameters.Exponent,
signingParameters.Exponent)
&& ByteArrayEquals(certificateParameters.Modulus,
signingParameters.Modulus);
您必须实现ByteArrayEquals
,因为在 .NET 中没有很好的方法来实现它。
如果您使用的是 DSA 而不是 RSA,则公钥由{p, q, g, y}
.
您可以将SignedXml.KeyIfo中签名证书的PublicKey属性与SignedXml.CheckSignatureReturningKey中的签名密钥输出进行比较。这个 C# 扩展方法为我完成了这项工作:
public static bool CheckSignatureReturningCertificate(this SignedXml signedXml, out X509Certificate2 signingCertificate)
{
signingCertificate = null;
AsymmetricAlgorithm signingKey;
bool isValid = signedXml.CheckSignatureReturningKey(out signingKey);
if (isValid)
{
IEnumerable<X509Certificate2> keyInfoCertificates =
signedXml.KeyInfo.OfType<KeyInfoX509Data>()
.SelectMany(x => x.Certificates.Cast<X509Certificate2>());
signingCertificate = keyInfoCertificates.FirstOrDefault(x => x.PublicKey.Key == signingKey);
if (signingCertificate == null)
{
throw new Exception("Signing certificate not found in KeyInfo.");
}
}
return isValid;
}
像这样使用它:
X509Certificate2 signingCertificate = null;
bool isValid = signedXml.CheckSignatureReturningCertificate(out signingCertificate);
if(isValid)
{
// signingCertificate now contains the certificate used to sign
}