public static extern IntPtr CertCreateSelfSignCertificate( IntPtr providerHandle, [In] ref CryptoApiBlob subjectIssuerBlob, int flags, [In] ref CryptKeyProviderInformation keyProviderInformation, [In] ref CryptAlgorithmIdentifier signatureAlgorithm, [In] ref SystemTime startTime, [In] ref SystemTime endTime, IntPtr extensions);
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); } } }
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 X509Certificate2 GenerateSelfSignedCertificate(string issuerDN, DateTime?startTime = null, DateTime?endTime = null) { if (issuerDN == null) { issuerDN = String.Empty; } var startSystemTime = default(SystemTime); if (startTime == null || (DateTime)startTime < DateTime.FromFileTimeUtc(0)) { startTime = DateTime.FromFileTimeUtc(0); startSystemTime = SystemTime.Create((DateTime)startTime); } if (endTime == null) { endTime = DateTime.MaxValue; } var endSystemTime = SystemTime.Create((DateTime)endTime); string containerName = Guid.NewGuid().ToString(); IntPtr providerContext = IntPtr.Zero; IntPtr cryptKey = IntPtr.Zero; IntPtr certificateContext = IntPtr.Zero; IntPtr algorithmPointer = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { providerContext = Externs.CryptAcquireContextW(containerName, null, 1, 0x8); cryptKey = Externs.CryptGenKey(providerContext, 1, 0x8000001); CryptoApiBlob nameBlob = CryptoApiBlob.Create(issuerDN); CryptKeyProvInfo keyProvider = new CryptKeyProvInfo { pwszContainerName = containerName, dwProvType = 1, 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 = Externs.CertCreateSelfSignCertificate(providerContext, nameBlob, 0, keyProvider, algorithmPointer, startSystemTime, endSystemTime, IntPtr.Zero); return(new X509Certificate2(certificateContext)); } finally { if (certificateContext != IntPtr.Zero) { Externs.CertFreeCertificateContext(certificateContext); } if (cryptKey != IntPtr.Zero) { Externs.CryptDestroyKey(cryptKey); } if (providerContext != IntPtr.Zero) { Externs.CryptReleaseContext(providerContext, 0); } if (algorithmPointer != IntPtr.Zero) { Marshal.DestroyStructure(algorithmPointer, typeof(CryptAlgorithmIdentifier)); Marshal.FreeHGlobal(algorithmPointer); } } }