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