public static X509Store Load(string file, string password) {
            if (file == null || password == null) {
                return null;
            }

            if (!File.Exists(file)) {
                throw new FileNotFoundException("", file);
            }

            var fileContents = File.ReadAllBytes(file);
            var ptr = Marshal.AllocHGlobal(fileContents.Length);
            Marshal.Copy(fileContents, 0, ptr, fileContents.Length);
            var cryptBlob = new CRYPT_DATA_BLOB {
                cbData = (uint)fileContents.Length,
                pbData = ptr
            };
            if (!PFXIsPFXBlob(ref cryptBlob)) {
                return null;
            }
            if (!PFXVerifyPassword(ref cryptBlob, password)) {
                return null;
            }

            X509Store store = null;
            var storePtr = PFXImportCertStore(ref cryptBlob, password);
            store = new X509Store(storePtr);
            Marshal.FreeHGlobal(ptr);
            return store;
        }
 public static extern IntPtr CertCreateSelfSignCertificate(
     IntPtr hProv,
     ref CRYPT_DATA_BLOB pSubjectIssuerBlob,
     uint dwFlagsm,
     IntPtr pinfo,
     IntPtr pSignatureAlgorithm,
     Native.SYSTEMTIME pStartTime,
     Native.SYSTEMTIME pEndTime,
     IntPtr other);
Example #3
0
    public unsafe void PFXImportCertStoreTest()
    {
        byte[] protectedPfxContent = ReadEmbeddedResource("protectedPair.pfx");
        fixed (byte* pbData = &protectedPfxContent[0])
        {
            var data = new CRYPT_DATA_BLOB
            {
                cbData = protectedPfxContent.Length,
                pbData = pbData,
            };
            using (var handle = PFXImportCertStore(ref data, "123456", PFXImportCertStoreFlags.None))
            {
                if (handle.IsInvalid)
                {
                    throw new Win32Exception();
                }

                Assert.False(handle.IsInvalid);
            }
        }
    }
Example #4
0
    public unsafe void PFXImportCertStoreTest()
    {
        byte[] protectedPfxContent = ReadEmbeddedResource("protectedPair.pfx");
        fixed(byte *pbData = protectedPfxContent)
        {
            var data = new CRYPT_DATA_BLOB
            {
                cbData = protectedPfxContent.Length,
                pbData = pbData,
            };

            using (var handle = PFXImportCertStore(ref data, "123456", PFXImportCertStoreFlags.None))
            {
                if (handle.IsInvalid)
                {
                    throw new Win32Exception();
                }

                Assert.False(handle.IsInvalid);
            }
        }
    }
        public static X509Store Load(string file, string password)
        {
            if (file == null || password == null)
            {
                return(null);
            }

            if (!File.Exists(file))
            {
                throw new FileNotFoundException("", file);
            }

            var fileContents = File.ReadAllBytes(file);
            var ptr          = Marshal.AllocHGlobal(fileContents.Length);

            Marshal.Copy(fileContents, 0, ptr, fileContents.Length);
            var cryptBlob = new CRYPT_DATA_BLOB {
                cbData = (uint)fileContents.Length,
                pbData = ptr
            };

            if (!PFXIsPFXBlob(ref cryptBlob))
            {
                return(null);
            }
            if (!PFXVerifyPassword(ref cryptBlob, password))
            {
                return(null);
            }

            X509Store store    = null;
            var       storePtr = PFXImportCertStore(ref cryptBlob, password);

            store = new X509Store(storePtr);
            Marshal.FreeHGlobal(ptr);
            return(store);
        }
Example #6
0
 public static unsafe extern SafeCertStoreHandle PFXImportCertStore(
     ref CRYPT_DATA_BLOB pPFX,
     string szPassword,
     PFXImportCertStoreFlags dwFlags);
        /// <summary>
        /// Adds the certificate to windows store.
        /// </summary>
        /// <param name="useMachineStore">if set to <c>true</c> [use machine store].</param>
        /// <param name="storeName">Name of the store.</param>
        /// <param name="certificate">The certificate.</param>
        internal static void AddCertificateToWindowsStore(
            bool useMachineStore,
            string storeName,
            X509Certificate2 certificate)
        {
            IntPtr hPfxStore = IntPtr.Zero;
            IntPtr hWindowsStore = IntPtr.Zero;
            IntPtr pName = IntPtr.Zero;
            IntPtr pContext = IntPtr.Zero;
            IntPtr pNewContext = IntPtr.Zero;
            CRYPT_DATA_BLOB tPfxData = new CRYPT_DATA_BLOB();

            try
            {
                byte[] pfxData = certificate.Export(X509ContentType.Pkcs12, (string)null);
                tPfxData.pbData = (IntPtr)Marshal.AllocHGlobal(pfxData.Length);
                tPfxData.cbData = pfxData.Length;
                Marshal.Copy(pfxData, 0, tPfxData.pbData, pfxData.Length);

                // import the PKCS#12 blob back into a file store.
                hPfxStore = NativeMethods.PFXImportCertStore(
                    ref tPfxData,
                    null,
                    GetFlags(useMachineStore, CRYPT_EXPORTABLE, CRYPT_MACHINE_KEYSET, CRYPT_USER_KEYSET));

                if (hPfxStore == IntPtr.Zero)
                {
                    hPfxStore = NativeMethods.PFXImportCertStore(
                        ref tPfxData,
                        String.Empty,
                        GetFlags(useMachineStore, CRYPT_EXPORTABLE, CRYPT_MACHINE_KEYSET, CRYPT_USER_KEYSET));

                    if (hPfxStore == IntPtr.Zero)
                    {
                        Throw("Could not import the certificate to a PKCS#12 store. Error={0:X8} Subject={1}", Marshal.GetLastWin32Error(), certificate.Subject);
                    }
                }

                pName = Marshal.StringToHGlobalUni(storeName);

                // open the store.
                hWindowsStore = NativeMethods.CertOpenStore(
                   (IntPtr)CERT_STORE_PROV_SYSTEM,
                   0,
                   IntPtr.Zero,
                   GetFlags(useMachineStore, 0,CERT_SYSTEM_STORE_LOCAL_MACHINE, CERT_SYSTEM_STORE_CURRENT_USER),
                   pName);

                if (hWindowsStore == IntPtr.Zero)
                {
                    Throw("Could not open the windows certificate store. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // Find the certificates in the system store. 
                pContext = NativeMethods.CertEnumCertificatesInStore(hPfxStore, IntPtr.Zero);

                while (pContext != IntPtr.Zero)
                {
                    // add back into store.
                    int bResult = NativeMethods.CertAddCertificateContextToStore(
                        hWindowsStore,
                        pContext,
                        CERT_STORE_ADD_REPLACE_EXISTING,
                        ref pNewContext);

                    if (bResult == 0)
                    {
                        Throw("Could not add the certificate to the windows store. Error={0:X8}", Marshal.GetLastWin32Error());
                    }

                    NativeMethods.CertFreeCertificateContext(pNewContext);
                    pNewContext = IntPtr.Zero;

                    // get next certificate.
                    pContext = NativeMethods.CertEnumCertificatesInStore(hPfxStore, pContext);
                }
            }
            finally
            {
                if (pName != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pName);
                }

                if (pContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pContext);
                }

                if (pNewContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pNewContext);
                }

                if (tPfxData.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(tPfxData.pbData);
                }

                if (hWindowsStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(hWindowsStore, 0);
                }

                if (hPfxStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(hPfxStore, 0);
                }
            }
        }
 public static extern int PFXExportCertStoreEx(IntPtr hStore, ref CRYPT_DATA_BLOB pPFX, string szPassword, IntPtr pvReserved, ExportCertStoreFlags dwFlags);
Example #9
0
 int CertTimestampAuthenticodeLicense(
     [In]      ref CRYPT_DATA_BLOB pSignedLicenseBlob,
     [In]      string pwszTimestampURI,
     [In, Out]  ref CRYPT_DATA_BLOB pTimestampSignatureBlob);
Example #10
0
 public static extern bool PFXIsPFXBlob(ref CRYPT_DATA_BLOB pPfx);
 private static extern bool PFXIsPFXBlob(
     ref CRYPT_DATA_BLOB pPfx);
Example #12
0
 private static extern bool PFXVerifyPassword(
     ref CRYPT_DATA_BLOB pPfx,
     [MarshalAs(UnmanagedType.LPWStr)] String szPassword,
     uint dwFlags = 0);
 public static extern int PFXExportCertStoreEx(
     IntPtr hStore,
     ref CRYPT_DATA_BLOB pPFX,
     [MarshalAs(UnmanagedType.LPWStr)]
     string szPassword,
     IntPtr pvReserved,
     int dwFlags);
        /// <summary>
        /// Calculates the public key identifier.
        /// </summary>
        private static CRYPT_DATA_BLOB GetPublicKeyIdentifier(IntPtr hProvider, ref CRYPT_DATA_BLOB publicKeyId)
        {
            IntPtr pPublicKeyInfo = IntPtr.Zero;

            try
            {
                // determine the size of the public key info structure.
                int dwKeySize = 0;

                int bResult = NativeMethods.CryptExportPublicKeyInfoEx(
                    hProvider,
                    AT_KEYEXCHANGE,
                    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                    szOID_RSA_RSA,
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref dwKeySize);

                if (bResult == 0)
                {
                    Throw("Cannot get size of the public key info structure. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                pPublicKeyInfo = Marshal.AllocHGlobal(dwKeySize);

                // export the public key info structure.
                bResult = NativeMethods.CryptExportPublicKeyInfoEx(
                    hProvider,
                    AT_KEYEXCHANGE,
                    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                    szOID_RSA_RSA,
                    0,
                    IntPtr.Zero,
                    pPublicKeyInfo,
                    ref dwKeySize);

                if (bResult == 0)
                {
                    Throw("Cannot get export the public key info structure. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // calculate the SHA1 hash of the public key info.
                publicKeyId.cbData = 20;
                publicKeyId.pbData = (IntPtr)Marshal.AllocHGlobal(publicKeyId.cbData);

                bResult = NativeMethods.CryptHashPublicKeyInfo(
                    hProvider,
                    CALG_SHA1,
                    0,
                    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                    pPublicKeyInfo,
                    publicKeyId.pbData,
                    ref publicKeyId.cbData);

                if (bResult == 0)
                {
                    Throw("Cannot calculate the hash for the public key info structure. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // return the hash.
                return publicKeyId;
            }
            finally
            {
                if (pPublicKeyInfo != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pPublicKeyInfo);
                }
            }
        }
Example #15
0
 int _AxlPublicKeyBlobToPublicKeyToken(
     [In]     ref CRYPT_DATA_BLOB pCspPublicKeyBlob,
     [In, Out] ref IntPtr ppwszPublicKeyToken);
Example #16
0
 int _AxlRSAKeyValueToPublicKeyToken(
     [In]     ref CRYPT_DATA_BLOB pModulusBlob,
     [In]     ref CRYPT_DATA_BLOB pExponentBlob,
     [In, Out] ref IntPtr ppwszPublicKeyToken);
Example #17
0
 int CertVerifyAuthenticodeLicense(
     [In]      ref CRYPT_DATA_BLOB pLicenseBlob,
     [In]      uint dwFlags,
     [In, Out]  ref AXL_SIGNER_INFO pSignerInfo,
     [In, Out]  ref AXL_TIMESTAMPER_INFO pTimestamperInfo);
Example #18
0
 private static extern IntPtr PFXImportCertStore(
     ref CRYPT_DATA_BLOB pPfx,
     [MarshalAs(UnmanagedType.LPWStr)] String szPassword,
     uint dwFlags = 0);
 public static extern IntPtr PFXImportCertStore(
     ref CRYPT_DATA_BLOB pPfx,
     [MarshalAs(UnmanagedType.LPWStr)] String szPassword,
     uint dwFlags);
Example #20
0
 private static extern bool PFXIsPFXBlob(
     ref CRYPT_DATA_BLOB pPfx);
 public static extern bool PFXIsPFXBlob(ref CRYPT_DATA_BLOB pPfx);
        /// <summary>
        /// Creates the certificate and adds it to the store.
        /// </summary>
        private static string CreateSelfSignedCertificate(
            IntPtr hProvider,
            IntPtr hStore,
            bool useMachineStore,
            string applicationName,
            string applicationUri,
            string subjectName,
            IList<string> hostNames,
            ushort keySize,
            ushort lifetimeInMonths,
            ushort algorithm = 0)
        {
            IntPtr hKey = IntPtr.Zero;
            IntPtr pKpi = IntPtr.Zero;
            IntPtr pThumbprint = IntPtr.Zero;
            IntPtr pContext = IntPtr.Zero;
            IntPtr pAlgorithmId = IntPtr.Zero;
            IntPtr pNewContext = IntPtr.Zero;
            CRYPT_DATA_BLOB publicKeyId = new CRYPT_DATA_BLOB();
            CERT_NAME_BLOB subjectNameBlob = new CERT_NAME_BLOB();
            SYSTEMTIME stValidTo = new SYSTEMTIME();
            CERT_EXTENSIONS extensions = new CERT_EXTENSIONS();
            CRYPT_DATA_BLOB friendlyName = new CRYPT_DATA_BLOB();

            GCHandle hValidTo = new GCHandle();
            GCHandle hExtensionList = new GCHandle();
            GCHandle hSubjectNameBlob = new GCHandle();
            GCHandle hFriendlyName = new GCHandle();

            try
            {
                // create a new key pair.
                int bResult = NativeMethods.CryptGenKey(
                    hProvider,
                    AT_KEYEXCHANGE,
                    CRYPT_EXPORTABLE | (keySize << 16),
                    ref hKey);

                if (bResult == 0)
                {
                    Throw("Could not generate a new key pair. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // gey the public key identifier.
                GetPublicKeyIdentifier(hProvider, ref publicKeyId);

                // construct the certificate subject name.
                CreateX500Name(subjectName, ref subjectNameBlob);
                GCHandle hSubjectName = GCHandle.Alloc(subjectNameBlob, GCHandleType.Pinned);

                // allocate memory for all possible extensions.
                extensions.cExtension = 0;
                extensions.rgExtension = Marshal.AllocHGlobal(6 * Marshal.SizeOf(typeof(CERT_EXTENSION)));

                // create the subject key info extension.
                IntPtr pPos = extensions.rgExtension;
                CERT_EXTENSION extension = new CERT_EXTENSION();
                CreateSubjectKeyIdentifierExtension(ref extension, ref publicKeyId);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the authority key info extension.
                extension = new CERT_EXTENSION();
                CreateAuthorityKeyIdentifierExtension(ref extension, ref publicKeyId);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the basic constraints extension.
                extension = new CERT_EXTENSION();
                CreateBasicConstraintsExtension(ref extension, false);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the key usage extension.
                extension = new CERT_EXTENSION();
                CreateKeyUsageExtension(ref extension, false);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the extended key usage extension.
                extension = new CERT_EXTENSION();
                CreateExtendedKeyUsageExtension(ref extension);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the subject alternate name extension.
                extension = new CERT_EXTENSION();
                CreateSubjectAltNameExtension(applicationUri, hostNames, ref extension);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // set the expiration date.
                DateTime validTo = DateTime.UtcNow.AddMonths(lifetimeInMonths);
                System.Runtime.InteropServices.ComTypes.FILETIME ftValidTo = new System.Runtime.InteropServices.ComTypes.FILETIME();
                ulong ticks = (ulong)(validTo.Ticks - new DateTime(1601, 1, 1).Ticks);
                ftValidTo.dwHighDateTime = (int)((0xFFFFFFFF00000000 & (ulong)ticks) >> 32);
                ftValidTo.dwLowDateTime = (int)((ulong)ticks & 0x00000000FFFFFFFF);

                NativeMethods.FileTimeToSystemTime(ref ftValidTo, ref stValidTo);

                // specify what key is being used to sign the certificate.
                CRYPT_KEY_PROV_INFO kpi = new CRYPT_KEY_PROV_INFO();

                kpi.pwszContainerName = KEY_CONTAINER_NAME; // must be the same as the hProvider
                kpi.pwszProvName = DEFAULT_CRYPTO_PROVIDER;
                kpi.dwProvType = PROV_RSA_FULL;
                kpi.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
                kpi.dwKeySpec = AT_KEYEXCHANGE;

                if (useMachineStore)
                {
                    kpi.dwFlags |= CRYPT_MACHINE_KEYSET;
                }
                else
                {
                    kpi.dwFlags |= CRYPT_USER_KEYSET;
                }

                pKpi = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CRYPT_KEY_PROV_INFO)));
                Marshal.StructureToPtr(kpi, pKpi, false);

                hValidTo = GCHandle.Alloc(stValidTo, GCHandleType.Pinned);
                hExtensionList = GCHandle.Alloc(extensions, GCHandleType.Pinned);
                hSubjectNameBlob = GCHandle.Alloc(subjectNameBlob, GCHandleType.Pinned);

                if (algorithm == 1)
                {
                    CRYPT_ALGORITHM_IDENTIFIER algorithmID = new CRYPT_ALGORITHM_IDENTIFIER();
                    algorithmID.pszObjId = "1.2.840.113549.1.1.11"; //SHA256

                    pAlgorithmId = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CRYPT_ALGORITHM_IDENTIFIER)));
                    Marshal.StructureToPtr(algorithmID, pAlgorithmId, false);

                    //create the certificate
                    pContext = NativeMethods.CertCreateSelfSignCertificate(
                         hProvider,
                         hSubjectNameBlob.AddrOfPinnedObject(),
                         0,
                         pKpi,
                         pAlgorithmId,
                         IntPtr.Zero,
                         hValidTo.AddrOfPinnedObject(),
                         hExtensionList.AddrOfPinnedObject());
                }
                else
                {
                    // (default) create the certificate.
                    pContext = NativeMethods.CertCreateSelfSignCertificate(
                    hProvider,
                    hSubjectNameBlob.AddrOfPinnedObject(),
                    0,
                    pKpi,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    hValidTo.AddrOfPinnedObject(),
                    hExtensionList.AddrOfPinnedObject());
                }

                if (pContext == IntPtr.Zero)
                {
                    Throw("Could not create self-signed certificate. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // get the thumbprint.
                int dwThumbprintSize = 20;
                pThumbprint = Marshal.AllocHGlobal(dwThumbprintSize);

                bResult = NativeMethods.CertGetCertificateContextProperty(
                    pContext,
                    CERT_SHA1_HASH_PROP_ID,
                    pThumbprint,
                    ref dwThumbprintSize);

                if (bResult == 0)
                {
                    Throw("Could not get the thumbprint of the new certificate. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                byte[] bytes = new byte[dwThumbprintSize];
                Marshal.Copy(pThumbprint, bytes, 0, dwThumbprintSize);
                string thumbprint = Utils.ToHexString(bytes);

                // set the friendly name.
                friendlyName.pbData = Marshal.StringToHGlobalUni(applicationName);
                friendlyName.cbData = (applicationName.Length+1)*Marshal.SizeOf(typeof(ushort));
                hFriendlyName = GCHandle.Alloc(friendlyName, GCHandleType.Pinned);

                bResult = NativeMethods.CertSetCertificateContextProperty(
                    pContext,
                    CERT_FRIENDLY_NAME_PROP_ID,
                    0,
                    hFriendlyName.AddrOfPinnedObject());

                if (bResult == 0)
                {
                    Throw("Could not set the friendly name for the certificate. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // add into store.
                bResult = NativeMethods.CertAddCertificateContextToStore(
                    hStore,
                    pContext,
                    CERT_STORE_ADD_REPLACE_EXISTING,
                    ref pNewContext);

                if (bResult == 0)
                {
                    Throw("Could not add the certificate to the store. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                return thumbprint;
            }
            finally
            {
                if (pContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pContext);
                }

                if (pNewContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pNewContext);
                }

                if (friendlyName.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(friendlyName.pbData);
                }

                if (pThumbprint != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pThumbprint);
                }

                if (pAlgorithmId != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pAlgorithmId, typeof(CRYPT_ALGORITHM_IDENTIFIER));
                    Marshal.FreeHGlobal(pAlgorithmId);
                }

                if (hValidTo.IsAllocated) hValidTo.Free();
                if (hExtensionList.IsAllocated) hExtensionList.Free();
                if (hSubjectNameBlob.IsAllocated) hSubjectNameBlob.Free();
                if (hFriendlyName.IsAllocated) hFriendlyName.Free();

                if (pKpi != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pKpi, typeof(CRYPT_KEY_PROV_INFO));
                    Marshal.FreeHGlobal(pKpi);
                }

                DeleteExtensions(ref extensions.rgExtension, extensions.cExtension);
                DeleteX500Name(ref subjectNameBlob);

                if (publicKeyId.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(publicKeyId.pbData);
                }

                if (hKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(hKey);
                }
            }
        }
Example #23
0
 public static extern bool PFXExportCertStoreEx([System.Runtime.InteropServices.InAttribute()] System.IntPtr hStore, ref CRYPT_DATA_BLOB pPFX, [System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string szPassword, System.IntPtr pvReserved, uint dwFlags);
        /// <summary>
        /// Creates the certificate.
        /// </summary>
        private static X509Certificate2 CreateCertificate(
            bool useMachineStore,
            string applicationName,
            string applicationUri,
            string subjectName,
            IList<string> hostNames,
            ushort keySize,
            ushort lifetimeInMonths,
            ushort algorithm = 0)
        {
            IntPtr hProvider = IntPtr.Zero;
            IntPtr hMemoryStore = IntPtr.Zero;
            IntPtr hPfxStore = IntPtr.Zero;
            IntPtr hWindowsStore = IntPtr.Zero;
            IntPtr pName = IntPtr.Zero;
            IntPtr pContext = IntPtr.Zero;
            IntPtr pNewContext = IntPtr.Zero;
            CRYPT_DATA_BLOB tPfxData = new CRYPT_DATA_BLOB();

            try
            {
                // create a container for the keys.
                int bResult = NativeMethods.CryptAcquireContextW(
                    ref hProvider,
                    KEY_CONTAINER_NAME,
                    DEFAULT_CRYPTO_PROVIDER,
                    PROV_RSA_FULL,
                    CRYPT_MACHINE_KEYSET);

                if (bResult == 0)
                {
                    bResult = NativeMethods.CryptAcquireContextW(
                        ref hProvider,
                        KEY_CONTAINER_NAME,
                        DEFAULT_CRYPTO_PROVIDER,
                        PROV_RSA_FULL,
                        CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET);

                    if (bResult == 0)
                    {
                        Throw("Could not create a container for the new key pair. Error={0:X8}", Marshal.GetLastWin32Error());
                    }
                }

                // create memory store to hold the new certificate.
                hMemoryStore = NativeMethods.CertOpenStore(
                    (IntPtr)CERT_STORE_PROV_MEMORY,
                    0,
                    IntPtr.Zero,
                    0,
                    IntPtr.Zero);

                if (hMemoryStore == IntPtr.Zero)
                {
                    Throw("Could not create a temporary memory store. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // create the certificate.
                string thumbprint = CreateSelfSignedCertificate(
                    hProvider,
                    hMemoryStore,
                    useMachineStore,
                    applicationName,
                    applicationUri,
                    subjectName,
                    hostNames,
                    keySize,
                    lifetimeInMonths,
                    algorithm);

                // determine the size of the PKCS#12 blob.
                bResult = NativeMethods.PFXExportCertStoreEx(
                    hMemoryStore,
                    ref tPfxData,
                    null,
                    IntPtr.Zero,
                    EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY);

                if (bResult == 0)
                {
                    Throw("Could not determine the size of the PKCS#12 blob. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                tPfxData.pbData = (IntPtr)Marshal.AllocHGlobal(tPfxData.cbData);

                // export the PKCS#12 blob.
                bResult = NativeMethods.PFXExportCertStoreEx(
                    hMemoryStore,
                    ref tPfxData,
                    null,
                    IntPtr.Zero,
                    EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY);

                if (bResult == 0)
                {
                    Throw("Could not export the certificate to a PKCS#12 blob. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // create certificate.
                byte[] bytes = new byte[tPfxData.cbData];
                Marshal.Copy(tPfxData.pbData, bytes, 0, tPfxData.cbData);

                X509Certificate2 certificate = new X509Certificate2(
                    bytes,
                    (string)null,
                    X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);

                return certificate;
            }
            finally
            {
                if (pName != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pName);
                }

                if (pContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pContext);
                }

                if (pNewContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pNewContext);
                }

                if (tPfxData.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(tPfxData.pbData);
                }

                if (hWindowsStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(hWindowsStore, 0);
                }

                if (hPfxStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(hPfxStore, 0);
                }

                if (hMemoryStore != IntPtr.Zero)
                {
                    NativeMethods.CertCloseStore(hMemoryStore, 0);
                }

                // delete any existing container.
                int bResult = NativeMethods.CryptAcquireContextW(
                    ref hProvider,
                    KEY_CONTAINER_NAME,
                    DEFAULT_CRYPTO_PROVIDER,
                    PROV_RSA_FULL,
                    CRYPT_DELETEKEYSET | CRYPT_MACHINE_KEYSET);

                if (bResult == 0)
                {
                    Utils.Trace("Could not delete the container used for the key pair. Error={0:X8}", Marshal.GetLastWin32Error());
                }
            }
        }
        // creates the basic constraints extension.
        private static void CreateSubjectKeyIdentifierExtension(ref CERT_EXTENSION pExtension, ref CRYPT_DATA_BLOB pKeyId)
        {
	        pExtension.pszObjId  = szOID_SUBJECT_KEY_IDENTIFIER;
	        pExtension.fCritical = 0;

            GCHandle hKey = GCHandle.Alloc(pKeyId, GCHandleType.Pinned);
            IntPtr pData = IntPtr.Zero;
            int dwDataSize = 0;

            try
            {
	            // calculate amount of memory required.
                int bResult = NativeMethods.CryptEncodeObjectEx(
		            X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		            szOID_SUBJECT_KEY_IDENTIFIER,
		            hKey.AddrOfPinnedObject(),
		            0,
		            IntPtr.Zero,
	                IntPtr.Zero,
		            ref dwDataSize);

	            if (bResult == 0)
	            {
		            throw new InvalidOperationException("Could not get size for subject key info extension.");
	            }

	            // allocate memory.
	            pData = Marshal.AllocHGlobal(dwDataSize);

	            // encode blob.
                bResult = NativeMethods.CryptEncodeObjectEx(
		            X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		            szOID_SUBJECT_KEY_IDENTIFIER,
		            hKey.AddrOfPinnedObject(),
		            0,
		            IntPtr.Zero,
		            pData,
		            ref dwDataSize);

	            if (bResult == 0)
	            {
                    throw new InvalidOperationException("Could not create for subject key info extension.");
	            }

                pExtension.Value.cbData = dwDataSize;
                pExtension.Value.pbData = pData;
                pData = IntPtr.Zero;
            }
            finally
            {
                if (pData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pData);
                }

                if (hKey.IsAllocated)
                {
                    hKey.Free();
                }
            }
        }
 public static extern bool PFXVerifyPassword(
     ref CRYPT_DATA_BLOB pPfx,
     [MarshalAs(UnmanagedType.LPWStr)] String szPassword,
     uint dwFlags);
        // creates the basic constraints extension.
        static void CreateAuthorityKeyIdentifierExtension(
            ref CERT_EXTENSION pExtension,
            ref CRYPT_DATA_BLOB pKeyId)
        {
	        // set the certificate as a non-CA certificate.
            CERT_AUTHORITY_KEY_ID2_INFO keyInfo = new CERT_AUTHORITY_KEY_ID2_INFO();

	        keyInfo.KeyId.cbData = pKeyId.cbData;
	        keyInfo.KeyId.pbData = pKeyId.pbData;

	        pExtension.pszObjId  = szOID_AUTHORITY_KEY_IDENTIFIER2;
	        pExtension.fCritical = 0;
            
            GCHandle hKeyInfo = GCHandle.Alloc(keyInfo, GCHandleType.Pinned);
            IntPtr pData = IntPtr.Zero;
            int dwDataSize = 0;

            try
            {
	            // calculate amount of memory required.
                int bResult = NativeMethods.CryptEncodeObjectEx(
		            X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		            szOID_AUTHORITY_KEY_IDENTIFIER2, // X509_AUTHORITY_KEY_ID,
		            hKeyInfo.AddrOfPinnedObject(),
		            0,
		            IntPtr.Zero,
	                IntPtr.Zero,
		            ref dwDataSize);

	            if (bResult == 0)
	            {
		            throw new InvalidOperationException("Could not get size for basic constraints extension.");
	            }

	            // allocate memory.
	            pData = Marshal.AllocHGlobal(dwDataSize);

	            // encode blob.
                bResult = NativeMethods.CryptEncodeObjectEx(
		            X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		            szOID_AUTHORITY_KEY_IDENTIFIER2, // X509_AUTHORITY_KEY_ID,
		            hKeyInfo.AddrOfPinnedObject(),
		            0,
		            IntPtr.Zero,
		            pData,
		            ref dwDataSize);

	            if (bResult == 0)
	            {
		            throw new InvalidOperationException("Could not create for basic constraints extension.");
	            }

                pExtension.Value.cbData = dwDataSize;
                pExtension.Value.pbData = pData;
                pData = IntPtr.Zero;
            }
            finally
            {
                if (pData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pData);
                }

                if (hKeyInfo.IsAllocated)
                {
                    hKeyInfo.Free();
                }
            }
        }
Example #28
0
 public static extern SafeCertStoreHandle PFXImportCertStore(
     ref CRYPT_DATA_BLOB pPFX,
     string szPassword,
     PFXImportCertStoreFlags dwFlags);
 internal static extern int CertNameToStr(X509Encoding dwCertEncodingType, ref CRYPT_DATA_BLOB pName, CertNameType dwStrType, [In, Out] char[] psz, int csz);