logo
down
shadow

X509Certificate2.Import with NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG


X509Certificate2.Import with NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG

By : user3038785
Date : November 24 2020, 12:01 PM
this will help The best flow I've found:
Open the PFX Exportable (sets the exportable bit, but not the plaintext exportable bit) Export encrypted PKCS#8 Import encrypted PKCS#8 with overwrite, no finalize Change the export policy Finalize (to commit the overwrite) Now if you ask the cert for its key it's plaintext exportable.
code :
internal static partial class Program
{
    internal static void Main(string[] args)
    {
        X509Certificate2 cert = ImportExportable(ECDsaP256_DigitalSignature_Pfx_Windows, "Test", machineScope: false);

        try
        {
            bool gotKey = NativeMethods.Crypt32.CryptAcquireCertificatePrivateKey(
                cert.Handle,
                NativeMethods.Crypt32.AcquireCertificateKeyOptions.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,
                IntPtr.Zero,
                out SafeNCryptKeyHandle keyHandle,
                out int keySpec,
                out bool callerFree);

            using (CngKey cngKey = CngKey.Open(keyHandle, 0))
            {
                Console.WriteLine(cngKey.ExportPolicy);

                Console.WriteLine(
                    Convert.ToBase64String(
                        cngKey.Export(CngKeyBlobFormat.Pkcs8PrivateBlob)));
            }
        }
        finally
        {
            cert.Reset();
        }
    }

    private static X509Certificate2 ImportExportable(byte[] pfxBytes, string password, bool machineScope)
    {
        X509KeyStorageFlags flags = X509KeyStorageFlags.Exportable;

        if (machineScope)
        {
            flags |= X509KeyStorageFlags.MachineKeySet;
        }
        else
        {
            flags |= X509KeyStorageFlags.UserKeySet;
        }

        X509Certificate2 cert = new X509Certificate2(pfxBytes, password, flags);

        try
        {
            bool gotKey = NativeMethods.Crypt32.CryptAcquireCertificatePrivateKey(
                cert.Handle,
                NativeMethods.Crypt32.AcquireCertificateKeyOptions.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,
                IntPtr.Zero,
                out SafeNCryptKeyHandle keyHandle,
                out int keySpec,
                out bool callerFree);

            if (!gotKey)
            {
                keyHandle.Dispose();
                throw new InvalidOperationException("No private key");
            }

            if (!callerFree)
            {
                keyHandle.SetHandleAsInvalid();
                keyHandle.Dispose();
                throw new InvalidOperationException("Key is not persisted");
            }

            using (keyHandle)
            {
                // -1 == CNG, otherwise CAPI
                if (keySpec == -1)
                {
                    using (CngKey cngKey = CngKey.Open(keyHandle, CngKeyHandleOpenOptions.None))
                    {
                        // If the CNG->CAPI bridge opened the key then AllowPlaintextExport is already set.
                        if ((cngKey.ExportPolicy & CngExportPolicies.AllowPlaintextExport) == 0)
                        {
                            FixExportability(cngKey, machineScope);
                        }
                    }
                }
            }
        }
        catch
        {
            cert.Reset();
            throw;
        }

        return cert;
    }

    internal static void FixExportability(CngKey cngKey, bool machineScope)
    {
        string password = nameof(NativeMethods.Crypt32.AcquireCertificateKeyOptions);
        byte[] encryptedPkcs8 = ExportEncryptedPkcs8(cngKey, password, 1);
        string keyName = cngKey.KeyName;

        using (SafeNCryptProviderHandle provHandle = cngKey.ProviderHandle)
        {
            ImportEncryptedPkcs8Overwrite(
                encryptedPkcs8,
                keyName,
                provHandle,
                machineScope,
                password);
        }
    }

    internal const string NCRYPT_PKCS8_PRIVATE_KEY_BLOB = "PKCS8_PRIVATEKEY";
    private static readonly byte[] s_pkcs12TripleDesOidBytes =
        System.Text.Encoding.ASCII.GetBytes("1.2.840.113549.1.12.1.3\0");

    private static unsafe byte[] ExportEncryptedPkcs8(
        CngKey cngKey,
        string password,
        int kdfCount)
    {
        var pbeParams = new NativeMethods.NCrypt.PbeParams();
        NativeMethods.NCrypt.PbeParams* pbeParamsPtr = &pbeParams;

        byte[] salt = new byte[NativeMethods.NCrypt.PbeParams.RgbSaltSize];

        using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(salt);
        }

        pbeParams.Params.cbSalt = salt.Length;
        Marshal.Copy(salt, 0, (IntPtr)pbeParams.rgbSalt, salt.Length);
        pbeParams.Params.iIterations = kdfCount;

        fixed (char* stringPtr = password)
        fixed (byte* oidPtr = s_pkcs12TripleDesOidBytes)
        {
            NativeMethods.NCrypt.NCryptBuffer* buffers =
                stackalloc NativeMethods.NCrypt.NCryptBuffer[3];

            buffers[0] = new NativeMethods.NCrypt.NCryptBuffer
            {
                BufferType = NativeMethods.NCrypt.BufferType.PkcsSecret,
                cbBuffer = checked(2 * (password.Length + 1)),
                pvBuffer = (IntPtr)stringPtr,
            };

            if (buffers[0].pvBuffer == IntPtr.Zero)
            {
                buffers[0].cbBuffer = 0;
            }

            buffers[1] = new NativeMethods.NCrypt.NCryptBuffer
            {
                BufferType = NativeMethods.NCrypt.BufferType.PkcsAlgOid,
                cbBuffer = s_pkcs12TripleDesOidBytes.Length,
                pvBuffer = (IntPtr)oidPtr,
            };

            buffers[2] = new NativeMethods.NCrypt.NCryptBuffer
            {
                BufferType = NativeMethods.NCrypt.BufferType.PkcsAlgParam,
                cbBuffer = sizeof(NativeMethods.NCrypt.PbeParams),
                pvBuffer = (IntPtr)pbeParamsPtr,
            };

            var desc = new NativeMethods.NCrypt.NCryptBufferDesc
            {
                cBuffers = 3,
                pBuffers = (IntPtr)buffers,
                ulVersion = 0,
            };

            using (var keyHandle = cngKey.Handle)
            {
                int result = NativeMethods.NCrypt.NCryptExportKey(
                    keyHandle,
                    IntPtr.Zero,
                    NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
                    ref desc,
                    null,
                    0,
                    out int bytesNeeded,
                    0);

                if (result != 0)
                {
                    throw new Win32Exception(result);
                }

                byte[] exported = new byte[bytesNeeded];

                result = NativeMethods.NCrypt.NCryptExportKey(
                    keyHandle,
                    IntPtr.Zero,
                    NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
                    ref desc,
                    exported,
                    exported.Length,
                    out bytesNeeded,
                    0);

                if (result != 0)
                {
                    throw new Win32Exception(result);
                }

                if (bytesNeeded != exported.Length)
                {
                    Array.Resize(ref exported, bytesNeeded);
                }

                return exported;
            }
        }
    }

    private static unsafe void ImportEncryptedPkcs8Overwrite(
        byte[] encryptedPkcs8,
        string keyName,
        SafeNCryptProviderHandle provHandle,
        bool machineScope,
        string password)
    {
        SafeNCryptKeyHandle keyHandle;

        fixed (char* passwordPtr = password)
        fixed (char* keyNamePtr = keyName)
        fixed (byte* blobPtr = encryptedPkcs8)
        {
            NativeMethods.NCrypt.NCryptBuffer* buffers = stackalloc NativeMethods.NCrypt.NCryptBuffer[2];

            buffers[0] = new NativeMethods.NCrypt.NCryptBuffer
            {
                BufferType = NativeMethods.NCrypt.BufferType.PkcsSecret,
                cbBuffer = checked(2 * (password.Length + 1)),
                pvBuffer = new IntPtr(passwordPtr),
            };

            if (buffers[0].pvBuffer == IntPtr.Zero)
            {
                buffers[0].cbBuffer = 0;
            }

            buffers[1] = new NativeMethods.NCrypt.NCryptBuffer
            {
                BufferType = NativeMethods.NCrypt.BufferType.PkcsName,
                cbBuffer = checked(2 * (keyName.Length + 1)),
                pvBuffer = new IntPtr(keyNamePtr),
            };

            NativeMethods.NCrypt.NCryptBufferDesc desc = new NativeMethods.NCrypt.NCryptBufferDesc
            {
                cBuffers = 2,
                pBuffers = (IntPtr)buffers,
                ulVersion = 0,
            };

            NativeMethods.NCrypt.NCryptImportFlags flags =
                NativeMethods.NCrypt.NCryptImportFlags.NCRYPT_OVERWRITE_KEY_FLAG |
                NativeMethods.NCrypt.NCryptImportFlags.NCRYPT_DO_NOT_FINALIZE_FLAG;

            if (machineScope)
            {
                flags |= NativeMethods.NCrypt.NCryptImportFlags.NCRYPT_MACHINE_KEY_FLAG;
            }

            int errorCode = NativeMethods.NCrypt.NCryptImportKey(
                provHandle,
                IntPtr.Zero,
                NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
                ref desc,
                out keyHandle,
                new IntPtr(blobPtr),
                encryptedPkcs8.Length,
                flags);

            if (errorCode != 0)
            {
                keyHandle.Dispose();
                throw new Win32Exception(errorCode);
            }

            using (keyHandle)
            using (CngKey cngKey = CngKey.Open(keyHandle, CngKeyHandleOpenOptions.None))
            {
                const CngExportPolicies desiredPolicies =
                    CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport;

                cngKey.SetProperty(
                    new CngProperty(
                        "Export Policy",
                        BitConverter.GetBytes((int)desiredPolicies),
                        CngPropertyOptions.Persist));

                int error = NativeMethods.NCrypt.NCryptFinalizeKey(keyHandle, 0);

                if (error != 0)
                {
                    throw new Win32Exception(error);
                }
            }
        }
    }
}

internal static class NativeMethods
{
    internal static class Crypt32
    {
        internal enum AcquireCertificateKeyOptions
        {
            None = 0x00000000,
            CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG = 0x00040000,
        }

        [DllImport("crypt32.dll", SetLastError = true)]
        internal static extern bool CryptAcquireCertificatePrivateKey(
            IntPtr pCert,
            AcquireCertificateKeyOptions dwFlags,
            IntPtr pvReserved,
            out SafeNCryptKeyHandle phCryptProvOrNCryptKey,
            out int dwKeySpec,
            out bool pfCallerFreeProvOrNCryptKey);
    }

    internal static class NCrypt
    {
        [DllImport("ncrypt.dll", CharSet = CharSet.Unicode)]
        internal static extern int NCryptExportKey(
            SafeNCryptKeyHandle hKey,
            IntPtr hExportKey,
            string pszBlobType,
            ref NCryptBufferDesc pParameterList,
            byte[] pbOutput,
            int cbOutput,
            [Out] out int pcbResult,
            int dwFlags);

        [StructLayout(LayoutKind.Sequential)]
        internal unsafe struct PbeParams
        {
            internal const int RgbSaltSize = 8;

            internal CryptPkcs12PbeParams Params;
            internal fixed byte rgbSalt[RgbSaltSize];
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct CryptPkcs12PbeParams
        {
            internal int iIterations;
            internal int cbSalt;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct NCryptBufferDesc
        {
            public int ulVersion;
            public int cBuffers;
            public IntPtr pBuffers;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct NCryptBuffer
        {
            public int cbBuffer;
            public BufferType BufferType;
            public IntPtr pvBuffer;
        }

        internal enum BufferType
        {
            PkcsAlgOid = 41,
            PkcsAlgParam = 42,
            PkcsName = 45,
            PkcsSecret = 46,
        }

        [DllImport("ncrypt.dll", CharSet = CharSet.Unicode)]
        internal static extern int NCryptOpenStorageProvider(
            out SafeNCryptProviderHandle phProvider,
            string pszProviderName,
            int dwFlags);

        internal enum NCryptImportFlags
        {
            None = 0,
            NCRYPT_MACHINE_KEY_FLAG = 0x00000020,
            NCRYPT_OVERWRITE_KEY_FLAG = 0x00000080,
            NCRYPT_DO_NOT_FINALIZE_FLAG = 0x00000400,
        }

        [DllImport("ncrypt.dll", CharSet = CharSet.Unicode)]
        internal static extern int NCryptImportKey(
            SafeNCryptProviderHandle hProvider,
            IntPtr hImportKey,
            string pszBlobType,
            ref NCryptBufferDesc pParameterList,
            out SafeNCryptKeyHandle phKey,
            IntPtr pbData,
            int cbData,
            NCryptImportFlags dwFlags);

        [DllImport("ncrypt.dll", CharSet = CharSet.Unicode)]
        internal static extern int NCryptFinalizeKey(SafeNCryptKeyHandle hKey, int dwFlags);
    }
}


Share : facebook icon twitter icon
How to store a X509Certificate2 in db c#

How to store a X509Certificate2 in db c#


By : Guan Bing
Date : March 29 2020, 07:55 AM
I wish this help you The certificate only includes the public key, so storing only that won't work.
On the other hand, cert.PrivateKey.ToXmlString(true) should work. Are you sure that you remembered to call it with the includePrivateParameters argument set to true and that you imported it as exportable?
code :
X509Certificate2 cert = new X509Certificate2("key.pfx", "password", X509KeyStorageFlags.Exportable);
string xml = cert.PrivateKey.ToXmlString(true);
X509Certificate2 crash IIS

X509Certificate2 crash IIS


By : Andria Philips
Date : March 29 2020, 07:55 AM
I hope this helps you . I imported the Certificate into the LocalMachine Store (not via code) then in my Software I changed
code :
   var cert = new X509Certificate2();
   cert.Import(Resources.wildcard, "xxx", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        foreach (X509Certificate2 certificate in store.Certificates)
        {
            if (certificate.SubjectName.Name != null && certs.SubjectName.Name.Contains("*.domain.xxx"))
            {
                cert = certificate;
            }
        }
xamarin.android X509Certificate2 constructor/import failed with SecureString password instead of plain string

xamarin.android X509Certificate2 constructor/import failed with SecureString password instead of plain string


By : Steve
Date : March 29 2020, 07:55 AM
To fix the issue you can do The reason is that SecureString is not completely supported in Mono. See the source for a comment. It calls the certificate class' Import method and passes a (string)null:
code :
[MonoTODO ("SecureString is incomplete")]
public override void Import (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
{
    Import (rawData, (string) null, keyStorageFlags);
}
RemoteCertificateValidationCallback with X509Certificate2

RemoteCertificateValidationCallback with X509Certificate2


By : user3840072
Date : March 29 2020, 07:55 AM
I hope this helps you . The X509Certificate2 class has a constructor that takes a X509Certificate as parameter. So you can do this:
X509Certificate2 Import PathTooLongException: The specified path, file name, or both are too long

X509Certificate2 Import PathTooLongException: The specified path, file name, or both are too long


By : Frank Chen
Date : March 29 2020, 07:55 AM
Any of those help The overload you are using is for loading your certificate from a file path. Since your base64 representation is far too long to be a path, it's throwing the exception you are getting.
Instead, you could use this overload method, which takes in the raw data as a byte array.
code :
var pfx = certficatestring;          

var bytes = Encoding.UTF32.GetBytes(pfx);

X509Certificate2 x509 = new X509Certificate2();
x509.Import(bytes,password,X509KeyStorageFlags.Exportable);
return x509;
Related Posts Related Posts :
  • Passing enum type to Converter with integer value
  • Pool of objects with objects that are already on the scene in advance
  • StatusBar text fade-out when binding using Caliburn.Micro
  • Queryfilter on ApplicationUser in OnModelCreating in ApplicationDbContext creates StackOverflowException
  • How to get record form a different table based on a value from first table with linq expression?
  • Show data in Grid from returned model
  • Using Attributes to Override Data Model Conventions
  • Basic OOP console calculator, result Error
  • Compositon and Repository pattern
  • Multiple using statements with if condition
  • How do i increase a number by 1 in every line that contain the number 1
  • Add binding to elements that are created in codebehind
  • How to add a column in an existing AspNetUsers table
  • Order a list of elements with another list of doubles
  • How to setup a NuGet package to copy content files to output build directory?
  • In SignalR Core using ChannelWriter: Do I need to call TryComplete twice if there's an exception?
  • C# GetProcessesByName: issue with colon
  • c# wpf | create complex object with user-defined name to Serialize into JSON
  • How can I get a instance of a generic list with reflection?
  • WPF XAML - Design time and visibility of textbox
  • EF Core and MySql query is too slow
  • Getting Registered App Display Name from an App Id
  • How to get all variables from a string
  • Delete entity with all childs connected
  • Azure Build agent cant´t find class library referance
  • Initialize Nested Dictionaries in c#
  • .Net Core Binding
  • Loading a pop up page in ASP.net through a js file
  • How to pass alert or notification message from controller to View?
  • C# to pause, turn on ssas server, backup cube.... how to?
  • How to execute DataTable.Select() for a column of custom class type for a particular element in that C#
  • how to connect mysql8.0 with C#
  • Passing incorrect values into MultiValueConverter by MultiBinding
  • Can i use IEnumerator as Update func?
  • How to convert API Json response to C# Array?
  • Blazor Textfield Oninput User Typing Delay
  • Performing both layout and render transform results in wrong output
  • uwp beforetextchanged cursor moving in front of text
  • How to keep duplicates from a string[] exclude words from a List and print them out
  • .Net Core Strings.Asc/Mid/Chr/Len missing even after importing Microsoft.VisualBasic
  • How to return to previous search page without being asked to Confirm Form Re-submission and keeping the results on ASP.N
  • How set a identity scaffolding item/page how initial page in asp.net MVC core?
  • LINQ isn't calling Dispose on my IEnumerator when using Union and Select, expected behavior or bug?
  • What is "ByteArray.uncompress()" in AS3 equivalent to in C#?
  • Getting a specific letter from a string variable for my simple guessing game for clues
  • Send an email with Outlook without a subject --- dialog box issue
  • passing List<MyModel> from my controller in the "WebInterfaceProject" to the processor method in "D
  • How to convert Word document created from template by OpenXML into MemoryStream?
  • How can I make a single slider that changes the color of an object?
  • Remap JSON parameter in c#
  • What is the difference between "this ref" and "ref this" when talking about C# 7.2 ref extension met
  • Convert OpenSSL encryption into native C#
  • Accessing Properties in Razor Pages
  • How to get SOAP element value
  • Projection after Group
  • C# error cannot convert sytem.text.regularexpressions.match to string
  • Issues with Save/Load System in a Text Based Adventure game made with ScriptableObjects in Unity
  • VS2019 MSBuild.exe - ASP .Net MVC project fails to publish when using PublishProfile, but works when using OutDir parame
  • Does <pages validateRequest="false" /> in Web.config still matter?
  • How to send new request to redirect URL with new access token
  • shadow
    Privacy Policy - Terms - Contact Us © festivalmusicasacra.org