3

.NET Framework バージョン 4.5 で、デジタル署名による XML の署名に関するブロッカーに遭遇しました。

私の問題は、個々の XML 要素に RSA SHA-256 アルゴリズムを使用した X.509 証明書で署名する必要があることに基づいています。このトピックに関する多くの .NET 投稿を読みましたが、CLR セキュリティ プロジェクト RSAPKCS1SHA256SignatureDescription.cs クラスで最初に開発されたソリューションがあるようです。RSAPKCS1SHA256SignatureDescription はもちろん .net ランタイムに組み込まれ、.NET 4.5 の時点で配布バイナリ System.Deployment.dll で利用できるようになりました。.NET で上記のソリューションを試みて、特定の XML 要素に RSA SHA-256 で署名しようとしましたが、まだ成功していません。

Oasis ebms 標準に準拠した SOAP メッセージに WSSE トークンで署名しようとしています。このクラスは、Soap With Attachments (SwA) および個々の添付ファイルへの署名に対応するように作成されていることに注意してください。私のコードは次のとおりです

私のコードは次のとおりです。

using System;
using System.Collections.Generic;
using System.IO;
using System.IdentityModel.Tokens;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Deployment.Internal.CodeSigning;

namespace TestCSharpX509CertificateRSSHA256
{
    public class SignatureSupportUtility
    {

    private bool IsSignatureContentTransform
    {
        get
        {
          return true;
          //get IsSignatureContentTransform                
        }
    }

       public SignatureSupportUtility()
       {
          Register();
       }


    private static void Register()
    {
        CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
    }

    private void Sign(Message message, string[] elementIdsToSign, string[] attachmentsToSign, string wssNamespace, X509Certificate2 certificate)
    {
       //Prepare XML to encrypt and sign
       var element = this.PrepareEncyrptSign(message);

            bool signEntireDocument = true;
            string elementToBeSigned = string.Empty;
            var signedMessage = new XmlDocument();
            signedMessage.AppendChild(signedMessage.ImportNode(element, true));

            SignatureType signAs = SignatureType.InternallyDetached;
            signedMessage.PreserveWhitespace = false;

            OverrideSignedXml signedXml = new OverrideSignedXml(signedMessage);
            signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

            if (elementIdsToSign != null && elementIdsToSign.Length > 0)
            {
                bool isContentTransform = this.IsSignatureContentTransform;

                foreach (string s in elementIdsToSign)
                {
                    // Create a reference to be signed.
                    Reference reference = new Reference(string.Format("#{0}", s));
                    reference.AddTransform(new XmlDsigExcC14NTransform());
                    reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";


                    // Add the reference to the SignedXml object.
                    signedXml.AddReference(reference);
                }

                signEntireDocument = false;
            }

            // Reference attachments to sign
            if (attachmentsToSign != null && attachmentsToSign.Length > 0)
            {
                bool isContentTransform = this.IsSignatureContentTransform;

                foreach (string attachmentId in attachmentsToSign)
                {
                    // Create a reference to be signed.
                    Reference reference = new Reference(string.Format("{0}{1}", Constants.CidUriScheme, attachmentId));
                    reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

                    if (isContentTransform)
                    {
                        AttachmentContentSignatureTransform env = new AttachmentContentSignatureTransform();
                        reference.AddTransform(env);
                    }
                    else
                    {
                        AttachmentCompleteSignatureTransform env = new AttachmentCompleteSignatureTransform();
                        reference.AddTransform(env);
                    }

                    // Add the reference to the SignedXml object.
                    signedXml.AddReference(reference);
                }

                signEntireDocument = false;
            }

            if (signEntireDocument)
            {
                Reference reference = new Reference();
                reference.Uri = "";
                reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

                XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
                reference.AddTransform(env);
                signedXml.AddReference(reference);
                signAs = SignatureType.Enveloped;
            }

            string x509CertificateReferenceId = string.Format("{0}-{1}", Constants.IdAttributeName, Guid.NewGuid().ToString("N"));
            KeyInfo keyInfo = new KeyInfo();
            keyInfo.AddClause(new KeyInfoX509SecurityTokenReference(string.Format("#{0}", x509CertificateReferenceId), wssNamespace));
            signedXml.KeyInfo = keyInfo;
           signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

           RSA  key = (RSACryptoServiceProvider)certificate.PrivateKey;
           signedXML.SigningKey = key;
            CidWebRequest.Message = message;

            signedXml.ComputeSignature();
            var xmlSignature = signedXml.GetXml();
            XmlDocument unsignedEnvelopeDoc = new XmlDocument();
            unsignedEnvelopeDoc.LoadXml(message.MessageAsString); }}} 
using System;
using System.Collections.Generic;
using System.IO;
using System.IdentityModel.Tokens;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Deployment.Internal.CodeSigning;


namespace TestCSharpX509CertificateRSSHA256
{
public sealed class OverrideSignedXml : SignedXml
{
    public OverrideSignedXml()
        : base()
    {
    }

    public OverrideSignedXml(XmlDocument doc)
        : base(doc)
    {
    }

    public override XmlElement GetIdElement(XmlDocument document, string idValue)
    {
        XmlElement element = base.GetIdElement(document, idValue);

        if (element == null)
        {
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
            nsmgr.AddNamespace("wsu", ="http://docs.oasis-open. org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

            element = document.SelectSingleNode("//*[@wsu:Id=\"" + idValue + "\"]", nsmgr) as XmlElement;
        }

        return element;
    }
}

}

SignatureSupportUtility クラスの Sign メソッドは、個々の XML 要素またはメッセージ全体に署名するのに十分なはずですが、SHA-256 がサポートされていないと主張する暗号化例外を受け取り続けます。RSAPKCS1SHA256SignatureDescription.cs が登録されていることを考えると、この例外は有効ではないと思います。ただし、SignedXML クラスに SHA-256 の名前空間が含まれておらず、SHA-128 のみが含まれていることを観察すると、登録に関係なく SHA 256 がサポートされているかどうか疑問に思い始めています。

私の問題を解決し、RSA SHA 256 アルゴリズムを介して X.509 証明書で XML に署名できるようにするための最善の方法を教えてください。

4

2 に答える 2

9

Oasis ebms も検討中です。

これを引用した記事は見つかりませんが、4.5 のクラスを使用しました。

public class RsaPkCs1Sha256SignatureDescription : SignatureDescription
{
    public RsaPkCs1Sha256SignatureDescription()
    {
        KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider";
        DigestAlgorithm = "System.Security.Cryptography.SHA256Managed";
        FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
        DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
    }

    public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
    {
        var asymmetricSignatureDeformatter = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName(DeformatterAlgorithm);
        asymmetricSignatureDeformatter.SetKey(key);
        asymmetricSignatureDeformatter.SetHashAlgorithm("SHA256");
        return asymmetricSignatureDeformatter;
    }

次に、次のようなものを使用して署名します(無関係なビットをいくつか編集しました):

    public XmlElement SignDocument(XmlDocument doc, List<string> idsToSign)
    {
        CryptoConfig.AddAlgorithm(typeof(RsaPkCs1Sha256SignatureDescription), @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

        var cspParams = new CspParameters(24) { KeyContainerName = "XML_DISG_RSA_KEY" };
        var key = new RSACryptoServiceProvider(cspParams);
        key.FromXmlString(_x509SecurityToken.Certificate.PrivateKey.ToXmlString(true));

        var signer = new SoapSignedXml(doc) { SigningKey = key };

        signer.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

        var keyInfo = new KeyInfo();
        keyInfo.AddClause(new SecurityTokenReference(_x509SecurityToken, SecurityTokenReference.SerializationOptions.Embedded));

        signer.KeyInfo = keyInfo;
        signer.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

        var cn14Transform = new XmlDsigExcC14NTransform();
        string referenceDigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";

        foreach (string id in idsToSign)
        {
            var reference = new Reference("#" + id);
            reference.AddTransform(cn14Transform);
            reference.DigestMethod = referenceDigestMethod;
            signer.AddReference(reference);
        }

        signer.ComputeSignature();

        return signer.GetXml();
    }

動作しているようで、相手側で OK を確認します。先日 Holodeck でテストしたところ、署名要素にないタイムスタンプで失敗したと思います。

ただし、添付ファイルの署名は .NET では実際の問題のようです。関連する変換がまったくサポートされていないと思います。

于 2013-06-24T21:53:18.370 に答える
0

残念ながら、秘密鍵をエクスポートできない場合、アンドリューの答えは当てはまりません。

私はスマート カードを使用していますが、今のところ SHA-256 で SignedXML を使用する方法が見つかりません。この機能は、RSACryptoServiceProvider の現在の実装では壊れているようです。

私の意見では、唯一の解決策は、CSP から PKCS#11 に切り替えてから、BouncyCastle.Net を使用することです。そして、すべてを書き直します。

于 2015-02-13T14:15:29.927 に答える