{"id":418,"date":"2015-04-03T22:23:00","date_gmt":"2015-04-03T22:23:00","guid":{"rendered":"d1f255a373a3cef72e03aa9d980c7eca"},"modified":"2015-04-03T22:23:00","modified_gmt":"2015-04-03T22:23:00","slug":"","status":"publish","type":"post","link":"https:\/\/www.xiaobo.li\/notes\/archives\/418","title":{"rendered":"\u7f51\u4e0a\u627e\u5230\u7684\u4e00\u4e2a dot net X509 \u8bc1\u4e66\u751f\u6210\u7c7b"},"content":{"rendered":"<p>\u7f51\u4e0a\u627e\u5230\u7684\u4e00\u4e2a&nbsp;dot net&nbsp;X509 \u8bc1\u4e66\u751f\u6210\u7c7b<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"brush:c#; toolbar: true; auto-links: true;\">using System;\r\nusing System.Runtime.InteropServices;\r\nusing System.Security.Cryptography.X509Certificates;\r\nusing SecureString = System.Security.SecureString;\r\nusing RuntimeHelpers = System.Runtime.CompilerServices.RuntimeHelpers;\r\n\r\ninternal class Certificate\r\n{\r\n    public static byte[] CreateSelfSignCertificatePfx(\r\n        string x500,\r\n        DateTime startTime,\r\n        DateTime endTime)\r\n    {\r\n        byte[] pfxData = CreateSelfSignCertificatePfx(\r\n            x500,\r\n            startTime,\r\n            endTime,\r\n            (SecureString)null);\r\n        return pfxData;\r\n    }\r\n\r\n    public static byte[] CreateSelfSignCertificatePfx(\r\n        string x500,\r\n        DateTime startTime,\r\n        DateTime endTime,\r\n        string insecurePassword)\r\n    {\r\n        byte[] pfxData;\r\n        SecureString password = null;\r\n\r\n        try\r\n        {\r\n            if (!string.IsNullOrEmpty(insecurePassword))\r\n            {\r\n                password = new SecureString();\r\n                foreach (char ch in insecurePassword)\r\n                {\r\n                    password.AppendChar(ch);\r\n                }\r\n\r\n                password.MakeReadOnly();\r\n            }\r\n\r\n            pfxData = CreateSelfSignCertificatePfx(\r\n                x500,\r\n                startTime,\r\n                endTime,\r\n                password);\r\n        }\r\n        finally\r\n        {\r\n            if (password != null)\r\n            {\r\n                password.Dispose();\r\n            }\r\n        }\r\n\r\n        return pfxData;\r\n    }\r\n\r\n    public static byte[] CreateSelfSignCertificatePfx(\r\n        string x500,\r\n        DateTime startTime,\r\n        DateTime endTime,\r\n        SecureString password)\r\n    {\r\n        byte[] pfxData;\r\n\r\n        if (x500 == null)\r\n        {\r\n            x500 = \"\";\r\n        }\r\n\r\n        SystemTime startSystemTime = ToSystemTime(startTime);\r\n        SystemTime endSystemTime = ToSystemTime(endTime);\r\n        string containerName = Guid.NewGuid().ToString();\r\n\r\n        GCHandle dataHandle = new GCHandle();\r\n        IntPtr providerContext = IntPtr.Zero;\r\n        IntPtr cryptKey = IntPtr.Zero;\r\n        IntPtr certContext = IntPtr.Zero;\r\n        IntPtr certStore = IntPtr.Zero;\r\n        IntPtr storeCertContext = IntPtr.Zero;\r\n        IntPtr passwordPtr = IntPtr.Zero;\r\n        RuntimeHelpers.PrepareConstrainedRegions();\r\n        try\r\n        {\r\n            Check(NativeMethods.CryptAcquireContextW(\r\n                out providerContext,\r\n                containerName,\r\n                null,\r\n                1, \/\/ PROV_RSA_FULL\r\n                8)); \/\/ CRYPT_NEWKEYSET\r\n\r\n            Check(NativeMethods.CryptGenKey(\r\n                providerContext,\r\n                1, \/\/ AT_KEYEXCHANGE\r\n                1, \/\/ CRYPT_EXPORTABLE\r\n                out cryptKey));\r\n\r\n            IntPtr errorStringPtr;\r\n            int nameDataLength = 0;\r\n            byte[] nameData;\r\n\r\n            \/\/ errorStringPtr gets a pointer into the middle of the x500 string,\r\n            \/\/ so x500 needs to be pinned until after we've copied the value\r\n            \/\/ of errorStringPtr.\r\n            dataHandle = GCHandle.Alloc(x500, GCHandleType.Pinned);\r\n\r\n            if (!NativeMethods.CertStrToNameW(\r\n                0x00010001, \/\/ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING\r\n                dataHandle.AddrOfPinnedObject(),\r\n                3, \/\/ CERT_X500_NAME_STR = 3\r\n                IntPtr.Zero,\r\n                null,\r\n                ref nameDataLength,\r\n                out errorStringPtr))\r\n            {\r\n                string error = Marshal.PtrToStringUni(errorStringPtr);\r\n                throw new ArgumentException(error);\r\n            }\r\n\r\n            nameData = new byte[nameDataLength];\r\n\r\n            if (!NativeMethods.CertStrToNameW(\r\n                0x00010001, \/\/ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING\r\n                dataHandle.AddrOfPinnedObject(),\r\n                3, \/\/ CERT_X500_NAME_STR = 3\r\n                IntPtr.Zero,\r\n                nameData,\r\n                ref nameDataLength,\r\n                out errorStringPtr))\r\n            {\r\n                string error = Marshal.PtrToStringUni(errorStringPtr);\r\n                throw new ArgumentException(error);\r\n            }\r\n\r\n            dataHandle.Free();\r\n            \r\n            dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned);\r\n            CryptoApiBlob nameBlob = new CryptoApiBlob(\r\n                nameData.Length,\r\n                dataHandle.AddrOfPinnedObject());\r\n\r\n            CryptKeyProviderInformation kpi = new CryptKeyProviderInformation();\r\n            kpi.ContainerName = containerName;\r\n            kpi.ProviderType = 1; \/\/ PROV_RSA_FULL\r\n            kpi.KeySpec = 1; \/\/ AT_KEYEXCHANGE\r\n\r\n            certContext = NativeMethods.CertCreateSelfSignCertificate(\r\n                providerContext,\r\n                ref nameBlob,\r\n                0,\r\n                ref kpi,\r\n                IntPtr.Zero, \/\/ default = SHA1RSA\r\n                ref startSystemTime,\r\n                ref endSystemTime,\r\n                IntPtr.Zero);\r\n            Check(certContext != IntPtr.Zero);\r\n            dataHandle.Free();\r\n\r\n            certStore = NativeMethods.CertOpenStore(\r\n                \"Memory\", \/\/ sz_CERT_STORE_PROV_MEMORY\r\n                0,\r\n                IntPtr.Zero,\r\n                0x2000, \/\/ CERT_STORE_CREATE_NEW_FLAG\r\n                IntPtr.Zero);\r\n            Check(certStore != IntPtr.Zero);\r\n\r\n            Check(NativeMethods.CertAddCertificateContextToStore(\r\n                certStore,\r\n                certContext,\r\n                1, \/\/ CERT_STORE_ADD_NEW\r\n                out storeCertContext));\r\n\r\n            NativeMethods.CertSetCertificateContextProperty(\r\n                storeCertContext,\r\n                2, \/\/ CERT_KEY_PROV_INFO_PROP_ID\r\n                0,\r\n                ref kpi);\r\n\r\n            if (password != null)\r\n            {\r\n                passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password);\r\n            }\r\n\r\n            CryptoApiBlob pfxBlob = new CryptoApiBlob();\r\n            Check(NativeMethods.PFXExportCertStoreEx(\r\n                certStore,\r\n                ref pfxBlob,\r\n                passwordPtr,\r\n                IntPtr.Zero,\r\n                7)); \/\/ EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY\r\n\r\n            pfxData = new byte[pfxBlob.DataLength];\r\n            dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned);\r\n            pfxBlob.Data = dataHandle.AddrOfPinnedObject();\r\n            Check(NativeMethods.PFXExportCertStoreEx(\r\n                certStore,\r\n                ref pfxBlob,\r\n                passwordPtr,\r\n                IntPtr.Zero,\r\n                7)); \/\/ EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY\r\n            dataHandle.Free();\r\n        }\r\n        finally\r\n        {\r\n            if (passwordPtr != IntPtr.Zero)\r\n            {\r\n                Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr);\r\n            }\r\n\r\n            if (dataHandle.IsAllocated)\r\n            {\r\n                dataHandle.Free();\r\n            }\r\n\r\n            if (certContext != IntPtr.Zero)\r\n            {\r\n                NativeMethods.CertFreeCertificateContext(certContext);\r\n            }\r\n\r\n            if (storeCertContext != IntPtr.Zero)\r\n            {\r\n                NativeMethods.CertFreeCertificateContext(storeCertContext);\r\n            }\r\n\r\n            if (certStore != IntPtr.Zero)\r\n            {\r\n                NativeMethods.CertCloseStore(certStore, 0);\r\n            }\r\n\r\n            if (cryptKey != IntPtr.Zero)\r\n            {\r\n                NativeMethods.CryptDestroyKey(cryptKey);\r\n            }\r\n\r\n            if (providerContext != IntPtr.Zero)\r\n            {\r\n                NativeMethods.CryptReleaseContext(providerContext, 0);\r\n                NativeMethods.CryptAcquireContextW(\r\n                    out providerContext,\r\n                    containerName,\r\n                    null,\r\n                    1, \/\/ PROV_RSA_FULL\r\n                    0x10); \/\/ CRYPT_DELETEKEYSET\r\n            }\r\n        }\r\n\r\n        return pfxData;\r\n    }\r\n\r\n    private static SystemTime ToSystemTime(DateTime dateTime)\r\n    {\r\n        long fileTime = dateTime.ToFileTime();\r\n        SystemTime systemTime;\r\n        Check(NativeMethods.FileTimeToSystemTime(ref fileTime, out systemTime));\r\n        return systemTime;\r\n    }\r\n\r\n    private static void Check(bool nativeCallSucceeded)\r\n    {\r\n        if (!nativeCallSucceeded)\r\n        {\r\n            int error = Marshal.GetHRForLastWin32Error();\r\n            Marshal.ThrowExceptionForHR(error);\r\n        }\r\n    }\r\n\r\n    [StructLayout(LayoutKind.Sequential)]\r\n    private struct SystemTime\r\n    {\r\n        public short Year;\r\n        public short Month;\r\n        public short DayOfWeek;\r\n        public short Day;\r\n        public short Hour;\r\n        public short Minute;\r\n        public short Second;\r\n        public short Milliseconds;\r\n    }\r\n\r\n    [StructLayout(LayoutKind.Sequential)]\r\n    private struct CryptoApiBlob\r\n    {\r\n        public int DataLength;\r\n        public IntPtr Data;\r\n\r\n        public CryptoApiBlob(int dataLength, IntPtr data)\r\n        {\r\n            this.DataLength = dataLength;\r\n            this.Data = data;\r\n        }\r\n    }\r\n\r\n    [StructLayout(LayoutKind.Sequential)]\r\n    private struct CryptKeyProviderInformation\r\n    {\r\n        [MarshalAs(UnmanagedType.LPWStr)] public string ContainerName;\r\n        [MarshalAs(UnmanagedType.LPWStr)] public string ProviderName;\r\n        public int ProviderType;\r\n        public int Flags;\r\n        public int ProviderParameterCount;\r\n        public IntPtr ProviderParameters; \/\/ PCRYPT_KEY_PROV_PARAM\r\n        public int KeySpec;\r\n    }\r\n\r\n    private static class NativeMethods\r\n    {\r\n        [DllImport(\"kernel32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool FileTimeToSystemTime(\r\n            [In] ref long fileTime,\r\n            out SystemTime systemTime);\r\n\r\n        [DllImport(\"AdvApi32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CryptAcquireContextW(\r\n            out IntPtr providerContext,\r\n            [MarshalAs(UnmanagedType.LPWStr)] string container,\r\n            [MarshalAs(UnmanagedType.LPWStr)] string provider,\r\n            int providerType,\r\n            int flags);\r\n\r\n        [DllImport(\"AdvApi32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CryptReleaseContext(\r\n            IntPtr providerContext,\r\n            int flags);\r\n\r\n        [DllImport(\"AdvApi32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CryptGenKey(\r\n            IntPtr providerContext,\r\n            int algorithmId,\r\n            int flags,\r\n            out IntPtr cryptKeyHandle);\r\n\r\n        [DllImport(\"AdvApi32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CryptDestroyKey(\r\n            IntPtr cryptKeyHandle);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CertStrToNameW(\r\n            int certificateEncodingType,\r\n            IntPtr x500,\r\n            int strType,\r\n            IntPtr reserved,\r\n            [MarshalAs(UnmanagedType.LPArray)] [Out] byte[] encoded,\r\n            ref int encodedLength,\r\n            out IntPtr errorString);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        public static extern IntPtr CertCreateSelfSignCertificate(\r\n            IntPtr providerHandle,\r\n            [In] ref CryptoApiBlob subjectIssuerBlob,\r\n            int flags,\r\n            [In] ref CryptKeyProviderInformation keyProviderInformation,\r\n            IntPtr signatureAlgorithm,\r\n            [In] ref SystemTime startTime,\r\n            [In] ref SystemTime endTime,\r\n            IntPtr extensions);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CertFreeCertificateContext(\r\n            IntPtr certificateContext);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        public static extern IntPtr CertOpenStore(\r\n            [MarshalAs(UnmanagedType.LPStr)] string storeProvider,\r\n            int messageAndCertificateEncodingType,\r\n            IntPtr cryptProvHandle,\r\n            int flags,\r\n            IntPtr parameters);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CertCloseStore(\r\n            IntPtr certificateStoreHandle,\r\n            int flags);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CertAddCertificateContextToStore(\r\n            IntPtr certificateStoreHandle,\r\n            IntPtr certificateContext,\r\n            int addDisposition,\r\n            out IntPtr storeContextPtr);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool CertSetCertificateContextProperty(\r\n            IntPtr certificateContext,\r\n            int propertyId,\r\n            int flags,\r\n            [In] ref CryptKeyProviderInformation data);\r\n\r\n        [DllImport(\"Crypt32.dll\", SetLastError = true, ExactSpelling = true)]\r\n        [return: MarshalAs(UnmanagedType.Bool)]\r\n        public static extern bool PFXExportCertStoreEx(\r\n            IntPtr certificateStoreHandle,\r\n            ref CryptoApiBlob pfxBlob,\r\n            IntPtr password,\r\n            IntPtr reserved,\r\n            int flags);\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7f51\u4e0a\u627e\u5230\u7684\u4e00\u4e2a&nbsp;dot net&nbsp;X509 \u8bc1\u4e66\u751f\u6210\u7c7b<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"brush:c#; toolbar: true; auto-links: true;\">using System;\r\nusing System.Runtime.InteropServices;\r\nusing System.Security.Cryptography.X509Certificates;\r\nusing SecureString = System.Security.SecureString;\r\nusing RuntimeHelpers = System.Runtime.CompilerServices.RuntimeHelpers;\r\n\r\ninternal class Certifica...<\/pre>\n<p> <a href=\"https:\/\/www.xiaobo.li\/notes\/archives\/418\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[279],"tags":[202],"class_list":["post-418","post","type-post","status-publish","format-standard","hentry","category-dotnet","tag-x509"],"_links":{"self":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/posts\/418","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/comments?post=418"}],"version-history":[{"count":0,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/posts\/418\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/media?parent=418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/categories?post=418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/tags?post=418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}