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;

my \$md5_hex = Digest::MD5->new;

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;

my \$md5_hex = Digest::MD5->new;

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