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

时间:2016-02-25 01:59:45

标签: objective-c c ssl openssl x509certificate

上下文:

我正在使用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)

我正在调用该函数传递value的C-String,我认为这是不正确的。这是我正在做的电话:

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

发生了什么:

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

我需要什么:

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

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

1 个答案:

答案 0 :(得分:3)

在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;
}