http://qs321.pair.com?node_id=342951

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

All,

I have two applications, one which generates a checksum in base64, and another one which generates a checksum in hex base. (IE: Base64 contains characters 09Az+/ and the hex checksum only contains 09af and is a bit longer.) I want to be able to compare these two checksums from these applications. Is there a base64 to hex or vice versa? If there isn't one, I'll just write a quick code snipit which does this, but I thought I would ask first. (Did a quick check of both cpan and perlmonks and got null.)

Cheers

Update: Solution: Math::BaseCalc


----
Zak - the office

Replies are listed 'Best First'.
Re: base64 and hex question
by borisz (Canon) on Apr 06, 2004 at 15:26 UTC
    If your applications use the same logic to generate the checksum, there is no problem to compare them. Just convert one of them to the other. I prefer Math::BaseCalc for that.
    Boris
      borisz,
      This was the approach I was working on when I saw your post. Can you tell me what I am doing wrong?
      #!/usr/bin/perl use strict; use warnings; use Digest::MD5; use Math::BaseCalc; my $md5_b64 = Digest::MD5->new; $md5_b64->add( 'foo bar' ); my $md5_hex = Digest::MD5->new; $md5_hex->add( 'foo bar' ); my $b64_digest = $md5_b64->b64digest; my $hex_digest = $md5_hex->hexdigest; my $base_64 = new Math::BaseCalc ( digits => [ 'A' .. 'Z', 'a' .. 'z', 0 .. 9, '+' , '/' ] ); my $base_16 = new Math::BaseCalc ( digits => [ 0 .. 9, 'a' .. 'f' ] ); my $b64_string = $base_16->to_base( $base_64->from_base( $b64_digest + ) ); print "Base 64 : $b64_digest\n"; print "Hex : $hex_digest\n\n"; __END__ Base 64 : MntvB0NYESObxH4VRDUycw Hex : 327b6f07435811239bc47e1544353273 Converted : 327b6f074358120000000000000000000
      It doesn't seem to work correctly? L~R

      Update: After talking with tye in the CB, he seems to think that Math::BaseCalc expects the number being converted to fit into a double as well as an endian problem. He suggested using Math::Fleximal instead and I stumbled on to converting from b64 -> b16 to correct for the endian problem encountered going the other way.

      #!/usr/bin/perl use strict; use warnings; use Digest::MD5; use Math::Fleximal; my $md5_b64 = Digest::MD5->new; $md5_b64->add( 'foo bar' ); my $md5_hex = Digest::MD5->new; $md5_hex->add( 'foo bar' ); my $b64_digest = $md5_b64->b64digest; my $hex_digest = $md5_hex->hexdigest; my $b16_string = Math::Fleximal->new ( $b64_digest , [ 'A'..'Z', 'a'..'z', '0'..'9', '+', '/'] )->change_flex ( [ 0..9, 'a'..'f' ] )->to_str() ; print "Base 64 : $b64_digest\n"; print "Hex : $hex_digest\n\n"; print "Converted : ", substr($b16_string, 0, 32), "\n"; __END__ Base 64 : MntvB0NYESObxH4VRDUycw Hex : 327b6f07435811239bc47e1544353273 Converted : 327b6f07435811239bc47e1544353273
      You probably want to look into the endian problem further instead of just relying on it working from b64 -> b16 though.
        Hi Limbic~Region,
        Update: After talking with tye in the CB, he seems to think that Math::BaseCalc expects the number being converted to fit into a double as well as an endian problem. He suggested using Math::Fleximal instead and I stumbled on to converting from b64 -> b16 to correct for the endian problem encountered going the other way.
        You are right, it can only convert numbers that fit into a double ( the docs say into a perl integer ). $num = $calc->from_base(STRING) Im very happy that you find this misbehavior. Yesterday I finnished something that rely on the conversion from dec to base64. But only for positive numbers up to 2147483647.
        Boris
      This is the solution, I was looking for, thanks!


      ----
      Zak - the office

        Am I missing the something. Just convert the base 64 to hex. The only issue is endianness and you can ignore that if you feel 2**127 is sufficient complexity for the task

        use Digest::MD5 qw( md5_hex md5_base64 ); use MIME::Base64; my $string = 'Am I missing something?'; my $hex = md5_hex( $string ); my $b64 = md5_base64( $string ); print "hex: $hex\nb64: $b64\n"; my $bin = decode_base64( $b64 ); my $h1 = join '', unpack "H*", $bin; # high nybble first my $h2 = join '', unpack "h*", $bin; # low nybble first print "h1: $h1\nh2: $h2\n"; # loose one bit of complexity for portablity print "Checksums are the same!\n" if $h1 eq $hex or $h2 eq $hex; __DATA__ hex: 8a4d8b4fa3d19e4e5c0755123b57a109 b64: ik2LT6PRnk5cB1USO1ehCQ h1: 8a4d8b4fa3d19e4e5c0755123b57a109 h2: a8d4b8f43a1de9e4c5705521b3751a90 Checksums are the same!

        cheers

        tachyon

Re: base64 and hex question
by ambrus (Abbot) on Apr 06, 2004 at 18:18 UTC

    Read about this question in perldoc perlfaq9.

Re: base64 and hex question
by matija (Priest) on Apr 06, 2004 at 15:24 UTC
    pack/unpack does translations into UUENCODE codes, which are think are closed, but not identical to BASE64. printf/sprintf with a format of "%x" (or "%X") will output hexadecimal codes. I think your best bet would be to transfer both to integers (using the "hex" function for hex-to-integer convesrion) and compare the (bignum) integers.
Re: base64 and hex question
by atcroft (Abbot) on Apr 06, 2004 at 15:10 UTC