use 5.010; use strict; use Carp qw/croak/; use List::Util qw/max/; sub xor_strings { croak "should be passed two arguments" unless @_==2; state $chunk_size = 4; state $pattern = sprintf '%%0%dx', $chunk_size; # Make strings equal length, and a multiple of $chunk_size. my $length = max(map { length $_ } @_); $length += $chunk_size - ($length % $chunk_size); my @strings = map { ('0'x($length - length $_)) . $_ } @_; # Join results of each chunk return join q{}, map { # Parse chunk hex to an integer my $i = $_; my @nums = map { hex substr $_, $i*$chunk_size, $chunk_size } @strings; # Xor them and convert to hex. sprintf $pattern, $nums[0] ^ $nums[1] } 0 .. ($length/$chunk_size)-1; } say xor_strings( '112233112233112233112233112233112233112233112233112233', 'aabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc112233', );