Openssl x509 print "Subject Alternative Name" (SAN)?

Is there a command to print the cert “Subject Alternative Name” (SAN) with openssl x509 -in ?

I have found only a command to print the “common name”: -subject

Please without -text

Hi @slart, I’ve never seen a way to do that. I just did a search and found that people have asked the same question on StackOverflow a number of times, and all of the answers appeared to suggest parsing the output from -text, or else writing a program to do it.

We do have logic in Certbot to do this from Python, and you can find it in

if you wanted to try to adapt it into a standalone Python program.

I also looked at certtool from GNUTLS, which sometimes has options that openssl doesn’t, but I didn’t see an easy way to do this with that program either.

I checked and the actual implementation is at

Note that it’s doing regular expression parsing of the text output, only within Python. According to the comment, there is apparently a nicer way to do it that’s less backwards-compatible.

Hi slart

Have a look at HTTPSforFree Code.

var domains = [];
try{
var csrAsn1 = ASN1.decode(Base64.decode(unarmor.exec(csr)[1]));

    // look for commonName in attributes
    if(csrAsn1.sub[0].sub[1].sub){
        var csrIds = csrAsn1.sub[0].sub[1].sub;
        for(var i = 0; i < csrIds.length; i++){
            var oidRaw = csrIds[i].sub[0].sub[0];
            var oidStart = oidRaw.header + oidRaw.stream.pos;
            var oidEnd = oidRaw.length + oidRaw.stream.pos + oidRaw.header;
            var oid = oidRaw.stream.parseOID(oidStart, oidEnd, Infinity);
            if(oid === "2.5.4.3"){
                var cnRaw = csrIds[i].sub[0].sub[1];
                var cnStart = cnRaw.header + cnRaw.stream.pos;
                var cnEnd = cnRaw.length + cnRaw.stream.pos + cnRaw.header;
                domains.push(cnRaw.stream.parseStringUTF(cnStart, cnEnd));
            }
        }
    }

    // look for subjectAltNames
    if(csrAsn1.sub[0].sub[3].sub){

        // find the PKCS#9 ExtensionRequest
        var xtns = csrAsn1.sub[0].sub[3].sub;
        for(var i = 0; i < xtns.length; i++){
            var oidRaw = xtns[i].sub[0];
            var oidStart = oidRaw.header + oidRaw.stream.pos;
            var oidEnd = oidRaw.length + oidRaw.stream.pos + oidRaw.header;
            var oid = oidRaw.stream.parseOID(oidStart, oidEnd, Infinity);
            if(oid === "1.2.840.113549.1.9.14"){

                // find any subjectAltNames
                for(var j = 0; j < xtns[i].sub[1].sub.length ? xtns[i].sub[1].sub : 0; j++){
                    for(var k = 0; k < xtns[i].sub[1].sub[j].sub.length ? xtns[i].sub[1].sub[j].sub : 0; k++){
                        var oidRaw = xtns[i].sub[1].sub[j].sub[k].sub[0];
                        var oidStart = oidRaw.header + oidRaw.stream.pos;
                        var oidEnd = oidRaw.length + oidRaw.stream.pos + oidRaw.header;
                        var oid = oidRaw.stream.parseOID(oidStart, oidEnd, Infinity);
                        if(oid === "2.5.29.17"){

                            // add each subjectAltName
                            var sans = xtns[i].sub[1].sub[j].sub[k].sub[1].sub[0].sub;
                            for(var s = 0; s < sans.length; s++){
                                var sanRaw = sans[s];
                                var tag = sanRaw.tag.tagNumber;
                                if(tag !== 2)
                                    continue; // ignore any other subjectAltName type than dNSName (2)
                                var sanStart = sanRaw.header + sanRaw.stream.pos;
                                var sanEnd = sanRaw.length + sanRaw.stream.pos + sanRaw.header;
                                domains.push(sanRaw.stream.parseStringUTF(sanStart, sanEnd));
                            }
                        }
                    }
                }
            }
        }
    }
}

esentially you need to use a AS1N parsing tool and look for an oid which has sans

Ooops. I had searched for a simpler way than “… -text | grep …”. :wink:

so did you find a better way? if so share with the class please :smiley:

openssl x509 -in XXX.crt -text -noout | grep 'DNS:' is probably the best. Any particular reason you want to avoid '-text'?

If you are using Perl, the following for example would work too:

perl -MCrypt::OpenSSL::X509 -e "print Crypt::OpenSSL::X509->new_from_file('XXX.crt')->extensions_by_name()->{'subjectAltName'}->value;"

NB: The above will fail if SAN is not present, but I guess in this particular case it's irrelevant.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.