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

作者:jiangzhenyu 时间:2021-12-02 03:17:03 

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


using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using SecureString = System.Security.SecureString;
using RuntimeHelpers = System.Runtime.CompilerServices.RuntimeHelpers;
internal class Certificate
{
public static byte[] CreateSelfSignCertificatePfx(
 string x500,
 DateTime startTime,
 DateTime endTime)
{
 byte[] pfxData = CreateSelfSignCertificatePfx(
  x500,
  startTime,
  endTime,
  (SecureString)null);
 return pfxData;
}
public static byte[] CreateSelfSignCertificatePfx(
 string x500,
 DateTime startTime,
 DateTime endTime,
 string insecurePassword)
{
 byte[] pfxData;
 SecureString password = null;
 try
 {
  if (!string.IsNullOrEmpty(insecurePassword))
  {
   password = new SecureString();
   foreach (char ch in insecurePassword)
   {
    password.AppendChar(ch);
   }
   password.MakeReadOnly();
  }
  pfxData = CreateSelfSignCertificatePfx(
   x500,
   startTime,
   endTime,
   password);
 }
 finally
 {
  if (password != null)
  {
   password.Dispose();
  }
 }
 return pfxData;
}
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();
 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, // 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
  }
 }
 return pfxData;
}
private static SystemTime ToSystemTime(DateTime dateTime)
{
 long fileTime = dateTime.ToFileTime();
 SystemTime systemTime;
 Check(NativeMethods.FileTimeToSystemTime(ref fileTime, out systemTime));
 return systemTime;
}
private static void Check(bool nativeCallSucceeded)
{
 if (!nativeCallSucceeded)
 {
  int error = Marshal.GetHRForLastWin32Error();
  Marshal.ThrowExceptionForHR(error);
 }
}
[StructLayout(LayoutKind.Sequential)]
private struct SystemTime
{
 public short Year;
 public short Month;
 public short DayOfWeek;
 public short Day;
 public short Hour;
 public short Minute;
 public short Second;
 public short Milliseconds;
}
[StructLayout(LayoutKind.Sequential)]
private struct CryptoApiBlob
{
 public int DataLength;
 public IntPtr Data;
 public CryptoApiBlob(int dataLength, IntPtr data)
 {
  this.DataLength = dataLength;
  this.Data = data;
 }
}
[StructLayout(LayoutKind.Sequential)]
private struct CryptKeyProviderInformation
{
 [MarshalAs(UnmanagedType.LPWStr)] public string ContainerName;
 [MarshalAs(UnmanagedType.LPWStr)] public string ProviderName;
 public int ProviderType;
 public int Flags;
 public int ProviderParameterCount;
 public IntPtr ProviderParameters; // PCRYPT_KEY_PROV_PARAM
 public int KeySpec;
}
private 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);
}
}

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

标签:C#,签名,认证
0
投稿

猜你喜欢

  • C语言实现四窗口聊天

    2021-12-28 01:02:12
  • Windows+Apache+resin配置

    2023-10-16 08:53:07
  • Asp.Net中MVC缓存详解

    2023-06-08 13:44:45
  • 配置springboot项目使用外部tomcat过程解析

    2021-11-22 22:34:25
  • Mybatis核心组成部分之SQL映射文件揭秘详解

    2023-08-22 18:45:21
  • java简单实现斗地主发牌功能

    2023-06-18 16:22:44
  • Java中BigInteger与BigDecimal类用法总结

    2021-09-14 07:15:26
  • Java Stopwatch类,性能与时间计时器案例详解

    2023-07-24 04:08:50
  • Java数据结构学习之树

    2022-01-19 23:40:58
  • SpringBoot+Spring Security+JWT实现RESTful Api权限控制的方法

    2022-07-18 03:38:36
  • Android实现网络图片浏览功能

    2023-10-17 14:05:38
  • springboot2.x只需两步快速整合log4j2的方法

    2023-06-06 20:41:21
  • C# AttributeUsage使用案例详解

    2022-06-25 08:12:09
  • Springboot整合MybatisPlus的实现过程解析

    2021-06-14 02:47:06
  • Flutter倒计时/计时器的实现代码

    2023-07-01 03:50:50
  • Java java.sql.Timestamp时间戳案例详解

    2023-11-10 13:50:47
  • 教你怎么用Java获取国家法定节假日

    2021-05-24 01:16:04
  • C#控制台实现飞行棋游戏

    2022-03-12 04:18:40
  • android仿直播圆点加载效果

    2023-11-13 07:11:10
  • JAVA WSIMPORT生成WEBSERVICE客户端401认证过程图解

    2023-11-14 00:27:55
  • asp之家 软件编程 m.aspxhome.com