From: Chris R. <chr...@me...> - 2001-09-21 08:44:12
|
Norbert Klasen <nor...@da...> wrote: > Hi, > I'm trying to decode X.509 certificates with Convert::ASN1 (0.14). This > works quite well exept for Names: > > AttributeTypeAndValue ::= SEQUENCE { > type AttributeType, > value AttributeValue } > > RelativeDistinguishedName ::= SET OF AttributeTypeAndValue > > RDNSequence ::= SEQUENCE OF RelativeDistinguishedName > > Name ::= CHOICE { -- only one possibility for now -- > rdnSequence RDNSequence } > > > It seems, as if the hashs for the SET elements are added to the wrong > parent. As result I get something like: > > issuer => { > rdnSequence => [], > value => '??cer...@tr...', > type => '1.2.840.113549.1.9.1' > } I tend to leave the DNs in the basic certificate as 'ANY', and then decode them separately. my %oid2attr = ( '2.5.4.3' => 'cn', '2.5.4.6' => 'c', '2.5.4.7' => 'l', '2.5.4.8' => 'st', '2.5.4.10' => 'o', '2.5.4.11' => 'ou', '0.9.2342.19200300.100.1.25' => 'dc' ); $asn->prepare(q< SEQUENCE { SEQUENCE { [0] IMPLICIT SEQUENCE { version INTEGER } serialNumber ANY, -- an INTEGER, but potentially big sigalg ANY, issuer ANY, -- a DN SEQUENCE { notBefore UTCTime, notAfter UTCTime } subject ANY, -- a DN spkinfo ANY, issueruid [1] IMPLICIT ANY OPTIONAL, subjectuid [2] IMPLICIT ANY OPTIONAL, [3] IMPLICIT SEQUENCE { extensions ANY } } alg ANY OPTIONAL, sig BIT STRING }>) or die; my $out = $asn->decode($cert) or die; print decodeDN($out->{'subject'}); sub decodeDN { my $pdu = shift; my $dn = Convert::ASN1->new; $dn->prepare("rdns SEQUENCE OF ANY"); my $rdn = Convert::ASN1->new; $rdn->prepare("rdn SET OF ANY"); my $ava = Convert::ASN1->new; $ava->prepare(q< SEQUENCE { type OBJECT IDENTIFIER, CHOICE { p PrintableString, t T61String, b BMPString, u UniversalString, i IA5String } } >); my $rdns = $dn->decode($pdu); my @dn; foreach my $a (@{$rdns->{rdns}}) { my $b = $rdn->decode($a); my @rdn; foreach my $c (@{$b->{rdn}}) { my $d = $ava->decode($c); my $s = $oid2attr{$d->{type}}; my $v = $d->{p} || $d->{t} || $d->{b} || $d->{u} || $d->{i} || die "Not a recognized syntax!"; $v =~ s/([+,=\\\$])/sprintf("\\%02X", ord($1))/eg; push @rdn, "$s=$v"; } unshift @dn, join("+", @rdn); } return join(", ", @dn); } This won't work for all attributes and syntaxes, but it should be OK for the commonly used ones. Cheers, Chris |