views:

282

answers:

1

Hi, I wonder how to change the password for .pfx file using crypt32.dll. I tried :

public bool ChangePassword(String pfxfilename, String pswd, String newPfxfilename,  String newPswd) {

        IntPtr hMemStore = IntPtr.Zero;
        IntPtr hCertCntxt = IntPtr.Zero;
        IntPtr pProvInfo = IntPtr.Zero;

        bool result = false;

        if (!File.Exists(pfxfilename)) {
            Console.WriteLine("File '{0}' not found.", pfxfilename);
            return result;
        }

        byte[] pfxdata = PfxOpen.GetFileBytes(pfxfilename);
        if (pfxdata == null || pfxdata.Length == 0)
            return result;

        CRYPT_DATA_BLOB ppfx = new CRYPT_DATA_BLOB();
        ppfx.cbData = pfxdata.Length;
        ppfx.pbData = Marshal.AllocHGlobal(pfxdata.Length);
        Marshal.Copy(pfxdata, 0, ppfx.pbData, pfxdata.Length);

        if (!Win32.PFXIsPFXBlob(ref ppfx)) {
            Console.WriteLine("!!!! File '{0}' is NOT a valid pfx blob !!!", pfxfilename);
            return result;
        }

        hMemStore = Win32.PFXImportCertStore(ref ppfx, pswd, CRYPT_USER_KEYSET);
        if (hMemStore == IntPtr.Zero) {
            string errormessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
            Console.WriteLine("\n{0}", errormessage);
            Marshal.FreeHGlobal(ppfx.pbData);
            return result;
        }

        const uint EXPORT_PRIVATE_KEYS = 0x0004;
        const uint REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY = 0x0002;
        const uint pfxflags = EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY;

        CRYPT_DATA_BLOB newppfx = new CRYPT_DATA_BLOB();
        newppfx.pbData = IntPtr.Zero;
        newppfx.cbData = 0;
        if (Win32.PFXExportCertStoreEx(hMemStore, ref newppfx, pswd, IntPtr.Zero, pfxflags)) {
            newppfx.pbData = Marshal.AllocHGlobal(newppfx.cbData);

            if (Win32.PFXExportCertStoreEx(hMemStore, ref newppfx, newPswd, IntPtr.Zero, pfxflags)) {
                byte[] pfxblob = new byte[newppfx.cbData];
                Marshal.Copy(newppfx.pbData, pfxblob, 0, newppfx.cbData);
                Marshal.FreeHGlobal(newppfx.pbData);

                PfxOpen.WriteFileBytes(newPfxfilename, pfxblob);
            }                
        }

        Marshal.FreeHGlobal(ppfx.pbData);
        Marshal.FreeHGlobal(newppfx.pbData);

        if (pProvInfo != IntPtr.Zero)
            Marshal.FreeHGlobal(pProvInfo);
        if (hCertCntxt != IntPtr.Zero)
            Win32.CertFreeCertificateContext(hCertCntxt);
        if (hMemStore != IntPtr.Zero)
            Win32.CertCloseStore(hMemStore, 0);
        return result;
    }
A: 

You can use the X509Certificate2 class. It has an Export method that lets you set its password.

klausbyskov