Subject: | URL::Encode is not utf8 binary 'clean' |
Encoding binary data via url_encode_utf8 and then decoding via url_decode_utf8 does not yield identical data (very subtly different)
I will concede this is a non-typical usage of URL::Encode
but I thought you would appreciate the knowledge that there is
some subtle issue with url_encode_utf8/url_decode_utf8
The script I attached has 3 test:
test 1:
- creates a binary string using Crypt::OpenSSL::RSA to encrypt a string.
- use hex_encode/hex_decode
- decrypt string: success
test 2:
- use original binary string
- use url_encode_utf8 / url_decode_utf8
- decrypt string: failure
test 3:
- use decoded string from test 2
- encode decode again, but using hex_encode / hex_decode
- decrypt string: success
Subject: | gen.pl |
#!/usr/bin/env perl
use strict;
use Crypt::OpenSSL::RSA;
use URL::Encode qw(:all);
my $rsa = Crypt::OpenSSL::RSA->generate_key(1024);
my $private_string = $rsa->get_private_key_string();
my $public_string = $rsa->get_public_key_x509_string();
my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($private_string);
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($public_string);
$rsa_priv->use_pkcs1_padding();
$rsa_pub->use_pkcs1_padding();
my $plaintext0 = 'a' x 117;
my $encrypted = $rsa_pub->encrypt($plaintext0);
my $encoded1 = hex_encode($encrypted);
my $decoded1 = hex_decode($encoded1);
if ($encrypted ne $decoded1) {
die "Encode1/decode1 failed\n";
}
my $plaintext1;
eval {
$plaintext1 = $rsa_priv->decrypt($decoded1);
};
if ($plaintext0 eq $plaintext1) {
print "\nEncrypted,encoded1/decoded1,decryped correctly\n\n";
} else {
print "\nEncrypted,encoded1/decoded1,decryped failed\n\n";
}
my $encoded2 = url_encode_utf8($encrypted);
my $decoded2 = url_decode_utf8($encoded2);
if ($encrypted ne $decoded2) {
die "Encode2/decode2 failed\n";
}
my $plaintext2;
eval {
$plaintext2 = $rsa_priv->decrypt($decoded2);
};
if ($plaintext0 eq $plaintext2) {
print "\nEncrypted,encoded2/decoded2,decryped correctly\n\n";
} else {
print "\nEncrypted,encoded2/decoded2,decryped failed\n\n";
}
my $encoded3 = hex_encode($decoded2);
my $decoded3 = hex_decode($encoded3);
my $plaintext3;
eval {
$plaintext3 = $rsa_priv->decrypt($decoded3);
};
if ($plaintext0 eq $plaintext3) {
print "\nEncrypted,encoded3/decoded3,decryped correctly\n\n";
} else {
print "\nEncrypted,encoded3/decoded3,decryped failed\n\n";
}
sub hex_encode {
my $input = shift;
my @bytes;
foreach my $i (0 .. (length($input) - 1)) {
my $byte = sprintf('%02x', ord(substr($input, $i, 1)));
push(@bytes, $byte);
}
my $output = join(qw{}, @bytes);
return $output;
}
sub hex_decode {
my $input = shift;
my @hex = ($input =~ /(..)/g);
my @dec = map({ hex($_) } @hex);
my @bytes = map({ pack('C', $_) } @dec);
my $output = join(q{},@bytes);
return $output;
}