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

问题描述 投票:1回答:2

我必须以尊重给定结构的方式添加证书请求(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)”,我尝试使用不同的智能卡广告,密钥容器都可以,但不是满的。

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

c# smartcard certenroll
2个回答
2
投票

您收到错误的答案“文件存在。(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服务器并打开我们正在使用的模板,我们可以发现密钥用法已在模板中定义。这意味着在代码或证书请求中我们不应再次指定它。

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


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);
© www.soinside.com 2019 - 2024. All rights reserved.