#!/usr/bin/perl -w

use Getopt::Std;
use Crypt::ECB;

use strict;

my $usage = "
Usage: ecb.pl [-d] [-c <cipher>] [-p <padding>] [-k <key>] [-f <keyfile>]
    or ecb.pl -l

Encrypt/decrypt files using ECB mode. Reads from STDIN, writes to STDOUT.

Options:
  -l		list available ciphers
  -d		decrypt (default mode is encrypt)
  -k <key>	key to use
  -f <keyfile>	file containing key; either -k or -f must be specified
  -c <cipher>	block cipher to use, defaults to 'Rijndael' (AES)
  -p <padding>	padding mode to use, possible values are 'standard' (default),
		'zeroes', 'oneandzeroes', 'rijndael_compat', 'null', 'space'
		and 'none'. See Crypt::ECB for details on the different modes.
";

my $options = {}; getopts('ldc:p:k:f:', $options) || die $usage;

list_ciphers(), exit(0) if $options->{l};

die $usage unless $options->{k} or $options->{f};

my $key		= $options->{k} || get_key($options->{f});
my $cipher	= $options->{c} || 'Rijndael';	# AES
my $padding	= $options->{p} || 'standard';

my $ecb = Crypt::ECB->new(-key => $key,	-cipher	=> $cipher, -padding => $padding);

my $decrypt = $options->{'d'};
$ecb->start($decrypt ? 'decrypt' : 'encrypt');

print $ecb->crypt while read(STDIN, $_, 1024);
print $ecb->finish;

exit(0);


sub get_key
{
	my $file = shift;

	open(F, $file) || die "Couldn't open '$file': $!\n";
	local $/;
	my $key = <F>;
	close F;

	return $key;
}


sub list_ciphers
{
	print "Checking your perl installation for block ciphers compliant with Crypt::ECB...\n";

	my ($ecb, $ok) = (Crypt::ECB->new, 0);

	close STDERR;

	foreach my $path (@INC)
	{
		while (<$path/Crypt/*.pm>)
		{
			s|^.*Crypt/||;
			s|\.pm$||;
			eval { $ecb->cipher($_) };
			printf(" found %-15s (keysize: %2s, blocksize: %2s)\n", $_, $ecb->keysize, $ecb->blocksize)
				if !$@ and ++$ok;
		}
	}

	unless ($ok)
	{
		print "There do not seem to be any block ciphers installed (at least none which I can\n"
		    . "use). Crypt::ECB will not be of any use to you unless you install some suitable\n"
		    . "cipher module(s).\n";
	}
}