How to import a certificate without user interaction (C++ & C#)


Hi, welcome back,


Today I'm posting a CryptoAPI sample which uses CryptUIWizImport to import a certificate without any user interaction:


 


<SAMPLE Language="C++">

CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc;
memset(&importSrc, 0, sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO));
importSrc.dwSize = sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO);
importSrc.dwSubjectChoice = CRYPTUI_WIZ_IMPORT_SUBJECT_FILE;
importSrc.pwszFileName = L"C:\\PathToPFX\\cert.pfx";
importSrc.pwszPassword = L"PasswordToDecryptPFX";
importSrc.dwFlags = CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED;
 
if (CryptUIWizImport(
CRYPTUI_WIZ_NO_UI,
NULL,
NULL,
&importSrc,
  NULL
) == 0)
{
printf("CryptUIWizImport error 0x%x\n", GetLastError());
}

</SAMPLE>


<SAMPLE Language="C#">

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
 
namespace ImportCertNet
{
    class Program
    {
        public struct CRYPTUI_WIZ_IMPORT_SRC_INFO
        {
            public Int32 dwSize;
            public Int32 dwSubjectChoice;
            [MarshalAs(UnmanagedType.LPWStr)]public String pwszFileName;
            public Int32 dwFlags;
            [MarshalAs(UnmanagedType.LPWStr)]public String pwszPassword;
        }
 
        [DllImport("CryptUI.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern Boolean CryptUIWizImport(
            Int32 dwFlags,
            IntPtr hwndParent,
            IntPtr pwszWizardTitle,
            ref CRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc,
            IntPtr hDestCertStore
        );
 
        public const Int32 CRYPTUI_WIZ_IMPORT_SUBJECT_FILE = 1;
        public const Int32 CRYPT_EXPORTABLE = 0x00000001;
        public const Int32 CRYPT_USER_PROTECTED = 0x00000002;
        public const Int32 CRYPTUI_WIZ_NO_UI = 0x0001;
 
        static void Main(string[] args)
        {
              CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc = new CRYPTUI_WIZ_IMPORT_SRC_INFO();
              importSrc.dwSize = Marshal.SizeOf(importSrc);
              importSrc.dwSubjectChoice = CRYPTUI_WIZ_IMPORT_SUBJECT_FILE;
              importSrc.pwszFileName = "C:\\alex.pfx";
              importSrc.pwszPassword = "password";
              importSrc.dwFlags = CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED;
 
              if (!CryptUIWizImport(
                CRYPTUI_WIZ_NO_UI,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref importSrc,
                    IntPtr.Zero
              ))
              {
                    Console.WriteLine("CryptUIWizImport error " + Marshal.GetLastWin32Error());
              }
 
              Console.WriteLine("<< Press any key to continue >>");
              Console.ReadKey();
        }
    }
}

</SAMPLE>


 


Note: if you enable High protection mode for the private keys of the certificates via policy, when installing a cert in a machine you will be requested for a password which will be used every time the private key is accessed. When using CryptUIWizImport, a dialog will appear requesting us to enter the High protection password, even if we said we don’t want any UI.


I hope this helps.


Cheers,


 


Alex (Alejandro Campos Magencio)

Comments (17)

  1. Jebus says:

    Hi,

    Very interesting article! I’m in need of something similar. I want to export a private key from a certificate using C#.net. The problem is that I don’t want that dialog box to appear when accessing the private key, but supply the password in code. Could I use the same approach as the code above?

    If so, do you have me some hints for me? I don’t have any experience on P/invoke what so ever :s

  2. Do you have High protection mode enabled for your private keys?

  3. Jebus says:

    Yes, that’s the reason I get dialog box. I’d like to export the certificate keys to a RSAParameters-object.

    Turning high protection off is one solution, but then the security of the certificates on server-side is compromised…

  4. Sorry, I haven’t seen a way to pass the high protection password programmatically, with any CryptoAPI I’ve ever used. You should have the same issues I commented with CryptUIWizImport in the article above.

  5. Asif Alam says:

    Using the above code I still get a security warning box..asking me If I would want to install the certificate or not..

    Please tell how to do away with this..

  6. Hi Alam,

    I don’t know right now why you may be getting that security warning box. CRYPTUI_WIZ_NO_UI should get rid of it. If it doesn’t maybe you can open a case with us, Technical Support, and we’ll be more than happy to assist you.

    Cheers,

    Alex

  7. Steven says:

    This is exactly what I am looking for, however, I need to code it using VBA.  Is this possible?

  8. Lux says:

    Hi,

    i’ve done something similar program; but i don’t know how to enable High protection mode with pass via c#.

    if i use CRYPT_USER_PROTECTED my program show the dialog, in this dialog i select high protection and i digit the password.

    do you have me some hints for me?

    thanks

    LuX

  9. Leonardo Maldonado says:

    There is any way to import a certificate revocation list without user interaction? do you have any example?

  10. Bruno says:

    Thanks, that’s exactly what I was looking for.

  11. MdbUK says:

    Hi, alejacma

    Do you have any ideas/examples on how to P/Invoke the CryptUIWizExport function from the Cryptui.dll within C# whilst passing a .NET X509Certificate as a parameter?

    Many thanks!

    Matt

  12. I don't have a sample, but it shouldn't be too difficult to achieve. You can use the Handle property of the X509Certificate2 object to create a CERT_CONTEXT struct (see blogs.msdn.com/…/how-to-call-cryptmsg-api-in-streaming-mode-c.aspx for a sample on how to do that), and then you can pass a pointer to that context to the API.

    If you have a Premier contract you may open an Advisory case and I could assist you on that.

  13. Hi,

    Anyone have this example compiled?

    Thanks

  14. Hi,

    Anyone have this example compiled?

  15. Mariam says:

    Hi

    I need to use this program as a windows service that it runs periodic. every thing is ok, but I dont know what must i do to warning  message that Asif Alam pointed.

    I'll appreciate if you can guide me to solve this

  16. Hi Mariam,

    I haven't "played" with this on Windows services, and I didn't have time to investage about the warning dialog that Asif pointed out, if it is mandatory or if it can be dismissed in any way. If you need urgent help, I suggest you open a Technical Support case with us so we can assist you.

    Regards,

    Alex

  17. Carl Cioffi says:

    I have this code and it works fine but I created the request with certreq and it created a private key file that I don't know the name of so when I import the certificate it doesn't have a private key associated with it.  Does anybody know how to create the private key file with a specific name when user certreq?  I've looked at all of the parameters that go in the .INF file but could not find anything that would allow me to control the name of the private key.

Skip to main content