#!/usr/bin/perl use strict; use Data::Dumper; use constant _SECRET => 'V+ëþ$ u O+@pr!ñ à m0!,! $+'; # test data my %hash = ( "key1" => "1", "key2" => '"2"', "key3" => "3" ); # compact and expand test data my $data = mac_serialize->expand ( mac_serialize->compact ( \%hash ) ); for ( keys %{$data} ) { print "$_ => $data->{$_}\n"; } package mac_serialize; use strict; use Compress::Zlib; use MD5; sub compact { # Serialize data for safe storage on untrusted systems # pass a reference to a hash, returns a string # use expand to de-serialize into a reference to a hash my $self = shift; my $data = shift; my $output; map ( { s/"/\\"/g } %{$data} ); #" # serialize hash into a string $output = "{ " . join ( ", ", map ( { qq {"$_" => "$data->{$_}"} } keys ( %{$data} ) ) ) . " }"; # compress, hex (for ascii storage), and generate a mac (so we can trust the data later) return unpack ( "H*", compress ( $output ) ) . "::" . MD5->hexhash ( _SECRET.MD5->hexhash ( _SECRET.unpack ( "H*", compress ( $output ) ) ) ); } sub expand { # Deserialize strings created w/compact into a hash reference # pass the output from compact, receive a hash reference my $self = shift; my ($data, $mac)= split ( /::/, shift ); # check to see that the data has not been tampered with if ( MD5->hexhash ( _SECRET.MD5->hexhash ( _SECRET.$data ) ) eq $mac ) { # data is safe, eval to a hash return eval ( uncompress ( pack ( "H*", $data ) ) ); } else { # untrusted data, send back undef return undef; } }