2012-02-07 28 views

回答

2

您可以將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 
} 
1

RSA算法的公鑰參數是{e, n},指數和模數。在.NET中,這些可從RSAParameters結構中獲得。其他字段表示私鑰。

因此,要比較一個X509Certificate2RSACryptoServiceProvider公鑰平等,你可以抓住這些參數:

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,因爲有no good way to do it in .NET。如果您使用DSA而不是RSA,公鑰由{p, q, g, y}組成。