openssl - 在证书上,在 subjectAltName 中的电子邮件地址应该是什么类型

标签 openssl x509 m2crypto

一点点背景 :
我正在构建一个 certificate authority使用 M2Crypto 和 Django,所以请在投票结束前三思而后行! :)

我的方法是最终用户由电子邮件地址识别,他们的自签名信任 anchor 显然是由他们自己发布的,但我应该如何存储他们的“身份”?

我在野外看到了许多证书,其中的做法是将邮件地址存储为 subjectAltName = rfc822:user@domain.test。 , 但是 googling suggest标准方式是subjectAltName = email:user@domain.test .

两者之间有什么区别,如果有,首选哪一个?

最佳答案

Is there any difference between the two, and if so, which one is preferred?



并不真地;这取决于您使用的 PKI 配置文件。 PKI 和 X509 是狂野的、狂野的、西部的。

如果您在组织内部运行私有(private) PKI,那么如何操作并不重要。选择一些东西并始终如一地做。

在网络上,它通常是 PKIX 并在 RFC 5280 中指定,Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile .根据 4.1.2.6,主题:
Conforming implementations generating new certificates with
electronic mail addresses MUST use the rfc822Name in the subject
alternative name extension (Section 4.2.1.6) to describe such
identities.  Simultaneous inclusion of the emailAddress attribute in
the subject distinguished name to support legacy implementations is
deprecated but permitted.

然后第 4.2.1.6 节,主题备用名称:
When the subjectAltName extension contains an Internet mail address,
the address MUST be stored in the rfc822Name.  The format of an
rfc822Name is a "Mailbox" as defined in Section 4.1.2 of [RFC2821].
A Mailbox has the form "Local-part@Domain".  Note that a Mailbox has
no phrase (such as a common name) before it, has no comment (text
surrounded in parentheses) after it, and is not surrounded by "<" and
">".

请注意,它不使用 rfc822:user@domain.testemail:user@domain.test .就像我说的,它是狂野的西部。你应该为任何事情做好准备。

您还拥有 CA/浏览器论坛及其颁发证书的标准。两个感兴趣的文件是:
  • Baseline Certificate Requirements
  • Extended Validation Certificate Requirements

  • 但他们推迟到 RFC 5280。
    rfc822:email:您看到的可能是由软件添加的演示文稿。例如,要使用 OpenSSL 枚举 SAN,您的函数将类似于:
    void print_san_name(X509* const cert)
    {
        int success = 0;
        GENERAL_NAMES* names = NULL;
        unsigned char* utf8 = NULL;
    
        do
        {
            if(!cert) break; /* failed */
    
            names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
            if(!names) break;
    
            int i = 0, count = sk_GENERAL_NAME_num(names);
            if(!count) break; /* failed */
    
            for( i = 0; i < count; ++i )
            {
                GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
                if(!entry) continue;
    
                if(GEN_DNS == entry->type)
                {
                    int len1 = 0, len2 = -1;
    
                    len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
                    if(utf8) {
                        len2 = (int)strlen((const char*)utf8);
                    }
    
                    if(len1 != len2) {
                        fprintf(stderr, "Strlen and ASN1_STRING size do not match (embedded null?):"
                                        " %d vs %d\n", len2, len1);
                        /* Handle error */
                    }
    
                    /* Do something with utf8 */
    
                    if(utf8) {
                        OPENSSL_free(utf8), utf8 = NULL;
                    }
                }
                else if(GEN_EMAIL == entry->type)
                {
                    ...
                }
                ...
            }
    
        } while (0);
    
        if(names)
            GENERAL_NAMES_free(names);
    
        if(utf8)
            OPENSSL_free(utf8);
    }
    

    (对不起,我没有提取 IA5Strings 方便的示例)。

    在上面,请注意类型:GEN_DNS或通用 DNS 名称。用于 www.example.com 之类的名称. OpenSSL 有其中一些类型,以下来自 x509v3.h :
    #define GEN_OTHERNAME   0
    #define GEN_EMAIL       1
    #define GEN_DNS         2
    #define GEN_X400        3
    #define GEN_DIRNAME     4
    #define GEN_EDIPARTY    5
    #define GEN_URI         6
    #define GEN_IPADD       7
    #define GEN_RID         8
    

    您的证书查看器或演示软件可能正在显示 rfc822:email:因为它遇到了一个类型GEN_EMAIL .

    当您查看 OpenSSL 的配置文件时,您会看到,例如:
    ...
    [ v3_ca ]
    subjectKeyIdentifier   = hash
    authorityKeyIdentifier = keyid:always,issuer:always
    subjectAltName         = email:myEmail@email.com
    issuerAltName          = issuer:copy
    
    email:不会逐字复制到 SAN 中。相反,它告诉 OpenSSL 使用 GEN_EMAIL字段的类型。

    如果您的证书查看器或演示软件没有添加前缀,那么它可能会解析一个 Distinguished Named。

    至于什么是专有名称,Peter Gutmann 很久以前告诉我(摘自他的电子邮件):“在 DN 中添加任何你想要的东西,只展示有用的部分”。就像我说的,它是狂野的西部。

    电子邮件地址也可能显示在 OID 下。例如,1.2.840.113549.1.9.1 arc .这是对 SAN 的补充。这就是为什么下面的图片有标签“电子邮件地址”的原因。

    彼得古特曼有一个 X509 Style Guide .摘自他的描述:它描述了各种 X.509 证书实现细节和陷阱,提供了关于做什么和不做什么的建议,最后列出了在现有实现中需要注意的已知错误和问题列表。

    最后,这是 Startcom 颁发的用户证书。他们提供免费证书,并在需要时向您收取撤销费用(因为这是成本所在)。这与其他预先收取撤销费用并在不需要时将其放入口袋的 CA 截然相反;)

    首先是X509证书:

    enter image description here

    其次是使用 Gutmann 的 dumpasn1 转储证书。 (从 www.cs.auckland.ac.nz/~pgut001 获取 dumpasn1.c 和 dumpasn1.cfg;用 gcc dumpasn1.c -o dumpasn1 编译;并复制到 /usr/local/bin 中)。注意没有rfc822:email:字首:

    enter image description here

    关于openssl - 在证书上,在 subjectAltName 中的电子邮件地址应该是什么类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17172239/

    相关文章:

    python - 无法选择密码

    Python OpenSSL 给出握手失败

    c++ - 将 const 指针 (EVP_MD) 保存到变量,以便在类方法 (HMAC) 中重新使用它

    c# - Bouncy CaSTLe 中的 TlsSignerCredentials 和 TlsAgreementCredentials 有什么区别

    无法使用 openssl 将 X509 对象读入临时文件以进行 Windows C 编程

    python - 扭曲的 DTLS 连接

    python - Python 中的时间戳服务器 rfc3161 响应 token 生成

    Android 无法加载本地 libcrypto 未满足的链接错误

    openssl - 如何在 OpenSSL 中指定 x509 配置属性的数据类型

    python - swig 无法找到 openssl conf