C# 仅使用.Net生成证书请求并提交给CA
我正在尝试仅使用.Net代码创建证书请求,并将请求提交给我们的内部Active Directory PKI证书颁发机构,然后获取证书。我有一个已经工作了几年的解决方案,但它使用了CERTCLILib和CERTENROLLLib,我想摆脱这些依赖关系,并将此代码移植到.NET5 然后将这些证书导入Yubikey设备。我们在Yubikey上生成密钥对,然后将公钥与CSR一起使用 这个问题对于获得一个DER编码的CSR非常有帮助,但我仍然有一些问题没有弄清楚C# 仅使用.Net生成证书请求并提交给CA,c#,.net-core,certificate,pki,C#,.net Core,Certificate,Pki,我正在尝试仅使用.Net代码创建证书请求,并将请求提交给我们的内部Active Directory PKI证书颁发机构,然后获取证书。我有一个已经工作了几年的解决方案,但它使用了CERTCLILib和CERTENROLLLib,我想摆脱这些依赖关系,并将此代码移植到.NET5 然后将这些证书导入Yubikey设备。我们在Yubikey上生成密钥对,然后将公钥与CSR一起使用 这个问题对于获得一个DER编码的CSR非常有帮助,但我仍然有一些问题没有弄清楚 如何指定要在CertificateRequ
CertificateRequest
对象中使用的CA和模板rsapameters
对象。如何将其放入RSA
对象中,以便与certificateRequest
构造函数一起使用System.Security.Cryptography.X509Certificates
命名空间中找不到任何实现该功能的类或方法DeviceDetails
包含关于Yubikey设备以及CA和模板的属性。此代码是一个更大的应用程序的一部分,该应用程序提供Yubikey设备
{
//private const int CC_UIPICKCONFIG = 0x1;
private const int CR_IN_BASE64 = 0x1;
private const int CR_IN_FORMATANY = 0;
private const int CR_DISP_ISSUED = 0x3;
private const int CR_DISP_UNDER_SUBMISSION = 0x5;
private const int CR_OUT_BASE64 = 0x1;
public static string GenerateRequest(DeviceDetails deviceDetails)
{
// Create all the objects that will be required
var objPkcs10 = new CX509CertificateRequestPkcs10();
var objDN = new CX500DistinguishedName();
var objObjectIds = new CObjectIds();
var objObjectId = new CObjectId();
var objExtensionKeyUsage = new CX509ExtensionKeyUsage();
var objX509ExtensionEnhancedKeyUsage = new CX509ExtensionEnhancedKeyUsage();
var objPublicKey = new CX509PublicKey();
try
{
var publicKey = Utilities.ExportPublicKeyToPEMFormat(deviceDetails.PublicKey);
publicKey = string.Join("", publicKey.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Where(s => !s.StartsWith("--")));
objPublicKey.InitializeFromEncodedPublicKeyInfo(publicKey, EncodingType.XCN_CRYPT_STRING_BASE64);
var sha512 = new CObjectId();
sha512.InitializeFromValue("2.16.840.1.101.3.4.2.3");
// Initialize the PKCS#10 certificate request object based on the public key.
objPkcs10.InitializeFromPublicKey(X509CertificateEnrollmentContext.ContextUser, objPublicKey, "");
objPkcs10.HashAlgorithm = sha512;
//Key Usage Extension
objExtensionKeyUsage.InitializeEncode(
X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE
);
objPkcs10.X509Extensions.Add((CX509Extension)objExtensionKeyUsage);
// Enhanced Key Usage Extension
objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2"); // OID for Client Authentication usage
objObjectIds.Add(objObjectId);
objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);
objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage);
// Encode the name in using the Distinguished Name object
objDN.Encode(
deviceDetails.CertificateDetails.Subject,
X500NameFlags.XCN_CERT_NAME_STR_NONE
);
// Adding the subject name by using the Distinguished Name object initialized above
objPkcs10.Subject = objDN;
// Adding the Subject Alternate Names
var strRfc822Name = deviceDetails.UserDetails.OUN + "@corp.com";
var strUpn = deviceDetails.UserDetails.OUN + "@corp.com";
var objRfc822Name = new CAlternativeName();
var objUserPrincipalName = new CAlternativeName();
var objAlternativeNames = new CAlternativeNames();
var objExtensionAlternativeNames = new CX509ExtensionAlternativeNames();
// Set Alternative RFC822 Name
objRfc822Name.InitializeFromString(AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME, strRfc822Name);
// Set Alternative UPN
objUserPrincipalName.InitializeFromString(AlternativeNameType.XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME, strUpn);
// Set Alternative Names
objAlternativeNames.Add(objRfc822Name);
objAlternativeNames.Add(objUserPrincipalName);
objExtensionAlternativeNames.InitializeEncode(objAlternativeNames);
objPkcs10.X509Extensions.Add((CX509Extension)objExtensionAlternativeNames);
// Create a CMC outer request and initialize
var cmcReq = new CX509CertificateRequestCmc();
cmcReq.InitializeFromInnerRequestTemplateName(objPkcs10, deviceDetails.CertificateDetails.TemplateName);
// encode the request
cmcReq.Encode();
var strRequest = cmcReq.RawData[EncodingType.XCN_CRYPT_STRING_BASE64];
return strRequest;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
// Submit request to CA and get response
public static X509Certificate2 SendRequest(DeviceDetails deviceDetails, string request, out string error)
{
error = "";
// Create all the objects that will be required
//var objCertConfig = new CCertConfig();
var objCertRequest = new CCertRequest();
try
{
// Submit the request
var iDisposition = objCertRequest.Submit(
CR_IN_BASE64 | CR_IN_FORMATANY,
request,
null,
deviceDetails.CertificateDetails.IssuingCa
);
// Check the submission status
if (CR_DISP_ISSUED != iDisposition) // Not enrolled
{
var strDisposition = objCertRequest.GetDispositionMessage();
if (CR_DISP_UNDER_SUBMISSION == iDisposition) // Pending
{
error = "The submission is pending: " + strDisposition;
return null;
}
else // Failed
{
error = $"The submission failed: {strDisposition}. Last status: {objCertRequest.GetLastStatus()}";
return null;
}
}
// Get the certificate
var strCert = objCertRequest.GetCertificate(CR_OUT_BASE64);
var rawCert = Convert.FromBase64String(strCert);
return new X509Certificate2(rawCert);
}
catch (Exception ex)
{
throw new Exception($"Error sending the request. {ex.Message}");
}
}
多部分问题很难回答,因为它们需要多部分答案。以下是我可以回答的部分: 如何指定要在CertificateRequest对象中使用的CA和模板 您不能,但这没关系,因为您也不在CertEnroll代码中。CertificateRequest对象相当于您的
objPkcs10
,CA和模板用于处理CreateSigningRequest
输出
我有一个公钥,它是一个对象。如何将其放入RSA对象以与CertificateRequest构造函数一起使用
一旦我有了DER编码的CSR,我如何将其提交给CA?我在System.Security.Cryptography.X509Certificates命名空间中找不到实现此功能的任何类或方法
这个盒子里没有直接的东西。基于
CX509CertificateRequest
类名,它似乎正在使用,但仍有身份验证和请求提交部分需要解决。我用以下行指定模板名称:cmcReq.initializeFrominerRequestTemplateName(objPkcs10,deviceDetails.CertificateDetails.TemplateName);因此,似乎(到目前为止)没有一种方法(仅使用dotnet)来实现这一点。@Dbloom好吧,它没有一条简单的路线,没有。但一旦您能够找到如何发现AD CS服务器并与之对话,可能所有的部分都存在。
using (RSA key = RSA.Create())
{
key.ImportParameters(rsaParameters);
...
}