使用 OpenSSL(以编程方式)向 PKCS#10 请求添加自定义扩展

Adding custom extension to PKCS#10 request using OpenSSL (programatically)

我想向通过 OpenSSL 创建的 PKCS#10 请求添加自定义扩展。请求生成和签名代码工作正常。

我可以通过它的 nid 添加已知的扩展,像这样(我从 Delphi 调用 OpenSSL):

as := 'critical,digitalSignature';
ext := X509V3_EXT_conf_nid(nil,nil,NID_key_usage,addr(as[1]));
sk_push(exts,ext);
X509_REQ_add_extensions(req,exts)

这按预期工作。现在我有了扩展的 OID 和数据,但我没有 nid。据我所知,我可以创建一个 nid:

NID:= OBJ_create(PAnsiChar(aoid),PAnsiChar(ashortname),PAnsiChar(alongname));

但是如果我尝试使用这个扩展,我会收到未知扩展错误。我发现我需要告诉 OpenSSL 如何处理我的扩展,例如通过使用类似的扩展:

  X509V3_EXT_add_alias(nid,NID_netscape_comment);

但问题是,如果我没有类似的扩展名来给它取别名怎么办?例如我想添加 szOID_REQUEST_CLIENT_INFO (1.3.6.1.4.1.311.21.20) 这是一个整数序列和 3 个 UTF8Strings:

SEQUENCE 
{
clientId INTEGER,
MachineName UTF8STRING,
UserName UTF8STRING,
ProcessName UTF8STRING
} 

或 szOID_ENROLLMENT_CSP_PROVIDER (1.3.6.1.4.1.311.13.2.2) 基本上是一个 BMP 字符串。

我有一个从 ASN.1 创建 DER 字节的代码,因此我可以轻松地将扩展数据创建为 OpenSSL 的原始字节,但我没有找到创建此类扩展的方法。基本上 man x509v3_config

中描述了类似的东西
1.2.3.4=DER:01:02:03:04

我终于成功了。主要的困惑是我不想添加扩展名而是添加属性。扩展只能包含 OCTET STRING 数据。这可以通过如下指定数据来实现:

data := 'DER:310C160A3....';
ext := X509V3_EXT_conf_nid(nil,nil,nid,addr(data[1]));

在这种情况下,X509V3_EXT_conf_nid 不会抱怨未知扩展(即使没有别名)并创建将采用以下形式的扩展:

  377:d=7  hl=2 l=  10 prim: OBJECT            :1.3.6.1.4.1.311.13.2.3
  389:d=7  hl=2 l=  15 prim: OCTET STRING      [HEX DUMP]:310C160A362E312E373630312E3230

扩展名将始终是 OCTET STRING,因为它应该是 DER 编码数据。

但是该属性与扩展具有相同的深度,并且可以包含任何 DER 数据。所以

data := loadfromhex('31091607312E322E33234');
X509_REQ_add1_attr_by_nid(req,nid,ASN1_SEQUENCE,addr(data[1]),length(data));

将产生所需的输出:

  377:d=4  hl=2 l=  10 prim: OBJECT            :1.3.6.1.4.1.311.13.2.3
  389:d=4  hl=2 l=   9 cons: SET               
  391:d=5  hl=2 l=   7 prim: IA5STRING         :1.2.3.4