• Google+
  • Twitter
  • YouTube
  • RSS
  • Facebook

Perl Base64 — How To Do Base64 Encoding in Perl

You can do base64 encoding in Perl using the MIME::Base64 module.

For those who don’t know, base64 is a way of encoding binary data in ASCII characters; so you can email your favorite program as text, if you want to (you’d have to be mad to want to do that, but sometimes it’s useful).

The following program encodes a simple string, then decodes it again. Note that encode_base64() adds a newline to the data when it encodes. This is part of the encoding — don’t remove it.

use strict;
use warnings;

use MIME::Base64;

sub main {
	my $text = 
            "We want the finest wines available to humanity.";
	
	print "Original text: $textn";

	$text = encode_base64($text);
	print "Encoded text: $textn";
	
	$text = decode_base64($text);
	print "Original text again: $textn";
}

main();
Original text: We want the finest wines available to humanity.
Encoded text: V2Ugd2FudCB0aGUgZmluZXN0IHdpbmVzIGF2YWlsYWJsZSB0byBodW1hbml0eS4=

Original text again: We want the finest wines available to humanity.

Base64 Encoding in Perl: A More Useful Example

Let’s take a look at a complete program that allows you to specify files to encode or decode on the command line. As a test, we’ll encode the program “text.exe”, then recode it again and run it to prove it still works!

C:>test.exe
Hello
use strict;
use warnings;

use MIME::Base64;
use Getopt::Std;

sub usage {
my $usage = q{

Encodes or decodes base64 files to or from binary files.
usage: 
	code64.pl [-d|-e] <input file> [-o] 
	
examples:

	decoding:
	code64.pl -d temp.txt -o out.txt
	
	encoding:
	code64.pl -e temp.txt -o out.txt
};

	return $usage;
}

sub main {
	my %opts;
	
	# Get command-line options. We want the user
	# to specify an input file (either for encoding
	# or decoding) and an output file.
	getopts('e:d:o:', %opts);
	
	# User must enter either -e  or
	# -d 
	unless($opts{e} or $opts{d}) {
		print "nNo input file specifiedn";
		die usage();
	}
	
	# User must specify -o  and hasn't.
	unless($opts{o}) {
		die "nNo output file specifiedn";
	}
	
	# Now we've got an output file name.
	my $output = $opts{o};
	
	# The input file name is after -e or -d.
	my $input = $opts{e} || $opts{d};
	
	# Open the input file.
	unless(open INPUT, $input) {
		die "nUnable to open input file '$input'n";
	}
	
	unless(open OUTPUT, '>'.$output) {
		die "nUnable to create output file '$output'n";
	}
	
	# Stop text mode mangling our files.
	binmode INPUT;
	binmode OUTPUT;
	
	# Undef the file record separator so we can read the
	# whole thing in one go.
	undef $/;
	
	# Read the input file.
	my $contents = <INPUT>;
	
	# Create the output file, encoding or decoding as
	# specified by the user.
	if($opts{e}) {
		print OUTPUT encode_base64($contents);
		print "Encoded '$input'; results in '$output'n";
	}
	elsif($opts{d}) {
		print OUTPUT decode_base64($contents);
		print "Decoded '$input'; results in '$output'n";
	}
	
	close INPUT;
	close OUTPUT;
}

main();

Encode the .exe to out.txt:

C:>test.pl -e test.exe -o out.txt
Encoded 'test.exe'; results in 'out.txt'

out.txt now contains a load of seemingly-random text, which you could send in an email if you were insane (or if, say, your company email policy forbids the sending of executables via email, but you really need to send one anyway).

Decode out.txt to out.exe:

C:>test.pl -d out.txt -o out.exe
Decoded 'out.txt'; results in 'out.exe'

Finally, run out.exe to prove it works:

C:>out.exe
Hello