File: System\Security\Cryptography\Xml\CryptoHelpers.cs
Web Access
Project: src\src\libraries\System.Security.Cryptography.Xml\src\System.Security.Cryptography.Xml.csproj (System.Security.Cryptography.Xml)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
 
namespace System.Security.Cryptography.Xml
{
    internal static class CryptoHelpers
    {
        internal const string CreateFromNameUnreferencedCodeMessage = "The algorithm implementations referenced in the XML payload might be removed. Ensure the required algorithm implementations are preserved in your application.";
        internal const string XsltRequiresDynamicCodeMessage = "XmlDsigXsltTransform uses XslCompiledTransform which requires dynamic code.";
 
        private static readonly char[] _invalidChars = new char[] { ',', '`', '[', '*', '&' };
 
        [RequiresDynamicCode(XsltRequiresDynamicCodeMessage)]
        [RequiresUnreferencedCode(CreateFromNameUnreferencedCodeMessage)]
        private static object? CreateFromKnownName(string name) =>
            name switch
            {
                "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" => new XmlDsigC14NTransform(),
                "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" => new XmlDsigC14NWithCommentsTransform(),
                "http://www.w3.org/2001/10/xml-exc-c14n#" => new XmlDsigExcC14NTransform(),
                "http://www.w3.org/2001/10/xml-exc-c14n#WithComments" => new XmlDsigExcC14NWithCommentsTransform(),
                "http://www.w3.org/2000/09/xmldsig#base64" => new XmlDsigBase64Transform(),
                "http://www.w3.org/TR/1999/REC-xpath-19991116" => new XmlDsigXPathTransform(),
                "http://www.w3.org/TR/1999/REC-xslt-19991116" => CreateXmlDsigXsltTransform(),
                "http://www.w3.org/2000/09/xmldsig#enveloped-signature" => new XmlDsigEnvelopedSignatureTransform(),
                "http://www.w3.org/2002/07/decrypt#XML" => new XmlDecryptionTransform(),
                "urn:mpeg:mpeg21:2003:01-REL-R-NS:licenseTransform" => new XmlLicenseTransform(),
                "http://www.w3.org/2000/09/xmldsig# X509Data" => new KeyInfoX509Data(),
                "http://www.w3.org/2000/09/xmldsig# KeyName" => new KeyInfoName(),
#pragma warning disable CA1416 // This call site is reachable on all platforms. 'DSAKeyValue' is unsupported on: 'ios', 'maccatalyst', 'tvos'
                "http://www.w3.org/2000/09/xmldsig# KeyValue/DSAKeyValue" => new DSAKeyValue(),
#pragma warning restore CA1416
                "http://www.w3.org/2000/09/xmldsig# KeyValue/RSAKeyValue" => new RSAKeyValue(),
                "http://www.w3.org/2000/09/xmldsig# RetrievalMethod" => new KeyInfoRetrievalMethod(),
                "http://www.w3.org/2001/04/xmlenc# EncryptedKey" => new KeyInfoEncryptedKey(),
                "http://www.w3.org/2000/09/xmldsig#dsa-sha1" => new DSASignatureDescription(),
                "System.Security.Cryptography.DSASignatureDescription" => new DSASignatureDescription(),
                "http://www.w3.org/2000/09/xmldsig#rsa-sha1" => new RSAPKCS1SHA1SignatureDescription(),
                "System.Security.Cryptography.RSASignatureDescription" => new RSAPKCS1SHA1SignatureDescription(),
                "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" => new RSAPKCS1SHA256SignatureDescription(),
                "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384" => new RSAPKCS1SHA384SignatureDescription(),
                "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" => new RSAPKCS1SHA512SignatureDescription(),
                _ => null,
            };
 
        [RequiresDynamicCode(XsltRequiresDynamicCodeMessage)]
        private static XmlDsigXsltTransform CreateXmlDsigXsltTransform()
        {
#if NET
            if (!RuntimeFeature.IsDynamicCodeSupported)
            {
                // XSLTs are only supported when dynamic code is supported. See https://github.com/dotnet/runtime/issues/84389
                throw new NotSupportedException(SR.Cryptography_Xml_XsltRequiresDynamicCode);
            }
#endif
 
            return new XmlDsigXsltTransform();
        }
 
        [RequiresDynamicCode(XsltRequiresDynamicCodeMessage)]
        [RequiresUnreferencedCode(CreateFromNameUnreferencedCodeMessage)]
        public static T? CreateFromName<T>(string? name) where T : class
        {
            if (name == null || name.IndexOfAny(_invalidChars) >= 0)
            {
                return null;
            }
            try
            {
                return (CryptoConfig.CreateFromName(name) ?? CreateFromKnownName(name)) as T;
            }
#if NET
            catch (NotSupportedException)
            {
                if (name == "http://www.w3.org/TR/1999/REC-xslt-19991116")
                {
                    // allow XSLT NotSupportedException to be thrown
                    throw;
                }
                return null;
            }
#endif
            catch (Exception)
            {
                return null;
            }
        }
 
        [RequiresUnreferencedCode(CreateFromNameUnreferencedCodeMessage)]
        [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCodeAttribute",
            Justification = "Only XmlDsigXsltTransform requires dynamic code. This method asserts that T is not a Transform.")]
        public static T? CreateNonTransformFromName<T>(string? name) where T : class
        {
            Debug.Assert(!typeof(Transform).IsAssignableFrom(typeof(T)));
 
            return CreateFromName<T>(name);
        }
    }
}