Search code examples
perlsslx509san

How to properly obtain SAN using Perl library Crypt::OpenSSL::X509


I have been using Crypt::X509 before, but now I porting my code to newer supported library Crypt::OpenSSL::X509. The most important fields in the certificate are CN and SAN, I expect there are a simple call like:

use Crypt::X509;
print $x509->$cert_hr->SubjectAltName;

But instead I have to use cumbersome code:

use Crypt::OpenSSL::X509;
my $ext = $x509->extensions_by_oid();
print ${$ext}{'2.5.29.17'}->value();

But what makes it worse, returned string has parasitic "." inside, and I need to create some smart regular expressions to safely clean it.

I feel I am missing something simple. Is there another function or library?

Edit: Test results: Proposed Timothy solution works as long as you updated to latest version of library. Cannot add comment, neither press 'Accepted answer.' Will re-visit later.


Solution

  • Here is an example of how to do it using Crypt::OpenSSL::X509 and Convert::ASN1 which I must say took far more time that I expected it to take:

    use Crypt::OpenSSL::X509;
    use Convert::ASN1;
     
    my $x509 = Crypt::OpenSSL::X509->new_from_file('google.pem');
    my $ext = $x509->extensions_by_oid();
    my $pdu = ${$ext}{'2.5.29.17'}->value();
    $pdu =~ s/#//g;
    
    my @san = get_san($pdu);
    
    print "Size: ", scalar @san, "\n";
    
    foreach (@san) {
        print "$_\n";
    }
    
    sub get_san {
        my $bin_data = join '', pack 'H*', @_;
        $asn = Convert::ASN1->new();
    
        my $ok = $asn->prepare(q<
            DNSName ::=  
                [2]
                IA5String
            SubjectAltName ::= SEQUENCE OF
                DNSName
        >);
        die "*** Could not prepare definition: ".$asn->error()
            if !$ok;
    
        my $top = $asn->find("SubjectAltName")
            or die $asn->error;
        $out = $top->decode($bin_data)
            or die "can't decode SubjectAltName: ".$top->error;
    
        return @$out;
    }
    

    https://github.com/dsully/perl-crypt-openssl-x509/pull/92 implements an expanded form of this which should work for most X509 certificates