#!/usr/bin/perl

###############################################################################
# File		: snsg.pm
# Contains	: Routine for generation of snow signatures.
#
# Author	: David Gümbel, david.guembel@gmx.de
# Note		: Plaintext read from STDIN
# License	: GNU GPL. http://www.gnu.org/licenses/licenses.html#GPL
###############################################################################



# Command line Options from Peter's Original:
#    WriteLn ('Valid options are:');
#    WriteLn (' --help     -h              output this help text and exit');
#    WriteLn (' --verbose  -v              tell verbosely what is happening');
#    WriteLn (' --decode   -d <passphrase> decode (default: encode)');
#    WriteLn (' --output   -o <file>       write output to <file> instead of stdout');
#    WriteLn (' --comment  -c <comment>    start with <comment>; default is "http://snsg.org "');
#    WriteLn (' --sep      -s              prepend a separator line containing "-- "');
#    WriteLn (' --cols     -C <columns>    set number of output columns; default is 72');
#    WriteLn (' --lines    -L <lines>      set number of output lines; default is 4');
#    WriteLn (' --max      -m              print maximum length of message to stderr');
#    WriteLn (' --nopad    -N              do not pad with random bytes (for debugging)');

package snsg;
use strict;
use GnuPG::Interface;
use IO::Handle;
use MIME::Base64;

#$main::static_sig_part= "http://snsg.org\n";

# command-line parameters
# not all implemented!
$main::help = 0;
$main::verbose = 0;
$main::decode = 0;
$main::output = "";
$main::comment = "http://snsg.org \n";
$main::sep = "";
$main::cols = 0;
$main::lines = 0;
$main::max = 0;
$main::nopad = 0;
$main::passphrase = "";


###############################################################################
# Procedure	: parse_params
# Purpose		: parse given command-line parameters
# Parameter	: List of all given params ($ARGV)
# Returns	:
# Comment	:
###############################################################################
sub parse_params
	{
	my @args = @_;
	my $k = 0;
	foreach my $i (0..((@args)-1))
		{
		if (($args[$i] eq "--help") or ($args[$i] eq "-h"))
			{
			$main::help = 1;
			}
		if (($args[$i] eq "--verbose") or ($args[$i] eq "-v"))
			{
			$main::verbose = 1;
			}
		if (($args[$i] eq "--decode") or ($args[$i] eq "-d"))
			{
			$main::decode = $args[$i+1];
			}
		if (($args[$i] eq "--output") or ($args[$i] eq "-o"))
			{
			$main::output = $args[$i+1];
			}
		if (($args[$i] eq "--comment") or ($args[$i] eq "-c"))
			{
			$main::comment = $args[$i+1];
			}
		if (($args[$i] eq "--sep") or ($args[$i] eq "-s"))
			{
			$main::sep = "-- \n";
			}
		if (($args[$i] eq "--cols") or ($args[$i] eq "-C"))
			{
			$main::cols = $args[$i+1];
			}
		if (($args[$i] eq "--lines") or ($args[$i] eq "-L"))
			{
			$main::lines = $args[$i+1];
			}
		if (($args[$i] eq "--max") or ($args[$i] eq "-m"))
			{
			$main::max = 1;
			}
		if (($args[$i] eq "--nopad") or ($args[$i] eq "-N"))
			{
			$main::nopad = 1;
			}
		if (($args[$i] eq "--pass") or ($args[$i] eq "-p"))
			{
			$main::passphrase = $args[$i+1];
			}
		}
	}



###############################################################################
# Procedure	: print_help_text
# Purpose		: print  --help text
# Parameter	:
# Returns	:
# Comment	:
###############################################################################
sub print_help_text
	{
print <<DONE
Snowsig-Perl 0.2.1 - Copyright (C) 2001 David Gümbel <david.guembel\@gmx.de>
This program is free software under the GNU General Public License.
Based on an idea by Peter Gerwinski.

Usage: echo "some text" | snsg.pl [Options] 		or
       echo | snsg.pl
Valid options are:
 --help     -h              output this help text and exit
 --pass	    -p		    passphrase (optional for encryption)
 --decode   -d 		    decode (default: encode)
 --output   -o <file>       write output to <file> instead of stdout
 --comment  -c <comment>    start with <comment>; default is "http://snsg.org "
 --sep      -s              prepend a separator line containing "-- "
DONE
	}


###############################################################################
# Procedure	: reset_params
# Purpose		: reset command-line-parameters (or better: their corresponding
#		  variables) back to original values.
# Parameter	:
# Returns	:
# Comment	:
###############################################################################
sub reset_params
	{

	$main::help = 0;
	$main::verbose = 0;
	$main::decode = 0;
	$main::output = "";
	$main::comment = "http://snsg.org \n";
	$main::sep = "";
	$main::cols = 0;
	$main::lines = 0;
	$main::max = 0;
	$main::nopad = 0;
	$main::passphrase = "";
	}

###############################################################################
# Procedure	: generate_sig
# Purpose		: Generate a snow-Signature
# Parameter	: (optonal) Plaintext to be encrypted
# Returns	: Ciphertext, Base64-coded, prepended by
#		  $main::sep. $main::comment
# Comment	:
###############################################################################
sub generate_sig
	{
	my $message = $_[0];
	my $passphrase = $_[1];
	my $input   = IO::Handle->new();
      	my $output  = IO::Handle->new();
	my $status  = IO::Handle->new();
	my $err	    = IO::Handle->new();
	my $logger  = IO::Handle->new();
	my $passphrase_fh = IO::Handle->new();

	my $result = "";

	# Use random number as passphrase if none given
	if ($passphrase eq "")
		{
		$passphrase = int(rand(60000));
		}

	# if no plaintext given, use random number
	if ($message eq "")
		{
		$message = int(rand(63000));
		}

	# create GPG-Object and connet it to handles:
	my $gnupg = GnuPG::Interface->new();
	#$gnupg->options->hash_init( armor   => 1,
				    #meta_interactive( 0 ),
	#			    );
	my $handles = GnuPG::Handles->new( stdin  => $input,
                                         stdout => $output,
					 status => $status,
					 stderr => $err,
					 logger => $logger,
					 passphrase => $passphrase_fh,
					 );

	my $pid = $gnupg->encrypt_symmetrically(handles => $handles);
	print $input $message;
	close $input;

	print $passphrase_fh $passphrase;
  	close $passphrase_fh;

	while (<$output>)
		{
		$result .= $_;
		}

	close $output;
  	waitpid $pid, 0;

	$result = encode_base64($result);
	$output = $main::sep. $main::comment . $result;
	return $output;
	}

###############################################################################
# Procedure	: decode_sig
# Purpose		: decrypt a snow-Signature
# Parameter	: ciphertext to be decrypted
# Returns	: plaintext
#		  $main::sep. $main::comment
# Comment	:
###############################################################################
sub decode_sig
	{
	my $message = $_[0];

	if ($message eq "")
		{
		return "Error: no message for decryption given!\n";
		}
		# now remove "-- \n" and "http://snsg.org[\s]*[\n]?":
	$message =~ s/-- \n//;
	$message =~ s/http:\/\/snsg\.org\s*\n?//;
	$message = decode_base64($message);

	my $passphrase = $_[1];
	# return error if no passphrade given
	if ($passphrase eq "")
		{
		return "Error: No passphrase for decryption given!\n";
		}

	my $input   = IO::Handle->new();
      	my $output  = IO::Handle->new();
	my $status  = IO::Handle->new();
	my $err	    = IO::Handle->new();
	my $logger  = IO::Handle->new();
	my $passphrase_fh = IO::Handle->new();

	my $result = "";


	# create GPG-Object and connet it to handles:
	my $gnupg = GnuPG::Interface->new();
	#$gnupg->options->hash_init( armor   => 1,
				    #meta_interactive( 0 ),
	#			    );
	my $handles = GnuPG::Handles->new( stdin  => $input,
                                         stdout => $output,
					 status => $status,
					 stderr => $err,
					 logger => $logger,
					 passphrase => $passphrase_fh,
					 );

	my $pid = $gnupg->decrypt(handles => $handles);
	print $input $message;
	close $input;

	print $passphrase_fh $passphrase;
  	close $passphrase_fh;

	while (<$output>)
		{
		$result .= $_;
		}

	close $output;
  	waitpid $pid, 0;
	$output = $result;
	return $output;
	}
1;

