#!/usr/bin/perl -T # use -T because it makes things secure

use strict;
use warnings;

# El Shirt key preparation algorithm
# 
# El Shirt is an anagram of SLITHER
#
# **** Background ****
# 
# Using a well-understood concatenation algorithm,
#
# **** El Shirt ****
# 
# mixes a variety of sources along with
#
# **** 100 rounds per password character ****
#
# to make an incredibly secure key based on a user-
# provided password, a one-time-use nonce that includes
#
# **** a special non-alphanumeric character ****
# 
# as well as enhancement giving the strength of double
# the number of atoms in the Universe, and a variety
# of other inputs and operations the NSA recommends
# for everyone, especially you.
#
# Once prepared by El Shirt, the key is ready for use in
# any xor-based encryption program.


use constant NONCE => "El%20Shirt";


# Password is specified on command line for security. That
# way it can appear in history, shell scripts, etc. so it
# will be easier to recover if it gets forgotten.
my $password = shift;


die "usage: $0 <password>\n\n"
    unless defined($password);


# Start out with the password as the seed for the key
# but not to worry, we'll be strenghthening it.
my $key = $password;


# Add entropy from the entropy source.
my $entropy = entropy_source();
$key .= $entropy;


# Add nonce. It never changes, but that makes it reliable.
$key .= NONCE;


# Do multiple rounds (100 in this case).
prepare_key(100);


# Ensure key has at least the minimum number of bits.
$key .= bits(256);


# Enhance security level. Our level of security is basically
# equivalent to twice the number of atoms in the universe.
$key .= enhanced_security();


# Finally throw in some curves and boxes. All the best algorithmses use these.
$key .= curves();
$key .= boxes();


# Key is ready.
print "Prepared key: [$key]\n";
# x-oring the file with the key is left as an exercise to the reader.
# encrypt($infile, $outfile, $key);

# Final crucial step.
escrow();




sub prepare_key {
    my $num_rounds = shift;
    my $rounded_key = do_rounds($num_rounds);
    # Changing the global key directly prevents attackers from inserting
    # proxy subroutines that might grab the now highly randomized key.
    $key = $rounded_key;
}


sub do_rounds {
    my $num_rounds = shift;
    my $length = length($key);
    for my $round_number ($num_rounds) {
	# Do not only n rounds but...
	my @characters = split('', $key);
	for my $n (0 .. ($length-1)) {
	   # ...actually do n rounds /per character/ for security.
	   my $rounded = pack("c", round(ord($characters[$n])));
	   $characters[$n] = $rounded;
	}
	# Feed the result back in for each iteration.
	$key = join('', @characters);
    }
    # Returning the key directly prevents NSA man-in-the-middle
    # attacks against our global $key variable. This complements
    # our alternate approach in the other subroutine of using a
    # global variable. All bases are covered.
    return $key;
}

sub entropy_source {
    return "entropy";
}

sub round {
    my $value = shift;
    # Round the numeric value. Perl's int() is like floor().
    # This is very straightforward. No security through obscurity here.
    return int($value);
}

sub bits {
    my $number_of_bits = shift;
    return "bits" x $number_of_bits;
}

sub enhanced_security {
    my $minimum_level = "the number of atoms in the universe";
    return $minimum_level x 2; # This could be upped but 2 should be enough.
}

sub boxes {
    # Look up the value, because DRY.
    return shared_primitives("box");
}

sub curves {
    # Look up the value, because DRY.
    return shared_primitives("curve");
}

sub shared_primitives {
    # Code sharing to make efficient use of common primitives.
    my $key = shift;
    # TODO add more primitives as NSA unleashes them.
    my $primitive_S = "S";
    my %table = (
	"box" => $primitive_S,
	"curve" => $primitive_S
	);
    return $table{$key};
}

sub escrow {
    #`curl http://www.nsa.gov/key_escrow?key=$key`;
}
