# the usual crc32 polynomial my $crc_poly = 0xedb88320; my $crc_size = 32; my $initial_str = "foo bar"; my $final_str = "baz blat"; my $desired_crc = 0x12345678; my $magic = forward_crc($initial_str, 0xffffffff) ^ reverse_crc("\0\0\0\0".$final_str, $desired_crc^0xffffffff); my $forged_str = $initial_str . pack("V",$magic) . $final_str; use String::CRC32; printf "%x\n", crc32($forged_str); # calculate an ordinary crc of $string, # given the initial register contents sub forward_crc { my ($str, $reg) = @_; foreach (split //, $str) { $reg ^= ord; for (1..8) { $reg = ($reg & 1) ? ($reg >> 1) ^ $crc_poly : $reg >> 1; } } return $reg; } # forward_crc # given the final register contents, calculate # what the register state was before $str sub reverse_crc { my ($str, $reg) = @_; my $poly = ($crc_poly << 1) ^ 1; my $highbit = 1 << ($crc_size - 1); foreach (reverse split //, $str) { for (1..8) { $reg = ($reg & $highbit) ? ($reg << 1) ^ $poly : $reg << 1; } $reg ^= ord; } return $reg; } # reverse_crc