private async ValueTask <X509Certificate2> LoadCertificateFromPemFileAsync(bool async, string clientCertificatePath, CancellationToken cancellationToken)
            {
                if (!(Certificate is null))
                {
                    return(Certificate);
                }

                string certficateText;

                try
                {
                    if (!async)
                    {
                        certficateText = File.ReadAllText(clientCertificatePath);
                    }
                    else
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        using (StreamReader sr = new StreamReader(clientCertificatePath))
                        {
                            certficateText = await sr.ReadToEndAsync().ConfigureAwait(false);
                        }
                    }

                    Regex certificateRegex = new Regex("(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)", RegexOptions.CultureInvariant, TimeSpan.FromSeconds(5));
                    Regex privateKeyRegex  = new Regex("(-+BEGIN PRIVATE KEY-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END PRIVATE KEY-+)", RegexOptions.CultureInvariant, TimeSpan.FromSeconds(5));

                    Match certificateMatch = certificateRegex.Match(certficateText);
                    Match privateKeyMatch  = privateKeyRegex.Match(certficateText);

                    if (!certificateMatch.Success)
                    {
                        throw new InvalidDataException("Could not find certificate in PEM file");
                    }

                    if (!privateKeyMatch.Success)
                    {
                        throw new InvalidDataException("Could not find private key in PEM file");
                    }

                    // ImportPkcs8PrivateKey was added in .NET Core 3.0, it is only present on Core.  If we can't find this method, we have a lightweight decoder we can use.
                    MethodInfo importPkcs8PrivateKeyMethodInfo = typeof(RSA).GetMethod("ImportPkcs8PrivateKey", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(ReadOnlySpan <byte>), typeof(int).MakeByRefType() }, null);

                    // CopyWithPrivateKey is present in .NET Core 2.0+ and .NET 4.7.2+.
                    MethodInfo copyWithPrivateKeyMethodInfo = typeof(RSACertificateExtensions).GetMethod("CopyWithPrivateKey", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(X509Certificate2), typeof(RSA) }, null);

                    if (copyWithPrivateKeyMethodInfo == null)
                    {
                        throw new PlatformNotSupportedException("The current platform does not support reading a private key from a PEM file");
                    }

                    RSA privateKey;

                    if (importPkcs8PrivateKeyMethodInfo != null)
                    {
                        privateKey = RSA.Create();

                        // Because ImportPkcs8PrivateKey takes a ReadOnlySpan<byte> as an argument, we can not call it directly via MethodInfo.Invoke (since all the arguments to the function
                        // have to be passed to MethodInfo.Invoke in an object array, and you can't put a byref type like ReadOnlySpan<T> in an array. So we create a delegate with the
                        // correct signature bound to the privateKey we want to import into and invoke that.
                        ImportPkcs8PrivateKeyDelegate importPrivateKey = (ImportPkcs8PrivateKeyDelegate)importPkcs8PrivateKeyMethodInfo.CreateDelegate(typeof(ImportPkcs8PrivateKeyDelegate), privateKey);
                        importPrivateKey(Convert.FromBase64String(privateKeyMatch.Groups[3].Value), out int _);
                    }
                    else
                    {
                        privateKey = LightweightPkcs8Decoder.DecodeRSAPkcs8(Convert.FromBase64String(privateKeyMatch.Groups[3].Value));
                    }

                    X509Certificate2 certWithoutPrivateKey = new X509Certificate2(Convert.FromBase64String(certificateMatch.Groups[3].Value));
                    Certificate = (X509Certificate2)copyWithPrivateKeyMethodInfo.Invoke(null, new object[] { certWithoutPrivateKey, privateKey });

                    // On desktop NetFX it appears the PrivateKey property is not initialized after calling CopyWithPrivateKey
                    // this leads to an issue when using the MSAL ConfidentialClient which uses the PrivateKey property to get the
                    // signing key vs. the extension method GetRsaPrivateKey which we were previously using when signing the claim ourselves.
                    // Because of this we need to set PrivateKey to the instance we created to deserialize the private key
                    if (Certificate.PrivateKey == null)
                    {
                        Certificate.PrivateKey = privateKey;
                    }

                    return(Certificate);
                }
                catch (Exception e) when(!(e is OperationCanceledException))
                {
                    throw new CredentialUnavailableException("Could not load certificate file", e);
                }
            }
        /// <summary>
        /// Loads an <see cref="X509Certificate2"/> from PEM data.
        /// </summary>
        /// <param name="data">The PEM data to parse.</param>
        /// <param name="cer">Optional public certificate data if not defined within the PEM data.</param>
        /// <param name="allowCertificateOnly">Whether to create an <see cref="X509Certificate2"/> if no private key is read.</param>
        /// <returns>An <see cref="X509Certificate2"/> loaded from the PEM data.</returns>
        /// <exception cref="CryptographicException">A cryptographic exception occurred when trying to create the <see cref="X509Certificate2"/>.</exception>
        /// <exception cref="InvalidDataException"><paramref name="cer"/> is null and no CERTIFICATE field is defined in PEM, or no PRIVATE KEY is defined in PEM.</exception>
        /// <exception cref="PlatformNotSupportedException">Creating a <see cref="X509Certificate2"/> from PEM data is not supported on the current platform.</exception>
        public static X509Certificate2 LoadCertificate(ReadOnlySpan <char> data, byte[] cer = null, bool allowCertificateOnly = false)
        {
            byte[] priv = null;

            while (TryRead(data, out PemField field))
            {
                // TODO: Consider building up a chain to determine the leaf certificate: https://github.com/Azure/azure-sdk-for-net/issues/19043
                if (field.Label.Equals("CERTIFICATE".AsSpan(), StringComparison.Ordinal))
                {
                    cer = field.FromBase64Data();
                }
                else if (field.Label.Equals("PRIVATE KEY".AsSpan(), StringComparison.Ordinal))
                {
                    priv = field.FromBase64Data();
                }

                int offset = field.Start + field.Length;
                if (offset >= data.Length)
                {
                    break;
                }

                data = data.Slice(offset);
            }

            if (cer is null)
            {
                throw new InvalidDataException("The certificate is missing the public key");
            }

            if (priv is null)
            {
                if (allowCertificateOnly)
                {
                    return(new X509Certificate2(cer));
                }

                throw new InvalidDataException("The certificate is missing the private key");
            }

            if (!s_initializedImportPkcs8PrivateKeyMethod)
            {
                // ImportPkcs8PrivateKey was added in .NET Core 3.0 and is only present on Core. We will fall back to a lightweight decoder if this method is missing from the current runtime.
                s_importPkcs8PrivateKeyMethod            = typeof(RSA).GetMethod("ImportPkcs8PrivateKey", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(ReadOnlySpan <byte>), typeof(int).MakeByRefType() }, null);
                s_initializedImportPkcs8PrivateKeyMethod = true;
            }

            if (s_copyWithPrivateKeyMethod is null)
            {
                s_copyWithPrivateKeyMethod = typeof(RSACertificateExtensions).GetMethod("CopyWithPrivateKey", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(X509Certificate2), typeof(RSA) }, null)
                                             ?? throw new PlatformNotSupportedException("The current platform does not support reading a private key from a PEM file");
            }

            RSA privateKey = null;

            try
            {
                if (s_importPkcs8PrivateKeyMethod != null)
                {
                    privateKey = RSA.Create();

                    // Because ImportPkcs8PrivateKey declares an out parameter we cannot call it directly using MethodInfo.Invoke since all arguments are passed as an object array.
                    // Instead we create a delegate with the correct signature and invoke it.
                    ImportPkcs8PrivateKeyDelegate importPkcs8PrivateKey = (ImportPkcs8PrivateKeyDelegate)s_importPkcs8PrivateKeyMethod.CreateDelegate(typeof(ImportPkcs8PrivateKeyDelegate), privateKey);
                    importPkcs8PrivateKey.Invoke(priv, out _);
                }
                else
                {
                    privateKey = LightweightPkcs8Decoder.DecodeRSAPkcs8(priv);
                }

                using X509Certificate2 certificateWithoutPrivateKey = new X509Certificate2(cer);
                X509Certificate2 certificate = (X509Certificate2)s_copyWithPrivateKeyMethod.Invoke(null, new object[] { certificateWithoutPrivateKey, privateKey });

                // On .NET Framework the PrivateKey member is not initialized after calling CopyWithPRivateKey.
                if (certificate.PrivateKey is null)
                {
                    certificate.PrivateKey = privateKey;
                }

                // Make sure the private key doesn't get disposed now that it's used.
                privateKey = null;

                return(certificate);
            }
            finally
            {
                // If we created and did not use the RSA private key, make sure it's disposed.
                privateKey?.Dispose();
            }
        }