【问题标题】:Programmatically verifying x509v3 extendedKeyUsage以编程方式验证 x509v3 extendedKeyUsage
【发布时间】:2019-06-04 05:46:28
【问题描述】:

背景

我需要以编程方式验证 x509 证书中的 extendedKeyUsage。我的目标是确保只有TLS Web Server Authentication, TLS Web Client Authentication 出现在extendedKeyUsage 中。我在 MacOS 上使用 OpenSSL 1.0.2p lib。

以下是我检索extendedKeyUsage 字段的代码:

#include <openssl/x509v3.h>
#include <openssl/bn.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <openssl/bio.h>

int verifyDeviceCertExtendedKeyUsage(){

    OpenSSL_add_all_algorithms();

    auto readBytes = MyApp::FileUtil::readAllBytes("path/to/pem");

    BIO *bio_mem = BIO_new(BIO_s_mem());
    BIO_puts(bio_mem, readBytes.data());
    X509 *x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL);

    ASN1_BIT_STRING *usage = static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL));
    if (usage && (usage->length > 0)){
        _CERTUTIL_LOG->debug("in verifyDeviceCertExtendedKeyUsage, usage->data[0]: {0:x}", (int)usage->data[0]);
    }
}

另外,摘自openssl x509 -text -noout -in path/to/pem的输出:

X509v3 Extended Key Usage: 
    TLS Web Server Authentication, TLS Web Client Authentication

问题

每次我运行我的代码时,usage-&gt;data[0] 的值都不同,这表明我的代码导致了未定义的行为。

注意:我使用类似的代码通过将X509_get_ext_d2i() 中的NID_ext_key_usage 替换为NID_key_usage 来成功检索keyUsage 字段。

如果我的代码返回了正确的值,我将通过与openssl/x509v3.h 中的以下内容进行比较来验证它:

# define XKU_SSL_SERVER          0x1
# define XKU_SSL_CLIENT          0x2

问题

我的代码有问题吗?

如何可靠地获取extendedKeyUsage 字段并验证它们?

更新

我找到了一个方法,但是比较字符串让我很不舒服:

BIO *bio_mem = BIO_new(BIO_s_mem());
BIO_puts(bio_mem, readBytes.data());
X509 *x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL);

auto extIndex = X509_get_ext_by_NID(x509, NID_ext_key_usage, -1);
if(extIndex < 0){
    BIO_free(bio_mem);
    X509_free(x509);
    return ERR;
}

X509_EXTENSION *ext = X509_get_ext(x509, extIndex);

EXTENDED_KEY_USAGE *eku = static_cast<EXTENDED_KEY_USAGE*>(X509V3_EXT_d2i(ext));

for(int i = 0 ; i < sk_ASN1_OBJECT_num(eku) ; i++){
    char buffer[100] = {0}; // <--- init all elements with 0, compiler specific behavior?
    OBJ_obj2txt(buffer, sizeof(buffer), sk_ASN1_OBJECT_value(eku, i), 1);

    if(strcmp(buffer, "1.3.6.1.5.5.7.3.1") == 0 && strcmp(buffer, "1.3.6.1.5.5.7.3.1") == 0){
        BIO_free(bio_mem);
        X509_free(x509);
        return SUCCESS;
    }
}

【问题讨论】:

  • 这是因为 X509_get_ext_d2i(..., NID_ext_key_usage, ...) 返回一个 EXTENDED_KEY_USAGE 结构(不像 NID_key_usage 那样的 ASN1_BIT_STRING)。您的 static_cast 破坏了一切,并且没有使用->数据字段。密钥用法和扩展密钥用法根本没有相同的格式,无论是在底层 X509 编码中,还是在内部 OpenSSL 结构中。

标签: c++ macos openssl x509


【解决方案1】:

在 openssl 1.1 中,一旦有了 X509 指针,就很容易了。你只需要使用以下方法:X509_get_extension_flagsX509_get_extended_key_usage

if ((X509_get_extension_flags(x509) & EXFLAG_XKUSAGE) == EXFLAG_XKUSAGE)
{
    auto const certificate_key_usage = X509_get_extended_key_usage(x509);
    if ((certificate_key_usage & (XKU_SSL_SERVER | XKU_SSL_CLIENT)) == (XKU_SSL_SERVER | XKU_SSL_CLIENT))
    {
        // has both TLS Web Server Authentication and TLS Web Client Authentication
    }
    else
    {
        // doesn't have both TLS Web Server Authentication and TLS Web Client Authentication
    }
}

对于旧版本的 openssl,您应该能够定义以下内容以使上述代码正常工作:

#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define X509_get_extension_flags(x) (x->ex_flags)
#define X509_get_extended_key_usage(x)  (x->ex_xkusage)
#endif

【讨论】:

  • 我尝试了你的建议。不幸的是x-&gt;ex_flags0
  • 我对上面的代码没有任何问题,所以问题可能是别的。可能是您加载证书的方式,也可能是证书本身。
  • 您可以尝试使用 PEM_read_bio_X509_AUX 之类的东西来加载 PEM 文件。
  • 我遇到了同样的问题并调用 X509_check_purpose(x, -1, -1); 加载了标志,也许有更好的方法来确保加载标志。
  • 我从来没有遇到过这个问题,但是查看 X509_get_extension_flags / X509_get_extended_key_usage 的 1.1.1 源代码,他们称之为 X509_check_purpose。因此,我假设您使用的是 openssl
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
  • 2016-01-02
相关资源
最近更新 更多