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(); } } }
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)
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
Do you have High protection mode enabled for your private keys?
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...
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.
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..
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.
Alex
This is exactly what I am looking for, however, I need to code it using VBA. Is this possible?
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
There is any way to import a certificate revocation list without user interaction? do you have any example?
Thanks, that's exactly what I was looking for.
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
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.
Anyone have this example compiled?
Thanks
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