简体   繁体   English

创建可导出的自签名证书

[英]Create Self Signed Certificate that is Exportable

I am trying to create a self signed certificate on Windows machines. 我试图在Windows机器上创建自签名证书。 I want the certificate be be exportable (even the private keys). 我希望证书可以导出(甚至是私钥)。 However, I am having some difficulty in accomplishing this task. 但是,我在完成这项任务时遇到了一些困难。

I found some web sites that point to the WIN32 calls. 我找到了一些指向WIN32调用的网站。 When I run the code on Windows XP, the certificate is stored in the Personal certificates and can be exported just fine. 当我在Windows XP上运行代码时,证书存储在个人证书中,可以很好地导出。 When I run this code on Windows 7 64-bit, I am getting the certificate an no errors, but the certificate is not exportable. 当我在Windows 7 64位上运行此代码时,我得到的证书没有错误,但证书不可导出。 I cannot then use it for the website I am assigning the certificate to. 我不能将它用于我分配证书的网站。

        Certificate.Check(Certificate.NativeMethods.CryptAcquireContextW(
                out providerContext,
                containerName,
                null,
                1, // PROV_RSA_FULL
                8)); // CRYPT_NEWKEYSET

            Certificate.Check(Certificate.NativeMethods.CryptGenKey(
                providerContext,
                1, // AT_KEYEXCHANGE
                1, // CRYPT_EXPORTABLE
                out cryptKey));

            IntPtr errorStringPtr;
            int nameDataLength = 0;
            byte[] nameData;

            // errorStringPtr gets a pointer into the middle of the x500 string,
            // so x500 needs to be pinned until after we've copied the value
            // of errorStringPtr.
            dataHandle = GCHandle.Alloc(commonName, GCHandleType.Pinned);

            if (!Certificate.NativeMethods.CertStrToNameW(
                0x00000001, // X509_ASN_ENCODING
                dataHandle.AddrOfPinnedObject(),
                3, // CERT_X500_NAME_STR = 3
                IntPtr.Zero,
                null,
                ref nameDataLength,
                out errorStringPtr))
            {
                string error = Marshal.PtrToStringUni(errorStringPtr);
                throw new ArgumentException(error);
            }

            nameData = new byte[nameDataLength];

            if (!Certificate.NativeMethods.CertStrToNameW(
                0x00000001, // X509_ASN_ENCODING
                dataHandle.AddrOfPinnedObject(),
                3, // CERT_X500_NAME_STR = 3
                IntPtr.Zero,
                nameData,
                ref nameDataLength,
                out errorStringPtr))
            {
                string error = Marshal.PtrToStringUni(errorStringPtr);
                throw new ArgumentException(error);
            }
            Console.WriteLine("THIS IS CHANGED");

            dataHandle.Free();

            dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned);
            Certificate.CryptoApiBlob nameBlob = new Certificate.CryptoApiBlob(
                nameData.Length,
                dataHandle.AddrOfPinnedObject());

            Certificate.CryptKeyProviderInformation kpi = new Certificate.CryptKeyProviderInformation();
            kpi.ContainerName = containerName;
            kpi.ProviderType = 1; // PROV_RSA_FULL
            kpi.KeySpec = 1; // AT_KEYEXCHANGE

            certContext = Certificate.NativeMethods.CertCreateSelfSignCertificate(
                IntPtr.Zero,
                ref nameBlob,
                0,
                ref kpi,
                IntPtr.Zero, // default = SHA1RSA
                ref startSystemTime,
                ref endSystemTime,
                IntPtr.Zero);
            Certificate.Check(certContext != IntPtr.Zero);
            dataHandle.Free();

            X509Certificate2 tempCert = new X509Certificate2(certContext);
            //result = new X509Certificate2(tempCert.RawData, "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
            result = tempCert;

            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store.Open(OpenFlags.ReadWrite);
            store.Add(result);
            store.Close();

Note the Certificate class is an internal class that just wraps around the different static methods and WIN32 definitions that I am using. 注意,Certificate类是一个内部类,它只包含我正在使用的不同静态方法和WIN32定义。 Here is the NativeMethods class definition (which shows the WIN32 API calls I am using): 这是NativeMethods类定义(显示我正在使用的WIN32 API调用):

    internal static class NativeMethods
{
    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool FileTimeToSystemTime(
        [In] ref long fileTime,
        out SystemTime systemTime);

    [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CryptAcquireContextW(
        out IntPtr providerContext,
        [MarshalAs(UnmanagedType.LPWStr)] string container,
        [MarshalAs(UnmanagedType.LPWStr)] string provider,
        int providerType,
        int flags);

    [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CryptReleaseContext(
        IntPtr providerContext,
        int flags);

    [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CryptGenKey(
        IntPtr providerContext,
        int algorithmId,
        int flags,
        out IntPtr cryptKeyHandle);

    [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CryptDestroyKey(
        IntPtr cryptKeyHandle);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CertStrToNameW(
        int certificateEncodingType,
        IntPtr x500,
        int strType,
        IntPtr reserved,
        [MarshalAs(UnmanagedType.LPArray)] [Out] byte[] encoded,
        ref int encodedLength,
        out IntPtr errorString);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    public static extern IntPtr CertCreateSelfSignCertificate(
        IntPtr providerHandle,
        [In] ref CryptoApiBlob subjectIssuerBlob,
        int flags,
        [In] ref CryptKeyProviderInformation keyProviderInformation,
        IntPtr signatureAlgorithm,
        [In] ref SystemTime startTime,
        [In] ref SystemTime endTime,
        IntPtr extensions);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CertFreeCertificateContext(
        IntPtr certificateContext);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    public static extern IntPtr CertOpenStore(
        [MarshalAs(UnmanagedType.LPStr)] string storeProvider,
        int messageAndCertificateEncodingType,
        IntPtr cryptProvHandle,
        int flags,
        IntPtr parameters);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CertCloseStore(
        IntPtr certificateStoreHandle,
        int flags);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CertAddCertificateContextToStore(
        IntPtr certificateStoreHandle,
        IntPtr certificateContext,
        int addDisposition,
        out IntPtr storeContextPtr);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CertSetCertificateContextProperty(
        IntPtr certificateContext,
        int propertyId,
        int flags,
        [In] ref CryptKeyProviderInformation data);

    [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool PFXExportCertStoreEx(
        IntPtr certificateStoreHandle,
        ref CryptoApiBlob pfxBlob,
        IntPtr password,
        IntPtr reserved,
        int flags);
}

Does it matter if I am on a 32-bit or 64-bit machine? 如果我在32位或64位机器上是否重要? I am at a loss as to what to do at this point. 我不知道此时该做些什么。 I got this code from the following link: Creating Self Signed Cert in C# 我从以下链接获得此代码: 在C#中创建自签名证书

I found the problem that was causing me to not be able to export the certificate. 我发现问题导致我无法导出证书。 It turns out that I was not actually able to export it on Windows XP either (I had seen it a few times but that was when I was debugging and had not executed code later on that caused it to break). 事实证明,我实际上无法在Windows XP上导出它(我已经看过几次但是那时我正在调试并且之后没有执行代码导致它中断)。

In a clean up routine, the key set was getting deleted: 在清理例程中,密钥集被删除:

NativeMethods.CryptAcquireContextW(
    out providerContext,
    containerName,
    null,
    1, // PROV_RSA_FULL
    0x10); // CRYPT_DELETEKEYSET

This causes the certificate to no longer be able to export the private key. 这会导致证书无法再导出私钥。 When this line was commented out, the certificate was installed in the Personal Certificates store of the Local Computer. 当此行被注释掉时,证书安装在本地计算机的个人证书存储中。 It was also allowed to be exported and therefore allowed me to configure IIS to point to this certificate. 它也被允许导出,因此允许我将IIS配置为指向此证书。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM