OpenSSL x509证书:使用X509_add1_ext_i2d()添加扩展名

语境:

我正在使用OpenSSL中的API生成x509证书。 我首先创建这样的X509结构:

X509 *x509 = X509_new(); // Assume no errors 

我想做什么:

现在我想为此证书添加扩展名。 具体来说,我想将“扩展密钥用法”扩展名设置为值serverAuth,clientAuth 。 为此,我尝试使用具有以下签名的OpenSSL函数x509_add1_ext_i2d()

 X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags) 

我正在调用该函数传递一个C字符串的value ,我认为这是不正确的。 这是我正在制作的电话:

 X509_add1_ext_i2d(x509, NID_ext_key_usage, "serverAuth,clientAuth", 0, 0) 

发生了什么:

当该行代码运行时,我得到一个EXC_BAD_ACCESS (code=EXC_i386_GPFLT)exception。 我假设那是因为我传入的value必须是某种特殊的东西(一个八位字符串?某种其他的OpenSSL值?)


我需要的:

为了正确地将该扩展名设置为字符串值serverAuth,clientAuth我需要为value参数传递什么? 或者,或者,为什么我得到列出的例外? 注意:如果我删除此行并尝试生成没有扩展名的证书(其他属性,如名称,到期日期等,我为了简洁而在此处排除),它可以正常工作。

我花了一整天的时间来倾听OpenSSL(荒谬可怜)的文档和谷歌搜索。 我能找到的所有内容都讨论了如何从命令行而不是代码中添加证书扩展。 我无法追踪这个函数期望在value参数中看到的内容。

在OpenSSL的源代码中进行了一些更多的工作之后,我偶然发现了makecert.c示例中的一个函数。 我已经稍微清理了一下,就在这里。 您传入要设置的扩展的NID以及它的简单字符串值。 非常便利:

 BOOL addExtension(X509 *cert, int nid, char *value) { X509_EXTENSION *ex = NULL; X509V3_CTX ctx; // This sets the 'context' of the extensions. No configuration database X509V3_set_ctx_nodb(&ctx); // Issuer and subject certs: both the target since it is self signed, no request and no CRL X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); if (!ex) { return NO; } int result = X509_add_ext(cert, ex, -1); X509_EXTENSION_free(ex); return (result == 0) ? YES : NO; }