首页 > 编程 > C# > 正文

C#创建自签名认证文件的方法

2019-10-29 21:41:01
字体:大 中 小
来源:转载
供稿:网友

这篇文章主要介绍了C#创建自签名认证文件的方法,实例分析了C#自签名认证文件的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下

本文实例讲述了C#创建自签名认证文件的方法。分享给大家供大家参考。具体如下:

 

 
  1. using System; 
  2. using System.Runtime.InteropServices; 
  3. using System.Security.Cryptography.X509Certificates; 
  4. using SecureString = System.Security.SecureString; 
  5. using RuntimeHelpers = System.Runtime.CompilerServices.RuntimeHelpers; 
  6. internal class Certificate 
  7. { 
  8. public static byte[] CreateSelfSignCertificatePfx( 
  9. string x500, 
  10. DateTime startTime, 
  11. DateTime endTime) 
  12. { 
  13. byte[] pfxData = CreateSelfSignCertificatePfx( 
  14. x500, 
  15. startTime, 
  16. endTime, 
  17. (SecureString)null); 
  18. return pfxData; 
  19. } 
  20. public static byte[] CreateSelfSignCertificatePfx( 
  21. string x500, 
  22. DateTime startTime, 
  23. DateTime endTime, 
  24. string insecurePassword) 
  25. { 
  26. byte[] pfxData; 
  27. SecureString password = null; 
  28. try 
  29. { 
  30. if (!string.IsNullOrEmpty(insecurePassword)) 
  31. { 
  32. password = new SecureString(); 
  33. foreach (char ch in insecurePassword) 
  34. { 
  35. password.AppendChar(ch); 
  36. } 
  37. password.MakeReadOnly(); 
  38. } 
  39. pfxData = CreateSelfSignCertificatePfx( 
  40. x500, 
  41. startTime, 
  42. endTime, 
  43. password); 
  44. } 
  45. finally 
  46. { 
  47. if (password != null) 
  48. { 
  49. password.Dispose(); 
  50. } 
  51. } 
  52. return pfxData; 
  53. } 
  54. public static byte[] CreateSelfSignCertificatePfx( 
  55. string x500, 
  56. DateTime startTime, 
  57. DateTime endTime, 
  58. SecureString password) 
  59. { 
  60. byte[] pfxData; 
  61. if (x500 == null) 
  62. { 
  63. x500 = ""; 
  64. } 
  65. SystemTime startSystemTime = ToSystemTime(startTime); 
  66. SystemTime endSystemTime = ToSystemTime(endTime); 
  67. string containerName = Guid.NewGuid().ToString(); 
  68. GCHandle dataHandle = new GCHandle(); 
  69. IntPtr providerContext = IntPtr.Zero; 
  70. IntPtr cryptKey = IntPtr.Zero; 
  71. IntPtr certContext = IntPtr.Zero; 
  72. IntPtr certStore = IntPtr.Zero; 
  73. IntPtr storeCertContext = IntPtr.Zero; 
  74. IntPtr passwordPtr = IntPtr.Zero; 
  75. RuntimeHelpers.PrepareConstrainedRegions(); 
  76. try 
  77. { 
  78. Check(NativeMethods.CryptAcquireContextW( 
  79. out providerContext, 
  80. containerName, 
  81. null, 
  82. 1, // PROV_RSA_FULL 
  83. 8)); // CRYPT_NEWKEYSET 
  84. Check(NativeMethods.CryptGenKey( 
  85. providerContext, 
  86. 1, // AT_KEYEXCHANGE 
  87. 1, // CRYPT_EXPORTABLE 
  88. out cryptKey)); 
  89. IntPtr errorStringPtr; 
  90. int nameDataLength = 0; 
  91. byte[] nameData; 
  92. // errorStringPtr gets a pointer into the middle of the x500 string, 
  93. // so x500 needs to be pinned until after we've copied the value 
  94. // of errorStringPtr. 
  95. dataHandle = GCHandle.Alloc(x500, GCHandleType.Pinned); 
  96. if (!NativeMethods.CertStrToNameW( 
  97. 0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING 
  98. dataHandle.AddrOfPinnedObject(), 
  99. 3, // CERT_X500_NAME_STR = 3 
  100. IntPtr.Zero, 
  101. null, 
  102. ref nameDataLength, 
  103. out errorStringPtr)) 
  104. { 
  105. string error = Marshal.PtrToStringUni(errorStringPtr); 
  106. throw new ArgumentException(error); 
  107. } 
  108. nameData = new byte[nameDataLength]; 
  109. if (!NativeMethods.CertStrToNameW( 
  110. 0x00010001, // X509_ASN_ENCODING | PKCS_7_ASN_ENCODING 
  111. dataHandle.AddrOfPinnedObject(), 
  112. 3, // CERT_X500_NAME_STR = 3 
  113. IntPtr.Zero, 
  114. nameData, 
  115. ref nameDataLength, 
  116. out errorStringPtr)) 
  117. { 
  118. string error = Marshal.PtrToStringUni(errorStringPtr); 
  119. throw new ArgumentException(error); 
  120. } 
  121. dataHandle.Free(); 
  122. dataHandle = GCHandle.Alloc(nameData, GCHandleType.Pinned); 
  123. CryptoApiBlob nameBlob = new CryptoApiBlob( 
  124. nameData.Length, 
  125. dataHandle.AddrOfPinnedObject()); 
  126. CryptKeyProviderInformation kpi = new CryptKeyProviderInformation(); 
  127. kpi.ContainerName = containerName; 
  128. kpi.ProviderType = 1; // PROV_RSA_FULL 
  129. kpi.KeySpec = 1; // AT_KEYEXCHANGE 
  130. certContext = NativeMethods.CertCreateSelfSignCertificate( 
  131. providerContext, 
  132. ref nameBlob, 
  133. 0, 
  134. ref kpi, 
  135. IntPtr.Zero, // default = SHA1RSA 
  136. ref startSystemTime, 
  137. ref endSystemTime, 
  138. IntPtr.Zero); 
  139. Check(certContext != IntPtr.Zero); 
  140. dataHandle.Free(); 
  141. certStore = NativeMethods.CertOpenStore( 
  142. "Memory", // sz_CERT_STORE_PROV_MEMORY 
  143. 0, 
  144. IntPtr.Zero, 
  145. 0x2000, // CERT_STORE_CREATE_NEW_FLAG 
  146. IntPtr.Zero); 
  147. Check(certStore != IntPtr.Zero); 
  148. Check(NativeMethods.CertAddCertificateContextToStore( 
  149. certStore, 
  150. certContext, 
  151. 1, // CERT_STORE_ADD_NEW 
  152. out storeCertContext)); 
  153. NativeMethods.CertSetCertificateContextProperty( 
  154. storeCertContext, 
  155. 2, // CERT_KEY_PROV_INFO_PROP_ID 
  156. 0, 
  157. ref kpi); 
  158. if (password != null) 
  159. { 
  160. passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); 
  161. } 
  162. CryptoApiBlob pfxBlob = new CryptoApiBlob(); 
  163. Check(NativeMethods.PFXExportCertStoreEx( 
  164. certStore, 
  165. ref pfxBlob, 
  166. passwordPtr, 
  167. IntPtr.Zero, 
  168. 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY 
  169. pfxData = new byte[pfxBlob.DataLength]; 
  170. dataHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned); 
  171. pfxBlob.Data = dataHandle.AddrOfPinnedObject(); 
  172. Check(NativeMethods.PFXExportCertStoreEx( 
  173. certStore, 
  174. ref pfxBlob, 
  175. passwordPtr, 
  176. IntPtr.Zero, 
  177. 7)); // EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY 
  178. dataHandle.Free(); 
  179. } 
  180. finally 
  181. { 
  182. if (passwordPtr != IntPtr.Zero) 
  183. { 
  184. Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); 
  185. } 
  186. if (dataHandle.IsAllocated) 
  187. { 
  188. dataHandle.Free(); 
  189. } 
  190. if (certContext != IntPtr.Zero) 
  191. { 
  192. NativeMethods.CertFreeCertificateContext(certContext); 
  193. } 
  194. if (storeCertContext != IntPtr.Zero) 
  195. { 
  196. NativeMethods.CertFreeCertificateContext(storeCertContext); 
  197. } 
  198. if (certStore != IntPtr.Zero) 
  199. { 
  200. NativeMethods.CertCloseStore(certStore, 0); 
  201. } 
  202. if (cryptKey != IntPtr.Zero) 
  203. { 
  204. NativeMethods.CryptDestroyKey(cryptKey); 
  205. } 
  206. if (providerContext != IntPtr.Zero) 
  207. { 
  208. NativeMethods.CryptReleaseContext(providerContext, 0); 
  209. NativeMethods.CryptAcquireContextW( 
  210. out providerContext, 
  211. containerName, 
  212. null, 
  213. 1, // PROV_RSA_FULL 
  214. 0x10); // CRYPT_DELETEKEYSET 
  215. } 
  216. } 
  217. return pfxData; 
  218. } 
  219. private static SystemTime ToSystemTime(DateTime dateTime) 
  220. { 
  221. long fileTime = dateTime.ToFileTime(); 
  222. SystemTime systemTime; 
  223. Check(NativeMethods.FileTimeToSystemTime(ref fileTime, out systemTime)); 
  224. return systemTime; 
  225. } 
  226. private static void Check(bool nativeCallSucceeded) 
  227. { 
  228. if (!nativeCallSucceeded) 
  229. { 
  230. int error = Marshal.GetHRForLastWin32Error(); 
  231. Marshal.ThrowExceptionForHR(error); 
  232. } 
  233. } 
  234. [StructLayout(LayoutKind.Sequential)] 
  235. private struct SystemTime 
  236. { 
  237. public short Year; 
  238. public short Month; 
  239. public short DayOfWeek; 
  240. public short Day; 
  241. public short Hour; 
  242. public short Minute; 
  243. public short Second; 
  244. public short Milliseconds; 
  245. } 
  246. [StructLayout(LayoutKind.Sequential)] 
  247. private struct CryptoApiBlob 
  248. { 
  249. public int DataLength; 
  250. public IntPtr Data; 
  251. public CryptoApiBlob(int dataLength, IntPtr data) 
  252. { 
  253. this.DataLength = dataLength; 
  254. this.Data = data; 
  255. } 
  256. } 
  257. [StructLayout(LayoutKind.Sequential)] 
  258. private struct CryptKeyProviderInformation 
  259. { 
  260. [MarshalAs(UnmanagedType.LPWStr)] public string ContainerName; 
  261. [MarshalAs(UnmanagedType.LPWStr)] public string ProviderName; 
  262. public int ProviderType; 
  263. public int Flags; 
  264. public int ProviderParameterCount; 
  265. public IntPtr ProviderParameters; // PCRYPT_KEY_PROV_PARAM 
  266. public int KeySpec; 
  267. } 
  268. private static class NativeMethods 
  269. { 
  270. [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 
  271. [return: MarshalAs(UnmanagedType.Bool)] 
  272. public static extern bool FileTimeToSystemTime( 
  273. [In] ref long fileTime, 
  274. out SystemTime systemTime); 
  275. [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] 
  276. [return: MarshalAs(UnmanagedType.Bool)] 
  277. public static extern bool CryptAcquireContextW( 
  278. out IntPtr providerContext, 
  279. [MarshalAs(UnmanagedType.LPWStr)] string container, 
  280. [MarshalAs(UnmanagedType.LPWStr)] string provider, 
  281. int providerType, 
  282. int flags); 
  283. [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] 
  284. [return: MarshalAs(UnmanagedType.Bool)] 
  285. public static extern bool CryptReleaseContext( 
  286. IntPtr providerContext, 
  287. int flags); 
  288. [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] 
  289. [return: MarshalAs(UnmanagedType.Bool)] 
  290. public static extern bool CryptGenKey( 
  291. IntPtr providerContext, 
  292. int algorithmId, 
  293. int flags, 
  294. out IntPtr cryptKeyHandle); 
  295. [DllImport("AdvApi32.dll", SetLastError = true, ExactSpelling = true)] 
  296. [return: MarshalAs(UnmanagedType.Bool)] 
  297. public static extern bool CryptDestroyKey( 
  298. IntPtr cryptKeyHandle); 
  299. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  300. [return: MarshalAs(UnmanagedType.Bool)] 
  301. public static extern bool CertStrToNameW( 
  302. int certificateEncodingType, 
  303. IntPtr x500, 
  304. int strType, 
  305. IntPtr reserved, 
  306. [MarshalAs(UnmanagedType.LPArray)] [Out] byte[] encoded, 
  307. ref int encodedLength, 
  308. out IntPtr errorString); 
  309. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  310. public static extern IntPtr CertCreateSelfSignCertificate( 
  311. IntPtr providerHandle, 
  312. [In] ref CryptoApiBlob subjectIssuerBlob, 
  313. int flags, 
  314. [In] ref CryptKeyProviderInformation keyProviderInformation, 
  315. IntPtr signatureAlgorithm, 
  316. [In] ref SystemTime startTime, 
  317. [In] ref SystemTime endTime, 
  318. IntPtr extensions); 
  319. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  320. [return: MarshalAs(UnmanagedType.Bool)] 
  321. public static extern bool CertFreeCertificateContext( 
  322. IntPtr certificateContext); 
  323. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  324. public static extern IntPtr CertOpenStore( 
  325. [MarshalAs(UnmanagedType.LPStr)] string storeProvider, 
  326. int messageAndCertificateEncodingType, 
  327. IntPtr cryptProvHandle, 
  328. int flags, 
  329. IntPtr parameters); 
  330. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  331. [return: MarshalAs(UnmanagedType.Bool)] 
  332. public static extern bool CertCloseStore( 
  333. IntPtr certificateStoreHandle, 
  334. int flags); 
  335. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  336. [return: MarshalAs(UnmanagedType.Bool)] 
  337. public static extern bool CertAddCertificateContextToStore( 
  338. IntPtr certificateStoreHandle, 
  339. IntPtr certificateContext, 
  340. int addDisposition, 
  341. out IntPtr storeContextPtr); 
  342. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  343. [return: MarshalAs(UnmanagedType.Bool)] 
  344. public static extern bool CertSetCertificateContextProperty( 
  345. IntPtr certificateContext, 
  346. int propertyId, 
  347. int flags, 
  348. [In] ref CryptKeyProviderInformation data); 
  349. [DllImport("Crypt32.dll", SetLastError = true, ExactSpelling = true)] 
  350. [return: MarshalAs(UnmanagedType.Bool)] 
  351. public static extern bool PFXExportCertStoreEx( 
  352. IntPtr certificateStoreHandle, 
  353. ref CryptoApiBlob pfxBlob, 
  354. IntPtr password, 
  355. IntPtr reserved, 
  356. int flags); 
  357. } 
  358. } 

希望本文所述对大家的C#程序设计有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表