Beispiel #1
0
        /// <summary>
        /// Sign an xml element with the supplied cert.
        /// </summary>
        /// <param name="xmlElement">xmlElement to be signed. The signature is
        /// added as a node in the document, right after the Issuer node.</param>
        /// <param name="cert">Certificate to use when signing.</param>
        /// <param name="includeKeyInfo">Include public key in signed output.</param>
        /// <param name="signingAlgorithm">The signing algorithm to use.</param>
        public static void Sign(
            this XmlElement xmlElement,
            X509Certificate2 cert,
            bool includeKeyInfo,
            string signingAlgorithm)
        {
            if (xmlElement == null)
            {
                throw new ArgumentNullException(nameof(xmlElement));
            }

            if (cert == null)
            {
                throw new ArgumentNullException(nameof(cert));
            }

            var signedXml = new SignedXmlWithIdFix(xmlElement.OwnerDocument);

            // The transform XmlDsigExcC14NTransform and canonicalization method XmlDsigExcC14NTransformUrl is important for partially signed XML files
            // see: http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signedxml.xmldsigexcc14ntransformurl(v=vs.110).aspx
            // The reference URI has to be set correctly to avoid assertion injections
            // For both, the ID/Reference and the Transform/Canonicalization see as well:
            // https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf section 5.4.2 and 5.4.3

            signedXml.SigningKey = EnvironmentHelpers.IsNetCore ? cert.PrivateKey :
                                   ((RSACryptoServiceProvider)cert.PrivateKey)
                                   .GetSha256EnabledRSACryptoServiceProvider();
            signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
            signedXml.SignedInfo.SignatureMethod        = signingAlgorithm;

            // We need a document unique ID on the element to sign it -- make one up if it's missing
            string id = xmlElement.GetAttribute("ID");

            if (String.IsNullOrEmpty(id))
            {
                id = "_" + Guid.NewGuid().ToString("N");
                xmlElement.SetAttribute("ID", id);
            }
            var reference = new Reference
            {
                Uri          = "#" + id,
                DigestMethod = GetCorrespondingDigestAlgorithm(signingAlgorithm)
            };

            reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
            reference.AddTransform(new XmlDsigExcC14NTransform());

            signedXml.AddReference(reference);
            signedXml.ComputeSignature();

            if (includeKeyInfo)
            {
                var keyInfo = new KeyInfo();
                keyInfo.AddClause(new KeyInfoX509Data(cert));
                signedXml.KeyInfo = keyInfo;
            }

            xmlElement.InsertAfter(
                xmlElement.OwnerDocument.ImportNode(signedXml.GetXml(), true),
                xmlElement["Issuer", Saml2Namespaces.Saml2Name]);
        }