On certificates, what type should E-mail addresses be when in subjectAltName

Kimvais picture Kimvais · Jun 18, 2013 · Viewed 8.3k times · Source

Little bit of background: I'm building a certificate authority using M2Crypto and Django, so please think twice before voting to close this as off topic! :)

My approach is that end-users are identified by e-mail addresses and their self-signed trust-anchors are issued obviously by themselves, but how should I store their 'identity'?

I've seen many certificates out there in the wild where the practice has been to store mail addresses as subjectAltName = rfc822:[email protected], but googling suggest that the standard way would be subjectAltName = email:[email protected].

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

Answer

jww picture jww · Dec 19, 2013

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

Not really; and it depends on the PKI profile you are using. PKI and X509 are the wild, wild, west.

If you are running a Private PKI internal to you organization, it does not matter how you do it. Pick something and do it consistently.


On the web its generally PKIX and specified in RFC 5280, Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. According to 4.1.2.6, Subject:

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.

Then Section 4.2.1.6, Subject Alternative Name:

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
">".

Notice that it does not use either rfc822:[email protected] or email:[email protected]. Like I said, its the wild, wild west. You should be prepared for anything.


You also have the CA/Browser Forums and their standards for issuing certificates. The two documents of interest are:

But they defer back to RFC 5280.


The rfc822: and email: you are seeing is probably added by software for presentation. For example, to enumerate the SANs using OpenSSL, your function would look similar to:

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

(Sorry I don't have an example that extracts the IA5Strings handy).

In the above, notice the type: GEN_DNS or general DNS name. That's used for names like www.example.com. OpenSSL has a few of those types, and below is from 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

Your certificate viewer or presentation software is probably displaying rfc822: or email: because it encountered a type GEN_EMAIL.


When you look at OpenSSL's configuration file, you will see, for example:

...
[ v3_ca ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer:always
subjectAltName         = email:[email protected]
issuerAltName          = issuer:copy

The email: is not copied verbatim into the SAN. Rather, it tells OpenSSL to use the GEN_EMAIL type for the field.


If your certificate viewer or presentation software is not adding the prefix, then its probably parsing a Distinguished Named.

As for what's in a distinguished name, Peter Gutmann told me a long time ago (taking from his email): "Stick anything you want in the DN and present only the bits that are useful". Like I said, its the wild, wild west.


Email addresses might show up under an OID, too. For example, the 1.2.840.113549.1.9.1 arc. That's in addition to the SAN. Its why the image below has that label "Email Address".


Peter Gutmann has an X509 Style Guide. Taken from his description: it describes various X.509 certificate implementation details and pitfalls, provides recommendations on what to do and what not to do, and finishes with a list of known bugs and problems to look out for in existing implementations.


Finally, here's a user certificate issued by Startcom. They offer free certificates and charge you for revocation if needed (because that's where the cost lies). That's diametrically opposed to other CAs who charge for the revocation up front and pocket it if not needed ;)

The first is the X509 certificate:

enter image description here

And second is the dump of the certificate using Gutmann's dumpasn1 (get dumpasn1.c and dumpasn1.cfg from www.cs.auckland.ac.nz/~pgut001; compile with gcc dumpasn1.c -o dumpasn1; and copy into /usr/local/bin). Notice there is not rfc822: or email: prefix:

enter image description here