2012-02-07 3 views
1

У меня есть X509Certificate2, содержащий открытый ключ. У меня есть RSACryptoServiceProvider (который пришел от звонка SignedXml.CheckSignatureReturningKey), также содержащий открытый ключ.Как я могу сравнить открытые ключи в .NET?

Я хочу узнать, пришел ли кто-то другой. Как я могу сравнить эти два?

ответ

2

Вы можете сравнить PublicKey имущество подписи сертификатов в SignedXml.KeyIfo с ключом ввода ключа от 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. Другие поля представляют собой закрытый ключ.

Таким образом, чтобы сравнить X509Certificate2 и RSACryptoServiceProvider для равенства ключей общественности, вы можете просто взять эти параметры:

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}.