使用C#和CertENrollLib添加证书请求(密码 - 质询)的扩展

时间:2014-07-25 11:56:31

标签: c# smartcard certenroll

我必须以尊重给定结构的方式添加证书请求(CSR)的扩展。即这一个ASN .1 structure

左边是我必须尊重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)”在编码请求的过程结束时,我尝试使用不同的智能卡广告,密钥容器都可以,而不是已满。

我的方法是否正确添加此挑战密码扩展名,我该如何解释此错误?

2 个答案:

答案 0 :(得分:2)

您获得的错误的答案&#34;该文件存在。 (HRESULT异常:0x80070050)&#34;是因为尝试在已经有密钥的模板上设置密钥。只是评论一下:

    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服务器并打开我们的模板   使用,我们可以发现密钥用法已在中定义   模板。这意味着在代码中,或在证书请求中我们   不应再指定它。

     

因此,我们需要评论添加密钥用法的代码   需要对增强型密钥使用部分进行评论,因为它已被定义   在模板中也是如此。因为我们让请求提供主题   在这里我们仍然可以指定主题信息   请求。生成请求消息的方法就是这样。

答案 1 :(得分:0)

以下是将挑战密码包含在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);