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);
private static CryptKeyProviderInformation NewProviderInformationFor(string containerName, int providerType, int keyexchange) { CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); kpi.ContainerName = containerName; kpi.ProviderType = providerType; kpi.KeySpec = keyexchange; kpi.Flags = NativeMethods.CRYPT_MACHINE_KEYSET; return(kpi); }
internal static byte[] CreateSelfSignCertificatePfx( string x500, DateTime startTime, DateTime endTime, SecureString password) { byte[] pfxData; if (x500 == null) { x500 = ""; } SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); string containerName = Guid.NewGuid().ToString(); GCHandle dataHandle = new GCHandle(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certContext = IntPtr.Zero; IntPtr certStore = IntPtr.Zero; IntPtr storeCertContext = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 8)); // CRYPT_NEWKEYSET Check(NativeMethods.CryptGenKey( providerContext, 1, // AT_KEYEXCHANGE 1 | (2048 << 16), // CRYPT_EXPORTABLE | 2048bit 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(x500, GCHandleType.Pinned); if (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_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 (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_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); } dataHandle.Free(); dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); CryptoApiBlob nameBlob = new CryptoApiBlob( nameData.Length, dataHandle.AddrOfPinnedObject()); CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); kpi.ContainerName = containerName; kpi.ProviderType = 1; // PROV_RSA_FULL kpi.KeySpec = 1; // AT_KEYEXCHANGE certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); certStore = NativeMethods.CertOpenStore( "Memory", // sz_CERT_STORE_PROV_MEMORY 0, IntPtr.Zero, 0x2000, // CERT_STORE_CREATE_NEW_FLAG IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, 1, // CERT_STORE_ADD_NEW out storeCertContext)); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 2, // CERT_KEY_PROV_INFO_PROP_ID 0, ref kpi); if (password != null) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } CryptoApiBlob pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY pfxData = new byte[pfxBlob.DataLength]; dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); pfxBlob.Data = dataHandle.AddrOfPinnedObject(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY dataHandle.Free(); } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (dataHandle.IsAllocated) { dataHandle.Free(); } if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 0x10); // CRYPT_DELETEKEYSET } } return(pfxData); }
public static byte[] CreateSelfSignedPfx(string subject, DateTime startTime, DateTime endTime, SecureString password) { if (subject == null) { throw new ArgumentNullException("Subject is null"); } var startSystemTime = ToSystemTime(startTime); var endSystemTime = ToSystemTime(endTime); var containerName = Guid.NewGuid().ToString(); var dataHandle = new GCHandle(); var providerContext = IntPtr.Zero; var cryptKey = IntPtr.Zero; var certContext = IntPtr.Zero; var certStore = IntPtr.Zero; var storeCertContext = IntPtr.Zero; var passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW(out providerContext, containerName, null, ProviderType.RsaAes, 8 /*CRYPT_NEWKEYSET*/)); Check(NativeMethods.CryptGenKey(providerContext, 1 /*AT_KEYEXCHANGE*/, 0x08000001 /*RSA2048BIT_KEY | CRYPT_EXPORTABLE*/, out cryptKey)); // errorStringPtr gets a pointer into the middle of the subject string, // so subject needs to be pinned until after we've copied the value // of errorStringPtr. dataHandle = GCHandle.Alloc(subject, GCHandleType.Pinned); var nameDataLength = 0; if (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING dataHandle.AddrOfPinnedObject(), 3, // CERT_X500_NAME_STR = 3 IntPtr.Zero, null, ref nameDataLength, out IntPtr errorStringPtr)) { var error = Marshal.PtrToStringUni(errorStringPtr); throw new ArgumentException(error); } var subjectData = new byte[nameDataLength]; if (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING dataHandle.AddrOfPinnedObject(), 3, // CERT_X500_NAME_STR = 3 IntPtr.Zero, subjectData, ref nameDataLength, out errorStringPtr)) { var error = Marshal.PtrToStringUni(errorStringPtr); throw new ArgumentException(error); } dataHandle.Free(); dataHandle = GCHandle.Alloc(subjectData, GCHandleType.Pinned); var subjectBlob = new CryptoApiBlob(subjectData.Length, dataHandle.AddrOfPinnedObject()); var kpi = new CryptKeyProviderInformation { ContainerName = containerName, ProviderType = ProviderType.RsaAes, KeySpec = 1 // AT_KEYEXCHANGE }; var ai = new CryptAlgorithmIdentifier { pszObjId = "1.2.840.113549.1.1.13", // SHA512RSA Parameters = IntPtr.Zero }; certContext = NativeMethods.CertCreateSelfSignCertificate(providerContext, ref subjectBlob, 0, ref kpi, ref ai, ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); certStore = NativeMethods.CertOpenStore("Memory" /*sz_CERT_STORE_PROV_MEMORY*/, 0, IntPtr.Zero, 0x2000 /*CERT_STORE_CREATE_NEW_FLAG*/, IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore(certStore, certContext, 1, /*CERT_STORE_ADD_NEW*/ out storeCertContext)); NativeMethods.CertSetCertificateContextProperty(storeCertContext, 2 /* CERT_KEY_PROV_INFO_PROP_ID */, 0, ref kpi); if (password != null) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } var pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx(certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY var pfxData = new byte[pfxBlob.DataLength]; dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); pfxBlob.Data = dataHandle.AddrOfPinnedObject(); Check(NativeMethods.PFXExportCertStoreEx(certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY dataHandle.Free(); return(pfxData); } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (dataHandle.IsAllocated) { dataHandle.Free(); } if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, ProviderType.RsaAes, 0x10); // CRYPT_DELETEKEYSET } } }
public static byte[] CreateSelfSignCertificatePfx( string x500, DateTime startTime, DateTime endTime, SecureString password) { byte[] pfxData; if (x500 == null) { x500 = ""; } SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); string containerName = Guid.NewGuid().ToString(); var dataHandle = new GCHandle(); var providerContext = IntPtr.Zero; var cryptKey = IntPtr.Zero; var certContext = IntPtr.Zero; var certStore = IntPtr.Zero; var storeCertContext = IntPtr.Zero; var passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 8)); // CRYPT_NEWKEYSET Check(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(x500, GCHandleType.Pinned); if (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_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 (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_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); } dataHandle.Free(); dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); var nameBlob = new CryptoApiBlob( nameData.Length, dataHandle.AddrOfPinnedObject()); var kpi = new CryptKeyProviderInformation(); kpi.ContainerName = containerName; kpi.ProviderType = 1; // PROV_RSA_FULL kpi.KeySpec = 1; // AT_KEYEXCHANGE certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); certStore = NativeMethods.CertOpenStore( "Memory", // sz_CERT_STORE_PROV_MEMORY 0, IntPtr.Zero, 0x2000, // CERT_STORE_CREATE_NEW_FLAG IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, 1, // CERT_STORE_ADD_NEW out storeCertContext)); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 2, // CERT_KEY_PROV_INFO_PROP_ID 0, ref kpi); if (password != null) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } var pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY pfxData = new byte[pfxBlob.DataLength]; dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); pfxBlob.Data = dataHandle.AddrOfPinnedObject(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY dataHandle.Free(); } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (dataHandle.IsAllocated) { dataHandle.Free(); } if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 0x10); // CRYPT_DELETEKEYSET } } return pfxData; }
private static byte[] CreateSelfSignCertificate(string distinguishedName, DateTime startTime, DateTime endTime, SecureString password) { if (distinguishedName == null) { distinguishedName = ""; } string containerName = Guid.NewGuid().ToString(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certContext = IntPtr.Zero; IntPtr certStore = IntPtr.Zero; IntPtr storeCertContext = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { providerContext = AcquireProviderContext(containerName, PROV_RSA_FULL, NativeMethods.CRYPT_NEWKEYSET + NativeMethods.CRYPT_MACHINE_KEYSET); cryptKey = GenerateKey(providerContext, AT_KEYEXCHANGE, NativeMethods.CRYPT_EXPORTABLE); CryptKeyProviderInformation kpi = NewProviderInformationFor(containerName, PROV_RSA_FULL, AT_KEYEXCHANGE); certContext = CreateSelfSignedCertificate(providerContext, distinguishedName, startTime, endTime, ref kpi); certStore = NativeMethods.CertOpenStore(sz_CERT_STORE_PROV_MEMORY, 0, IntPtr.Zero, CERT_STORE_CREATE_NEW_FLAG, IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore(certStore, certContext, CERT_STORE_ADD_NEW, out storeCertContext)); NativeMethods.CertSetCertificateContextProperty(storeCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, ref kpi); return(ExportCertificate(certStore, password)); } finally { if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW(out providerContext, containerName, null, PROV_RSA_FULL, NativeMethods.CRYPT_DELETEKEYSET); } } }
private static IntPtr CreateSelfSignedCertificate(IntPtr providerContext, string distinguishedName, DateTime startTime, DateTime endTime, ref CryptKeyProviderInformation kpi) { SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); byte[] nameData = GetNameData(distinguishedName); GCHandle dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); try { CryptoApiBlob nameBlob = new CryptoApiBlob(nameData.Length, dataHandle.AddrOfPinnedObject()); IntPtr certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); return(certContext); } finally { if (dataHandle.IsAllocated) { dataHandle.Free(); } } }
/// <summary> /// 自己証明書作成のメソッド本体 /// rawData が nullで、自己証明書を新規作成 /// rawDate を指定すると、既存の自己証明書の更新 /// </summary> /// <param name="rawData">更新時の証明書バイナリーデータ</param> /// <param name="x500">組織名(CN="XXXXX")</param> /// <param name="startTime">開始日</param> /// <param name="endTime">終了日</param> /// <param name="insecurePassword">セキュア パスワード</param> /// <returns>証明書データ</returns> public static byte[] CreateSelfSignCertificatePfx( byte[] rawData, string x500, DateTime startTime, DateTime endTime, SecureString password) { byte[] pfxData; if (x500 == null) { x500 = ""; } SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); string containerName = Guid.NewGuid().ToString(); GCHandle dataHandle = new GCHandle(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certContext = IntPtr.Zero; IntPtr certStore = IntPtr.Zero; IntPtr storeCertContext = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; IntPtr callerFreeProvOrNCryptKey = IntPtr.Zero; // コード本体を制約された実行領域 (CER) として指定します。 RuntimeHelpers.PrepareConstrainedRegions(); try { if (password != null) { // アンマネージ COM タスク アロケーターから割り当てられたメモリ ブロックに、マネージ SecureString オブジェクトの内容をコピーします passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } if (rawData == null) { // 自己証明書の新規作成用にハンドル(HCRYPTPROV) を取得します(providerContext) // cryptographic service provider(CSP)内で キーコンテナに対するハンドル(HCRYPTPROV)を取得します Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, //MS_ENHANCED_PROV, null, PROV_RSA_FULL, CRYPT_NEWKEYSET)); // ランダムな暗号化用のセッションキーか public/private のキーペアを生成します(HCRYPTKEY) Check(NativeMethods.CryptGenKey( providerContext, AT_KEYEXCHANGE, //RSA2048BIT_KEY | CRYPT_EXPORTABLE, // 2048ビットへ変更、標準は1024ビット RSA1024BIT_KEY | CRYPT_EXPORTABLE, // 2048ビットへ変更、標準は1024ビット out cryptKey)); } else { // 自己証明書の更新用にハンドル(HCRYPTPROV) を取得します(providerContext) // 証明書データ(PFX Blob)をインポートします CryptoApiBlob certBlob = new CryptoApiBlob(); certBlob.DataLength = rawData.Length; // 証明書データをPFX Blobへコピーします certBlob.Data = Marshal.AllocHGlobal(certBlob.DataLength); Marshal.Copy(rawData, 0, certBlob.Data, rawData.Length); Check(NativeMethods.PFXIsPFXBlob(ref certBlob)); // PFX Blobが正常かどうかを確認します certStore = NativeMethods.PFXImportCertStore( ref certBlob, passwordPtr, CRYPT_EXPORTABLE | CRYPT_USER_KEYSET); Check(certStore != IntPtr.Zero); // 証明書を取得します certContext = NativeMethods.CertEnumCertificatesInStore( certStore, IntPtr.Zero); Check(certContext != IntPtr.Zero); // 証明書の private キーを含めて、キーコンテナに対するハンドル(HCRYPTPROV)を取得します IntPtr keySpec = IntPtr.Zero; Check(NativeMethods.CryptAcquireCertificatePrivateKey( certContext, 0, IntPtr.Zero, out providerContext, out keySpec, out callerFreeProvOrNCryptKey)); // 不要になったハンドルを解放 Check(NativeMethods.CertCloseStore(certStore, 0)); Check(NativeMethods.CertFreeCertificateContext(certContext)); Marshal.FreeHGlobal(certBlob.Data); if (keySpec != IntPtr.Zero) Marshal.FreeHGlobal(keySpec); } IntPtr errorStringPtr; int nameDataLength = 0; byte[] nameData; // errorStringPtr は、 x500 文字列に対するポインターを取得します。 // この理由で、値を errorStringPtr へコピーするまではピン止めする必要があります dataHandle = GCHandle.Alloc(x500, GCHandleType.Pinned); // X.500 文字列を エンコードされた証明書名へ変換します if (!NativeMethods.CertStrToNameW( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, dataHandle.AddrOfPinnedObject(), CERT_X500_NAME_STR, IntPtr.Zero, null, ref nameDataLength, out errorStringPtr)) { string error = Marshal.PtrToStringUni(errorStringPtr); throw new ArgumentException(error); } nameData = new byte[nameDataLength]; if (!NativeMethods.CertStrToNameW( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, dataHandle.AddrOfPinnedObject(), CERT_X500_NAME_STR, IntPtr.Zero, nameData, ref nameDataLength, out errorStringPtr)) { string error = Marshal.PtrToStringUni(errorStringPtr); throw new ArgumentException(error); } dataHandle.Free(); dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); CryptoApiBlob nameBlob = new CryptoApiBlob( nameData.Length, dataHandle.AddrOfPinnedObject()); // 暗号化キー情報 CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); kpi.ContainerName = containerName; kpi.ProviderType = PROV_RSA_FULL; kpi.KeySpec = AT_KEYEXCHANGE; // 自己証明書を作成し、CERT_CONTEXT 構造体のポインター(証明書)を返します。 // HCRYPTPROV か、NCryptOpenKey を使用した NCRYPT_KEY_HANDLE certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); // 指定した CSP を使って証明書ストアを開きます certStore = NativeMethods.CertOpenStore( sz_CERT_STORE_PROV_MEMORY, 0, IntPtr.Zero, CERT_STORE_CREATE_NEW_FLAG, IntPtr.Zero); Check(certStore != IntPtr.Zero); // 証明書コンテキストを証明書ストアへ追加します Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, CERT_STORE_ADD_NEW, out storeCertContext)); // 指定した証明書コンテキストへ拡張プロパティを設定します // この場合は暗号化キーです NativeMethods.CertSetCertificateContextProperty( storeCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, ref kpi); CryptoApiBlob pfxBlob = new CryptoApiBlob(); // 証明書をエクスポートします。参照された証明書ストアから関連付けられた private キーは、存在する場合にです // 1度目のエクスポートで、pfxBlob.DataLengthを取得します。 // 2度目のエクスポートは、pfxBlob.Data を pfxDataにポインター経由で取得します。 Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)); pfxData = new byte[pfxBlob.DataLength]; dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); pfxBlob.Data = dataHandle.AddrOfPinnedObject(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)); dataHandle.Free(); } catch (Exception e) { throw e; } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (dataHandle.IsAllocated) { dataHandle.Free(); } if (certContext != IntPtr.Zero) { // 証明書コンテキストを解放します NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { // 証明書ストアコンテキストを解放します NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { // 証明書ストアをクローズします NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { // 暗号化キーを解放します NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { // cryptographic service provider(CSP) を解放します NativeMethods.CryptReleaseContext(providerContext, 0); // 暗号化キーをコンテナから削除します NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, PROV_RSA_FULL, CRYPT_DELETEKEYSET); } if (callerFreeProvOrNCryptKey != IntPtr.Zero) Marshal.FreeHGlobal(callerFreeProvOrNCryptKey); } return pfxData; }
public static extern Boolean CertSetCertificateContextProperty( IntPtr certificateContext, Int32 propertyId, Int32 flags, [In] ref CryptKeyProviderInformation data);
public static X509Certificate2 GenerateSelfSignedCertificate(String name = "", DateTime?startTime = null, DateTime?endTime = null) { if (startTime == null || (DateTime)startTime < DateTime.FromFileTimeUtc(0)) { startTime = DateTime.FromFileTimeUtc(0); } var startSystemTime = ((DateTime)startTime).ToSystemTime(); if (endTime == null) { endTime = DateTime.MaxValue; } var endSystemTime = ((DateTime)endTime).ToSystemTime(); string containerName = Guid.NewGuid().ToString(); GCHandle dataHandle = new GCHandle(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certificateContext = IntPtr.Zero; IntPtr algorithmPointer = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { MarshalHelper.CheckReturnValue(CryptAcquireContextW(out providerContext, containerName, null, 0x18, 0x8)); MarshalHelper.CheckReturnValue(CryptGenKey(providerContext, 0x6610, 0x4000001, out cryptKey)); IntPtr errorStringPtr; int nameDataLength = 0; byte[] nameData; dataHandle = GCHandle.Alloc(name, GCHandleType.Pinned); if (!CertStrToNameW(0x10001, dataHandle.AddrOfPinnedObject(), 3, IntPtr.Zero, null, ref nameDataLength, out errorStringPtr)) { string error = Marshal.PtrToStringUni(errorStringPtr); throw new ArgumentException(error); } nameData = new byte[nameDataLength]; if (!CertStrToNameW(0x10001, dataHandle.AddrOfPinnedObject(), 3, IntPtr.Zero, nameData, ref nameDataLength, out errorStringPtr)) { string error = Marshal.PtrToStringUni(errorStringPtr); throw new ArgumentException(error); } dataHandle.Free(); dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); CryptoApiBlob nameBlob = new CryptoApiBlob { cbData = (uint)nameData.Length, pbData = dataHandle.AddrOfPinnedObject() }; dataHandle.Free(); CryptKeyProviderInformation keyProvider = new CryptKeyProviderInformation { pwszContainerName = containerName, dwProvType = 0x18, dwKeySpec = 1 }; CryptAlgorithmIdentifier algorithm = new CryptAlgorithmIdentifier { pszObjId = "1.2.840.113549.1.1.13", Parameters = new CryptoApiBlob() }; algorithmPointer = Marshal.AllocHGlobal(Marshal.SizeOf(algorithm)); Marshal.StructureToPtr(algorithm, algorithmPointer, false); certificateContext = CertCreateSelfSignCertificate(providerContext, ref nameBlob, 0, ref keyProvider, algorithmPointer, ref startSystemTime, ref endSystemTime, IntPtr.Zero); MarshalHelper.CheckReturnValue(certificateContext != IntPtr.Zero); return(new X509Certificate2(certificateContext)); } finally { if (dataHandle.IsAllocated) { dataHandle.Free(); } if (certificateContext != IntPtr.Zero) { CertFreeCertificateContext(certificateContext); } if (cryptKey != IntPtr.Zero) { CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { CryptReleaseContext(providerContext, 0); } if (algorithmPointer != IntPtr.Zero) { Marshal.DestroyStructure(algorithmPointer, typeof(CryptAlgorithmIdentifier)); Marshal.FreeHGlobal(algorithmPointer); } } }
/// <summary> /// Creates the self sign certificate PFX. /// </summary> /// <param name="x500">The X500.</param> /// <param name="startTime">The start time.</param> /// <param name="endTime">The end time.</param> /// <param name="password">The password.</param> /// <returns></returns> /// <exception cref="ArgumentException"> /// </exception> public static byte[] CreateSelfSignCertificatePfx( string x500, DateTime startTime, DateTime endTime, SecureString password) { byte[] pfxData; if (x500 == null) { x500 = ""; } #if NETCOREAPP3_1 SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); sanBuilder.AddIpAddress(IPAddress.Loopback); sanBuilder.AddIpAddress(IPAddress.IPv6Loopback); sanBuilder.AddDnsName("localhost"); sanBuilder.AddDnsName(Environment.MachineName); X500DistinguishedName distinguishedName = new X500DistinguishedName(x500); using (RSA rsa = RSA.Create(2048)) { var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add( new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false)); request.CertificateExtensions.Add( new X509EnhancedKeyUsageExtension( new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false)); request.CertificateExtensions.Add(sanBuilder.Build()); var certificate = request.CreateSelfSigned(new DateTimeOffset(startTime), new DateTimeOffset(endTime)); certificate.FriendlyName = "Generated Certificate"; pfxData = certificate.Export(X509ContentType.Pfx, password); } #else SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); string containerName = Guid.NewGuid().ToString(); GCHandle dataHandle = new GCHandle(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certContext = IntPtr.Zero; IntPtr certStore = IntPtr.Zero; IntPtr storeCertContext = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL, 2048 bit type: 1 | (2048<<16) 8)); // CRYPT_NEWKEYSET Check(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(x500, GCHandleType.Pinned); if (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_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 (!NativeMethods.CertStrToNameW( 0x00010001, // X509_ASN_ENCODING | PKCS_7_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); } dataHandle.Free(); dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); CryptoApiBlob nameBlob = new CryptoApiBlob( nameData.Length, dataHandle.AddrOfPinnedObject()); CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); kpi.ContainerName = containerName; kpi.ProviderType = 1; // PROV_RSA_FULL kpi.KeySpec = 1; // AT_KEYEXCHANGE certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); certStore = NativeMethods.CertOpenStore( "Memory", // sz_CERT_STORE_PROV_MEMORY 0, IntPtr.Zero, 0x2000, // CERT_STORE_CREATE_NEW_FLAG IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, 1, // CERT_STORE_ADD_NEW out storeCertContext)); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 2, // CERT_KEY_PROV_INFO_PROP_ID 0, ref kpi); if (password != null) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } CryptoApiBlob pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY pfxData = new byte[pfxBlob.DataLength]; dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); pfxBlob.Data = dataHandle.AddrOfPinnedObject(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY dataHandle.Free(); } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (dataHandle.IsAllocated) { dataHandle.Free(); } if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 0x10); // CRYPT_DELETEKEYSET } } #endif return(pfxData); }
/// <summary> /// Create a self-signed certificate. /// </summary> internal static byte[] CreateSelfSignedCert( X500DistinguishedName subjectName, string friendlyName, DateTime startTime, DateTime endTime, SecureString password) { byte[] pfxData; SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); string containerName = Guid.NewGuid().ToString(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certContext = IntPtr.Zero; IntPtr certStore = IntPtr.Zero; IntPtr storeCertContext = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 8)); // CRYPT_NEWKEYSET Check(NativeMethods.CryptGenKey( providerContext, 1, // AT_KEYEXCHANGE 1 | (KeySize << 16), // CRYPT_EXPORTABLE out cryptKey)); unsafe { fixed(char *pContainerName = containerName.ToCharArray()) { CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); kpi.ContainerName = (IntPtr)pContainerName; kpi.ProviderType = 1; // PROV_RSA_FULL kpi.KeySpec = 1; // AT_KEYEXCHANGE fixed(byte *pSubjectName = &subjectName.RawData[0]) { CryptoApiBlob nameBlob = new CryptoApiBlob( subjectName.RawData.Length, (IntPtr)pSubjectName); certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); } certStore = NativeMethods.CertOpenStore( "Memory", // sz_CERT_STORE_PROV_MEMORY 0, IntPtr.Zero, 0x2000, // CERT_STORE_CREATE_NEW_FLAG IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, 1, // CERT_STORE_ADD_NEW out storeCertContext)); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 2, // CERT_KEY_PROV_INFO_PROP_ID 0, (IntPtr)(&kpi)); } fixed(char *pFriendlyName = friendlyName.ToCharArray()) { var blob = new CryptoApiBlob( friendlyName.Length * sizeof(char), (IntPtr)pFriendlyName); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 11, // CERT_FRIENDLY_NAME_PROP_ID 0, (IntPtr)(&blob)); } if (password != null && password.Length > 0) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } CryptoApiBlob pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY pfxData = new byte[pfxBlob.DataLength]; fixed(byte *pData = pfxData) { pfxBlob.Data = (IntPtr)pData; Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY } } } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 0x10); // CRYPT_DELETEKEYSET } } return(pfxData); }
/// <summary>建立自签名证书</summary> /// <param name="distName"></param> /// <param name="startTime"></param> /// <param name="endTime"></param> /// <param name="password"></param> /// <returns></returns> public static Byte[] CreateSelfSignCertificatePfx(X500DistinguishedName distName, DateTime startTime, DateTime endTime, SecureString password) { var containerName = Guid.NewGuid().ToString(); var dataHandle = new GCHandle(); var providerContext = IntPtr.Zero; var cryptKey = IntPtr.Zero; var certContext = IntPtr.Zero; var certStore = IntPtr.Zero; var storeCertContext = IntPtr.Zero; var passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 8)); // CRYPT_NEWKEYSET Check(NativeMethods.CryptGenKey( providerContext, 1, // AT_KEYEXCHANGE 1, // CRYPT_EXPORTABLE out cryptKey)); var nameData = distName.RawData; dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); var nameBlob = new CryptoApiBlob(nameData.Length, dataHandle.AddrOfPinnedObject()); var kpi = new CryptKeyProviderInformation(); kpi.ContainerName = containerName; kpi.ProviderType = 1; // PROV_RSA_FULL kpi.KeySpec = 1; // AT_KEYEXCHANGE var startSystemTime = ToSystemTime(startTime); var endSystemTime = ToSystemTime(endTime); certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); certStore = NativeMethods.CertOpenStore( "Memory", // sz_CERT_STORE_PROV_MEMORY 0, IntPtr.Zero, 0x2000, // CERT_STORE_CREATE_NEW_FLAG IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, 1, // CERT_STORE_ADD_NEW out storeCertContext)); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 2, // CERT_KEY_PROV_INFO_PROP_ID 0, ref kpi); if (password != null) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } var pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY var pfxData = new Byte[pfxBlob.DataLength]; dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); pfxBlob.Data = dataHandle.AddrOfPinnedObject(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY dataHandle.Free(); return pfxData; } finally { if (passwordPtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); if (dataHandle.IsAllocated) dataHandle.Free(); if (certContext != IntPtr.Zero) NativeMethods.CertFreeCertificateContext(certContext); if (storeCertContext != IntPtr.Zero) NativeMethods.CertFreeCertificateContext(storeCertContext); if (certStore != IntPtr.Zero) NativeMethods.CertCloseStore(certStore, 0); if (cryptKey != IntPtr.Zero) NativeMethods.CryptDestroyKey(cryptKey); if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 0x10); // CRYPT_DELETEKEYSET } } }
private static CryptKeyProviderInformation NewProviderInformationFor(string containerName, int providerType, int keyexchange) { CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); kpi.ContainerName = containerName; kpi.ProviderType = providerType; kpi.KeySpec = keyexchange; kpi.Flags = NativeMethods.CRYPT_MACHINE_KEYSET; return kpi; }
private static IntPtr CreateSelfSignedCertificate(IntPtr providerContext, string distinguishedName, DateTime startTime, DateTime endTime, ref CryptKeyProviderInformation kpi) { SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); byte[] nameData = GetNameData(distinguishedName); GCHandle dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); try { CryptoApiBlob nameBlob = new CryptoApiBlob(nameData.Length, dataHandle.AddrOfPinnedObject()); IntPtr certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); return certContext; } finally { if (dataHandle.IsAllocated) { dataHandle.Free(); } } }
/// <summary>建立自签名证书</summary> /// <param name="distName"></param> /// <param name="startTime"></param> /// <param name="endTime"></param> /// <param name="password"></param> /// <returns></returns> public static Byte[] CreateSelfSignCertificatePfx(X500DistinguishedName distName, DateTime startTime, DateTime endTime, SecureString password) { var containerName = Guid.NewGuid().ToString(); var dataHandle = new GCHandle(); var providerContext = IntPtr.Zero; var cryptKey = IntPtr.Zero; var certContext = IntPtr.Zero; var certStore = IntPtr.Zero; var storeCertContext = IntPtr.Zero; var passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 8)); // CRYPT_NEWKEYSET Check(NativeMethods.CryptGenKey( providerContext, 1, // AT_KEYEXCHANGE 1, // CRYPT_EXPORTABLE out cryptKey)); var nameData = distName.RawData; dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); var nameBlob = new CryptoApiBlob(nameData.Length, dataHandle.AddrOfPinnedObject()); var kpi = new CryptKeyProviderInformation { ContainerName = containerName, ProviderType = 1, // PROV_RSA_FULL KeySpec = 1 // AT_KEYEXCHANGE }; var startSystemTime = ToSystemTime(startTime); var endSystemTime = ToSystemTime(endTime); certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); dataHandle.Free(); certStore = NativeMethods.CertOpenStore( "Memory", // sz_CERT_STORE_PROV_MEMORY 0, IntPtr.Zero, 0x2000, // CERT_STORE_CREATE_NEW_FLAG IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, 1, // CERT_STORE_ADD_NEW out storeCertContext)); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 2, // CERT_KEY_PROV_INFO_PROP_ID 0, ref kpi); if (password != null) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } var pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY var pfxData = new Byte[pfxBlob.DataLength]; dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); pfxBlob.Data = dataHandle.AddrOfPinnedObject(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY dataHandle.Free(); return(pfxData); } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (dataHandle.IsAllocated) { dataHandle.Free(); } if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 0x10); // CRYPT_DELETEKEYSET } } }
public static extern bool CertSetCertificateContextProperty( IntPtr certificateContext, int propertyId, int flags, [In] ref CryptKeyProviderInformation data);
/// <summary> /// Create a self-signed certificate. /// </summary> internal static byte[] CreateSelfSignedCert( X500DistinguishedName subjectName, string friendlyName, DateTime startTime, DateTime endTime, SecureString password) { byte[] pfxData; SystemTime startSystemTime = ToSystemTime(startTime); SystemTime endSystemTime = ToSystemTime(endTime); string containerName = Guid.NewGuid().ToString(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certContext = IntPtr.Zero; IntPtr certStore = IntPtr.Zero; IntPtr storeCertContext = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { Check(NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 8)); // CRYPT_NEWKEYSET Check(NativeMethods.CryptGenKey( providerContext, 1, // AT_KEYEXCHANGE 1 | (KeySize << 16), // CRYPT_EXPORTABLE out cryptKey)); unsafe { fixed (char* pContainerName = containerName.ToCharArray()) { CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); kpi.ContainerName = (IntPtr)pContainerName; kpi.ProviderType = 1; // PROV_RSA_FULL kpi.KeySpec = 1; // AT_KEYEXCHANGE fixed (byte* pSubjectName = &subjectName.RawData[0]) { CryptoApiBlob nameBlob = new CryptoApiBlob( subjectName.RawData.Length, (IntPtr)pSubjectName); certContext = NativeMethods.CertCreateSelfSignCertificate( providerContext, ref nameBlob, 0, ref kpi, IntPtr.Zero, // default = SHA1RSA ref startSystemTime, ref endSystemTime, IntPtr.Zero); Check(certContext != IntPtr.Zero); } certStore = NativeMethods.CertOpenStore( "Memory", // sz_CERT_STORE_PROV_MEMORY 0, IntPtr.Zero, 0x2000, // CERT_STORE_CREATE_NEW_FLAG IntPtr.Zero); Check(certStore != IntPtr.Zero); Check(NativeMethods.CertAddCertificateContextToStore( certStore, certContext, 1, // CERT_STORE_ADD_NEW out storeCertContext)); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 2, // CERT_KEY_PROV_INFO_PROP_ID 0, (IntPtr)(&kpi)); } fixed (char* pFriendlyName = friendlyName.ToCharArray()) { var blob = new CryptoApiBlob( friendlyName.Length * sizeof(char), (IntPtr)pFriendlyName); NativeMethods.CertSetCertificateContextProperty( storeCertContext, 11, // CERT_FRIENDLY_NAME_PROP_ID 0, (IntPtr)(&blob)); } if (password != null && password.Length > 0) { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } CryptoApiBlob pfxBlob = new CryptoApiBlob(); Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY pfxData = new byte[pfxBlob.DataLength]; fixed (byte* pData = pfxData) { pfxBlob.Data = (IntPtr)pData; Check(NativeMethods.PFXExportCertStoreEx( certStore, ref pfxBlob, passwordPtr, IntPtr.Zero, 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY } } } finally { if (passwordPtr != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } if (certContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(certContext); } if (storeCertContext != IntPtr.Zero) { NativeMethods.CertFreeCertificateContext(storeCertContext); } if (certStore != IntPtr.Zero) { NativeMethods.CertCloseStore(certStore, 0); } if (cryptKey != IntPtr.Zero) { NativeMethods.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { NativeMethods.CryptReleaseContext(providerContext, 0); NativeMethods.CryptAcquireContextW( out providerContext, containerName, null, 1, // PROV_RSA_FULL 0x10); // CRYPT_DELETEKEYSET } } return pfxData; }