Подписание Xml-документа с использованием метода подписи RSA-SHA256

Я использую метод ниже для подписи документов Xml:

public static XmlDocument SignDocument(XmlDocument doc)
    {
        string signatureCanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
        string signatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
        string digestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256";

        string signatureReferenceURI = "#_73e63a41-156d-4fda-a26c-8d79dcade713";

        CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), signatureMethod);

        var signingCertificate = GetCertificate();

        SignedXml signer = new SignedXml(doc);
        signer.SigningKey = signingCertificate.PrivateKey;
        signer.KeyInfo = new KeyInfo();
        signer.KeyInfo.AddClause(new KeyInfoX509Data(signingCertificate));

        signer.SignedInfo.CanonicalizationMethod = signatureCanonicalizationMethod;
        signer.SignedInfo.SignatureMethod = signatureMethod;

        XmlDsigEnvelopedSignatureTransform envelopeTransform = new XmlDsigEnvelopedSignatureTransform();
        XmlDsigExcC14NTransform cn14Transform = new XmlDsigExcC14NTransform();

        Reference signatureReference = new Reference();
        signatureReference.Uri = signatureReferenceURI;
        signatureReference.AddTransform(envelopeTransform);
        signatureReference.AddTransform(cn14Transform);
        signatureReference.DigestMethod = digestMethod;

        signer.AddReference(signatureReference);

        signer.ComputeSignature();
        XmlElement signatureElement = signer.GetXml();

        doc.DocumentElement.AppendChild(signer.GetXml());

        return doc;
    }


        private static X509Certificate2 GetCertificate()
    {

        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2 card = null;
        foreach (X509Certificate2 cert in store.Certificates)
        {
            if (!cert.HasPrivateKey) continue;

            if (cert.Thumbprint.Equals("a_certain_thumb_print", StringComparison.OrdinalIgnoreCase))
            {
                card = cert;
                break;
            }
        }
        store.Close();

        return card;
    }

Исключение типа System.Security.Cryptography.CryptographicException возникает при попытке вычислить подпись с сообщением об ошибке Указан неверный алгоритм. Есть идеи?

Машина: Windows Server 2008 R2

.NET Framework: 4.0.

IDE: Visual Studio 2010.


person UncleZen    schedule 01.08.2012    source источник
comment
Я решил эту проблему (спасибо Филиппу) следующим образом: /* добавьте следующие строки кода после var signingCertificate = GetCertificate();*/ CspParameters cspParams = new CspParameters(24); cspParams.KeyContainerName = XML_DISG_RSA_KEY; Ключ RSACryptoServiceProvider = новый RSACryptoServiceProvider(cspParams); key.FromXmlString(signingCertificate.PrivateKey.ToXmlString(true)); /* назначаем новый ключ SigningKey подписывающей стороны */ metadataSigner.SigningKey = key;   -  person UncleZen    schedule 03.08.2012
comment
спасибо UncleZen, который исправил это, но cspParams.KeyContainerName = XML_DISG_RSA_KEY не является обязательным, он работает и без него.   -  person BitSchupser    schedule 07.10.2013


Ответы (3)


Большое спасибо за этот блог. Это действительно решило мою проблему. Кстати, если сертификат загружается из файла, он должен быть экспортируемым: X509Certificate2 x509Key = new X509Certificate2("xxxxx.pfx", "123", X509KeyStorageFlags.Exportable);

person minhj    schedule 16.06.2013
comment
Это не отвечает на вопрос - person Avi Turner; 16.06.2013
comment
Это не отвечает на вопрос, но после реализации решения UncleZen вы получите ошибку «Ключ недействителен для использования в указанном состоянии», если ключ не был помечен как экспортируемый. - person BitSchupser; 07.10.2013

string signalMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

Этот метод подписи не реализован в .NET в соответствии с https://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signedinfo.signaturemethod(v=vs.110).aspx

person yaras    schedule 13.09.2016

В ответе @minhj упоминается какой-то блог, но ссылки там нет.

Однако добавление класса, упомянутого здесь, и его регистрация устранили проблему. Кажется, его следует регистрировать только один раз для каждого домена приложения.

person Gokulnath    schedule 22.04.2016