C#创建自签名认证文件的方法
作者:jiangzhenyu 发布时间:2021-12-02 03:17:03
标签:C#,签名,认证
本文实例讲述了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#程序设计有所帮助。


猜你喜欢
- 一个简单的微服务架构图本文设计的 Spring Cloud 版本以及用到的 Spring Cloud 组件Spring Cloud Hoxt
- 问题:最近在项目中遇到,不同客户机安装不同Office版本,在导出Excel时,发生错误。找不到Excel Com组件,错误信息如下。&nb
- 1、什么是值传递,什么是引用传递?值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数
- 前言quarkus号称超音速亚原子JAVA为Graalvm量身定制的java堆栈,是否名副其实呢?下面就来看看真实情况如何。动手前先简单介绍
- 1.在实体类中添加@TableId注解:2.在navicat中设置id自动增长:3.测试一下,当我们再次插入的时候,就会看到id4.对注解中
- 一、线程的优先级别线程优先级别的使用范例:package cn.galc.test;public class TestThread6 { p
- 概述本文介绍通过java程序向PDF文档添加图片,以及替换和删除PDF中已有的图片。另外,关于图片的操作还可参考设置PDF 图片背景、设置P
- 手动编写 SQL 语句和映射实体类的过程常常是繁琐且易出错的。这时,我们就可以借助 MyBatis Generator (MBG) 这个强大
- c#下压缩解压,主要是用第三方类库进行封装的。ICSharpCode.SharpZipLib.dll类库,链接地址为你官方下载链接。压缩主要
- 基本结构我们先来看一段最基本的代码,分析这段代码在RxJava中是如何实现的。Observable.OnSubscribe<Strin
- 内存泄露,是Android开发者最头疼的事。可能一处小小的内存泄露,都可能是毁千里之堤的蚁穴。 怎么才能检测内存泄露呢? AndroidSt
- 在C#当中,利用WebClient这个核心类,可以轻易的打造一个下载器。但是这里想要强调的是,我们用的是异步操作。所谓异步,是相对于同步的概
- 0.关于AOP面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也
- 本文实例讲述了Android编程开发之Spinner组件用法。分享给大家供大家参考,具体如下:Spinner组件组要用显示一个下拉列表,在使
- 需求:用户和账户一对一关系,查询账户时实现用户的延迟加载思路:根据id查询,需要延迟加载的一方1、用户实体类package com.yl.b
- Eureka注册中心/服务发现框架Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中
- struts2可以非常简单地使用FreeMarker模板作为视图技术,对于传统的jsp页面而言,FreeMarker是一个绝佳的替代方案。除
- Swing包的介绍Java基础类数据库(Java Foundation Class)给java应用程序增加了图形界面、丰富的功能性以及与用户
- 前提:你的电脑是AMD处理器,想使用Android studio,自己的电脑系统是win10家庭版,在百度找到勾选hyper-v就能用,然后
- 1、引出安卓初学者一般在写android Activity的时候总是会在onCreate方法中加上setContentView方法来加载la