我必须以尊重给定结构的方式添加证书请求(CSR)的扩展。就是这一个
左边是我必须尊重chalenge密码的结构,右边是我从challenge-password OID值生成OID对象时得到的结构,然后将所有这些直接嵌入到PKCS10请求的扩展列表中:
CObjectId cp_oid = new CObjectId();
// OID 1.2.840.113549.1.9.7
// cp_oid.InitializeFromName(CERTENROLL_OBJECTID.XCN_OID_RSA_challengePwd);
cp_oid.InitializeFromValue("1.2.840.113549.1.9.7");
然后我创建一个CX509Extension对象将OID添加到PKCS10请求:
CX509Extension extension = new CX509Extension();
string b64__challengePassword=System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(this.challengePassword));
extension.Initialize(cp_oid, EncodingType.XCN_CRYPT_STRING_BASE64_ANY, b64__challengePassword);
_certificateRequest.X509Extensions.Add(extension);
由于结构明显不同于我必须获得的结构(见上图的右侧部分),我现在使用更复杂的方法:
_certificateRequest = new CX509CertificateRequestPkcs10();
_certificateRequest.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, (CX509PrivateKey)_privateKey, null);
_certificateRequest.Subject = (CX500DistinguishedName)_subjectName;
CObjectIds cp_oids = new CObjectIds();
CObjectId cp_oid = new CObjectId();
// OID 1.2.840.113549.1.9.7
// cp_oid.InitializeFromName(CERTENROLL_OBJECTID.XCN_OID_RSA_challengePwd);
cp_oid.InitializeFromValue("1.2.840.113549.1.9.7");
CX509Extension _extension = new CX509Extension();
cp_oids.Add(cp_oid);
//now how do I add that oid list to the 1.2.840.113549.1.9.14 OID ?
//I try with CX509ExtensionEnhancedKeyUsage instead of a simple CX509Extension
//which one of all these is the correct extensions?
/*
* IX509ExtensionAlternativeNames Specifies one or more alternative name forms for the subject of a certificate.
IX509ExtensionAuthorityKeyIdentifier Represents an AuthorityKeyIdentifier extension.
IX509ExtensionBasicConstraints Specifies whether the certificate subject is a certification authority and, if so, the depth of the subordinate certification authority chain.
IX509ExtensionCertificatePolicies Represents a collection of policy information terms.
IX509ExtensionMSApplicationPolicies Represents a collection of object identifiers that indicate how a certificate can be used by an application.
IX509ExtensionEnhancedKeyUsage Represents a collection of object identifiers that identify the intended uses of the public key contained in a certificate.
IX509ExtensionKeyUsage Represents restrictions on the operations that can be performed by the public key contained in the certificate.
IX509Extensions Manages a collection of IX509Extension objects.
IX509ExtensionSmimeCapabilities Represents a collection that reports the decryption capabilities of an email recipient to an email sender.
IX509ExtensionSubjectKeyIdentifier Represents a SubjectKeyIdentifier extension used to identify a signing certificate.
IX509ExtensionTemplate Represents a CertificateTemplate extension that contains a version 2 template.
IX509ExtensionTemplateName Represents a CertificateTemplateName extension that contains a version 1 template.
*/
CX509ExtensionEnhancedKeyUsage eku = new CX509ExtensionEnhancedKeyUsage();
eku.InitializeEncode(cp_oids);
eku.Critical = false;
CX509AttributeExtensions InitExt = new CX509AttributeExtensions();
// Add the extension objects into an IX509Extensions collection.
CX509Extensions ext1 = new CX509Extensions();
ext1.Add((CX509Extension)eku);
// Use the IX509Extensions collection//to initialize an IX509AttributeExtensions object.
CX509AttributeExtensions ext1att = new CX509AttributeExtensions();
ext1att.InitializeEncode(ext1);
//Add the IX509AttributeExtensions object to an IX509Attributes collection.
CX509Attributes att1 = new CX509Attributes();
att1.Add((CX509Attribute)ext1att);
//Use the IX509Attributes collection to initialize an ICryptAttribute object.
CCryptAttribute crypt1 = new CCryptAttribute();
crypt1.InitializeFromValues(att1);
//Initialize a CMC or PKCS #10 request object and retrieve the ICryptAttributes collection.
//Add the ICryptAttribute object to the ICryptAttributes collection for the request.
_certificateRequest.CryptAttributes.Add(crypt1);
//Console.WriteLine("-- encode");
this.status2 = this.status2 + "-- encode <BR>";
try
{
_certificateRequest.Encode();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
string rawData = _certificateRequest.get_RawData();
Console.WriteLine("data=" + rawData);
然而,我在编码请求的过程结束时得到了令人费解的错误“文件存在。(HRESULT的异常:0x80070050)”,我尝试使用不同的智能卡广告,密钥容器都可以,但不是满的。
我的方法是添加此挑战 - 密码扩展是否正确,我该如何解释此错误?
您收到错误的答案“文件存在。(HRESULT:0x80070050除外)”是因为尝试在已有密钥的模板上设置密钥。只是评论这个:
CX509ExtensionEnhancedKeyUsage eku = new CX509ExtensionEnhancedKeyUsage();
eku.InitializeEncode(cp_oids);
eku.Critical = false;
CX509AttributeExtensions InitExt = new CX509AttributeExtensions();
// Add the extension objects into an IX509Extensions collection.
CX509Extensions ext1= new CX509Extensions();
ext1.Add((CX509Extension)eku);
它应该工作。
在文章Working with Active Directory Certificate Service via C#中搜索:
似乎我们已经完成了,但是如果我们只是执行它会向我们抛出异常,说在添加一些扩展时该文件存在。
它解释了一切。
来自文章:
异常消息可能有点令人困惑。实际上,这是因为我们定义了在证书模板中定义的内容。如果我们深入研究源代码,我们可以看到在添加密钥用法扩展时发生了异常。
如果我们回到CA服务器并打开我们正在使用的模板,我们可以发现密钥用法已在模板中定义。这意味着在代码或证书请求中我们不应再次指定它。
因此,我们需要对添加密钥用法的代码进行注释,我们还需要对增强型密钥使用部分进行注释,因为它也已在模板中定义。因为我们让请求提供主题名称,所以我们仍然可以在请求中指定主题信息。生成请求消息的方法是这样的。
以下是将CertEnroll生成的挑战密码包含在PKCS10中的代码:
private static byte[] getDerBytes(int tag, byte[] data)
{
if (data.Length > byte.MaxValue)
{
throw new NotSupportedException("Support for integers greater than 255 not yet implemented.");
}
var header = new byte[] { (byte)tag, (byte)data.Length };
return header.Concat(data).ToArray();
}
和
public static byte[] EncodePrintableString(string data)
{
var dataBytes = Encoding.ASCII.GetBytes(data);
return getDerBytes(0x13, dataBytes);
}
最后:
CObjectId cp_oid = new CObjectId();
cp_oid.InitializeFromName(CERTENROLL_OBJECTID.XCN_OID_RSA_challengePwd);
byte[] b64__challengePassword = EncodePrintableString("password");
ICryptAttribute ChallengeAttributes = new CCryptAttribute();
ChallengeAttributes.InitializeFromObjectId(cp_oid);
CX509Attribute ChallengeAttribute = new CX509Attribute();
ChallengeAttribute.Initialize(cp_oid, EncodingType.XCN_CRYPT_STRING_BASE64_ANY,
Convert.ToBase64String(b64__challengePassword));
ChallengeAttributes.Values.Add(ChallengeAttribute);
objPkcs10.CryptAttributes.Add((CCryptAttribute)ChallengeAttributes);