Как я могу сравнить открытые ключи в .NET? - PullRequest
1 голос
/ 07 февраля 2012

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

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

Ответы [ 2 ]

2 голосов
/ 28 апреля 2015

Можно сравнить свойство 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 голос
/ 09 февраля 2012

Параметры открытого ключа для алгоритма 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, потому что нет хорошего способа сделать это в .NET .

Если вы используете DSA, а не RSA, открытый ключ состоит из {p, q, g, y}.

...