droopycom has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I have the following ASN.1 grammar:

SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING }
When I do a decode my pem file with this, the BIT STRING seems to be stored as an array (or ref to array) with 2 elements, but I cant figure out what those two elements are really containing...

Any idea ?

Thanks.

Update --- Ok I figured it out:

A BIT STRING is stored as an array with two elements.
- The first element contain the bit strings data
- The second element contain the bit string length

When encoding a bitstring, using Convert::ASN1::encode, you can specify it two ways (at least)

$asn->prepare(q< str BIT STRING >) # Method1: length is multiple of 8 $asn->encode(str => "UU"); # Method2: length is explicit $asn->encode(str => ["UU", 12]);
The first call will encode the bitstring "0101010101010101" (16 bits)
The second call will encode the bitstring "010101010101" (12 bits)

Replies are listed 'Best First'.
Re: Convert::PEM and BIT STRING
by zentara (Cardinal) on Sep 19, 2008 at 20:01 UTC
    Hi, yeah I see your problem, you can get the BIT STRING but it is unknowable, as to what it is. I didn't have your key, so I had to make my own. I don't know how to use the BIT STRING instead of the keys. Here is a simple example that shows how dereferencing works
    #!/usr/bin/perl use warnings; use strict; use Crypt::DSA; use Crypt::DSA::Key; my $dsa = Crypt::DSA->new; my $key = $dsa->keygen(Size => 512, Verbosity => 1); printf "Public key: %s\n", $key->pub_key; my $pem = $key->write( Type => 'PEM', Filename => 'zsave1'); print "pem-> $pem\n"; #show that the file saved as private key contains all #information my $pem1 = Convert::PEM->new( Name => "DSA PRIVATE KEY", ASN => qq( DSAPrivateKey SEQUENCE { version INTEGER, p INTEGER, q INTEGER, g INTEGER, pub_key INTEGER, priv_key INTEGER } )); my $pkey = $pem1->read( Filename => 'zsave1' ); my %deref = %$pkey; for(keys(%deref)) {print "\n$_: $deref{$_}\n"} print "\n"; my %d = %{$deref{DSAPrivateKey}}; for (keys(%d)) {print "$_ : $d{$_}\n"} __END__

    I had a key_pub and key_priv pair that test with, and ran your script on it

    #!/usr/bin/perl -w use Data::Dumper; use Convert::PEM; my $pem = Convert::PEM->new( Name => "PUBLIC KEY", ASN => qq( AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } )) or die "New failed: ", Convert::PEM->errstr; my $key = $pem->read(Filename => "key_pub") or die "Decryption failed: ", $pem->errstr; my $aref; my %deref = %$key; for(keys(%deref)) {print "\n$_: $deref{$_}\n"; $aref = $deref{$_}; } print "$aref\n"; print @$aref,"\n"; __END__
    It gives me the same BIT STRING, but I don't know what it is. Googling for "subjectPublicKey BIT STRING " gives some details. My best guess is that you will have to read something like X.509 specs, and figure out the BIT STRING structure, then unpack the binary data we see in the dumps.

    Sorry I can't help more. BIT STRING isn't even mentioned in Convert::PEM. It is mentioned in Crypt-DSA-0.13/lib/Crypt/DSA/Key/Pem.pm. I think you will need to figure out what special type of BIT STRING it is, then unpack accordingly.

    By the way, where are you getting the public key you are testing from? Is it off of a Blackberry, or something? Add "blackberry" to the search string above and get it's structure.


    I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: Convert::PEM and BIT STRING
by zentara (Cardinal) on Sep 19, 2008 at 18:12 UTC
    Use DataDumper on it? Do you have a working minimal example?

    I'm not really a human, but I play one on earth Remember How Lucky You Are
      I can dump the data, but it doesnt really help me figuring out how a ASN.1 bitstring is stored in a perl variable.

      The minimal example (The "key.pem.pub" file is the public part of an RSA key generated by openssl genrsa).

      #!/usr/bin/perl -w use Data::Dumper; use Convert::PEM; my $pem = Convert::PEM->new( Name => "PUBLIC KEY", ASN => qq( AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } )) or die "New failed: ", Convert::PEM->errstr; my $key = $pem->read(Filename => "key.pem.pub") or die "Decryption failed: ", $pem->errstr; print "$key->{algorithm}\n"; print "$key->{subjectPublicKey}\n"; print Dumper($key->{subjectPublicKey});
      The output is (as seen in vi) not very pretty :
      HASH(0x9745798) ARRAY(0x97457a8) $VAR1 = [ '0<82>^A^H^B<82>^A^A^@²tº]u<9b>|M?)^?Ræ<9c>Úö)B<86>úçh<99>< +94>ñ7^P«®Êð<83>r^XßNϵd<86>D^K^V^Bý^A^G AÿÒN©<99>ï¨:<9b><94>^^k <85>xö4*%ÿ§^Sö<91>º"<83> a^S<82>Ö³[u.×Ù<86>FQ<82>ËN^F#ê<9b>·¼Ô0^\iºÍCt¡ý<8f>õë!4Wc<95> Àêá÷^W +7>åé<  ^SùD^\*¤<96>Ñ^¯<92>Á^_«Ö1RZ<81>^N^Q<82><83> ^A!^O^A^QÙz}Ù°ï< ï¼<9e>ä^XZu1r^Wæ^_ç¡ê¼<94>]^F<83>éûvô<8c>¸ùüý<99>fÿ\\7v<83>Ù<91><89>8< +96>~<96>b<8e>ßÞ$;r<91>Ê4ßÞ\'̲)þ^Fl~õ]Êá]`20ý^?^^¿.!òzy0<9a>^L<90><80 +><9f>e<9b>^B^A#', 2144 ];
      The BIT STRING is supposed to be the DER encoding of some other ASN.1 structure.

      Thank you.