From xs4all!xs4all!news.unisource.nl!surfnet.nl!howland.erols.net!newsfeed.internetmci.com!flesh.fly.net!anon.lcs.mit.edu!nym.alias.net!mail2news Mon Aug 26 22:21:11 1996
Path: xs4all!xs4all!news.unisource.nl!surfnet.nl!howland.erols.net!newsfeed.internetmci.com!flesh.fly.net!anon.lcs.mit.edu!nym.alias.net!mail2news
Date: Sat, 24 Aug 1996 13:37:00 -0700
Message-ID: <199608242037.NAA22799@abraham.cs.berkeley.edu>
From: nobody@cypherpunks.ca (John Anonymous MacDonald)
Comments: There is no way to determine the originator of this message.
	If you wish to be blocked from receiving all anonymous mail, send
	your request to the <remailer-operators@c2.org> mailing list.
	The operator of this particular remailer can be reached at
	<remailer-admin@cypherpunks.ca>.
Newsgroups: alt.privacy.anon-server
Subject: REPLY block generator in perl
Mail-To-News-Contact: admin@nym.alias.net
Organization: mail2news@nym.alias.net
Lines: 334



I needed a reply block generator. There was none available 
(though you can set Raph's premail to use a storefile and kinda
hot wire it to make reply blocks), so I wrote one in perl.

Anywhere, it's 250 lines of perl.  Either perl 4 or 5 should
work.  It seems to generate working blocks, though there's no
guarantee that it will work for all remailers.

It's reasonably friendly, because it will lead you 
through the block generation process.

You need to use the explicit email address of the remailer.
You can't use just the short name.  All remailers'
keys must be in your pgp pubring.  

This program is hereby forthwich howevermuchly and all that legalese
placed into the public domain. Use it however you want.  If people
find it useful, it would be nice if someone put it in an ftp site, and
made a note of it in some remailer web page. (Raph? are you there?)

To run it, just save it as (for example) "make_rep_block", change
the first line to point to your copy of perl, change the
PGP_PROG line if necessary, "chmod +x make_rep_block", and
just run "make_rep_block"  and follow the prompts.

======= perl reply block generator =========
#!/usr/bin/perl
# --*-perl-*--

# FIX THE FIRST LINE TO REFLECT THE LOCATION OF PERL
#  (do "which perl" or "whereis perl")
########################################################
# set this variable to your pgp program; if it is in your
#  $path, it is ok as it stands
$PGP_PROG = "pgp";
#######################################################

# this program is free for any purpose whatsoever. 
# it is placed in the public domain and all that
.#
# perl is ugly ugly ugly. 
# 
.#
# don't bother criticizing the inelegance of this thing;
# it was a 3 hour hack job.
.#
# the user interface to pgp stinks.  very non-unixy.
# the more obscure commands aren't documented in
# the man page.  someone needs to rewrite it as
# a library, so it can be better integrated into 
# extension languages.
.#
# building reply blocks is annoying because different remailers
#  are sensitive to blank lines in different ways.  This
#  sticks a blank line just about everywhere, and seems to 
#  make functioning blocks.
.#
.#
# 
.#

print (stdout <<EOF);
This program creates a reply block suitable for use with a nym.
It will prompt you for a series of latent times (used with
the \"Latent-Time:\"  remailer header)  and conventional 
passwords (used with the \"Encrypt-Key:\" header).  NO SPACES
ARE ALLOWED IN ANY OF YOUR ENTRIES!!

You must supply all remailers as their full email addresses.  It will
not parse the short names like \"replay\" and \"lucifer\".  All
the remailers must be in your public ring. 

It will create a file with your reply block, and a description file
with all the latent times and passwords.  Keep the latter hidden away.

As it stands, the block will be suitable for the block that
sits at a nym (like alpha.c2.org or nym.alias.net).
If you want to use the block for email-replies, just clip out the
stuff above the \"::\" and tell respondents to send the block 
to the first remailer in the list.

=================================================
EOF


# takes a prompt, and a default value
sub prompt_for_input
.{
    local($prompt_string) = $_[0];
    local($default_string) = $_[1];
    local($ret_string)    = "";
    print(stdout "$prompt_string   [$default_string] > ");
    $ret_string = <stdin>;
    chop $ret_string;
    if ($ret_string eq "") {return $default_string} else {return $ret_string;}
.}
.	

# takes a pgp'ed input file, and adds email address/crypto layer
sub add_pgp_layer
.{
    local($keyname)      = @_[0];   # to pgp encrypt this step block, 
                                    #    if desired; else "" 
    local($destination)  = @_[1];   # email address of next stop 
    local($latent_time)  = @_[2];   # or "" 
    local($pass_phrase)  = @_[3];   # conventional pgp encryption, or "" 
    local($infile_name)  = @_[4];   # file name of extant block 
    local($outfile_name) = @_[5];   # file name that this complete 
                                    #   block will have, upon return 
    local($double_stars) = @_[6];   # 1 to put ** at end for conv encr
        
    open(outfile, ">$outfile_name");	
    # create/open outfile_tmp for read/write
    open(outfile_tmp, ">${outfile_name}.tmp"); close(outfile_tmp); 
    open(outfile_tmp, "+>${outfile_name}.tmp");
    
    print(outfile_tmp "::\nAnon-To: $destination\n");
    
    # if using passphrase or latent time, put in the appropriate headers
    if ($latent_time ne "") 
    { 
	print(outfile_tmp "Latent-Time: $latent_time\n"); 
    }    
. 
    if ($pass_phrase ne "") 
    { 
	print(outfile_tmp "Encrypt-Key: $pass_phrase\n");  
    }			

    # put in a blank line
    print(outfile_tmp "\n");

    # if there is a previous layer, open it and tack it onto end of 
    #     outfile_tmp
    if ($infile_name ne "") 
    { 
	if (open(infile,  "<$infile_name") != 1) 
	{
	    die("Couldn't open $infile_name in add_pgp_layer\n");
	}
	# and copy the files
	while (<infile>) {   print (outfile_tmp  "$_"); }
    }

    # mark start of conventional encryption (if used) with **
    #  note that we put a \n before it so a blankline separates the last 
    #  pgp'ed block from **
    if ( $double_stars==1) 
    {
	print(outfile_tmp "\n**\n\n");
    } 
   
    # if a pgp keyname exists, encrypt the new file
    if ($keyname ne "" )
    {
	close(outfile_tmp); 
	# build the pgp command string; pipe all to /dev/null
	#  we do this through a pipe so the name of the temp
	#  file doesn't end up in the pgp block (tricky, tricky...)
	local($PGP_COMMAND) =
	    " cat ${outfile_name}.tmp | ".  
	    "$PGP_PROG -feat +batchmode +force $keyname ".
	    "-o ${outfile_name}.tmp.asc > /dev/null 2>&1 ";
	`$PGP_COMMAND`;
	# die if errorcode = 1 or output file doesn't exist
	if ( $? == 1 || (! -f "${outfile_name}.tmp.asc" ))
	{ 
	    die "Failed to create pgp'd file ${outfile_name}.tmp.asc".
		" \n\tfrom ${outfile_name}.tmp in add_pgp_layer\n\t".
		"using key: $keyname\n\t".
		"Perhaps this key isn't in your pubring?\n\n";
	}
	# note TWO \n's 
	print(outfile "::\nEncrypted: PGP\n\n");
        
	# now copy the pgp'ed file ${outfile_name}.tmp.asc to the 
	#  normal outfile
	open(outfile_asc, "<${outfile_name}.tmp.asc");
	while (<outfile_asc>) {print(outfile "$_")};
    } else  # otherwise, copy the un-pgp'ed outfile.tmp to outfile
    {
	seek(outfile_tmp,0,0);
	while (<outfile_tmp>) {print(outfile "$_")};
	close(outfile_tmp); 
    }
.	
    
    # close and delete the temporary files	
    close(outfile_asc); close(outfile); close(infile);
    unlink( ("${outfile_name}.tmp.asc", "${outfile_name}.tmp") );
.	
}		


##########################################################
# ask user for inputs to build reply block
#########################################################
sub prompt_params
.{
    local($block_name) = 
	prompt_for_input("File name for response block","resp_block.asc");
    local($final_dest) = 
	prompt_for_input("Final destination           ","you\@your.place");
    local($nym_latent) = 
	prompt_for_input("Latent-Time at your nym (leave blank for none)","");
    local($nym_passwd) = 
	prompt_for_input("Encrypt-Key at your nym (leave blank for none)". "");
    local($done_remailers) = "XXX";
    local($remailer_count) = 0;
    local(@remailer_list)  = ("$final_dest");
    local(@remailer_pass)  = ("");
    local(@remailer_latent_time) = ("");
    # a base file name for making temp files 
    local($base_filename) = ".XXXcreate_resp_block"; 
    


    do
    {	   
	$remailer_count ++;
.	
	@remailer_list[$remailer_count]=
	    prompt_for_input("--> Full email address of remailer".
                             " #$remailer_count" , XXX);
	@remailer_pass[$remailer_count]=
	    prompt_for_input("--> Encrypt-Key for #$remailer_count".
			     " (leave blank for none)" , "");
	@remailer_latent_time[$remailer_count]=
	    prompt_for_input("--> Latent-Time for #$remailer_count".
			     " (leave blank for none)" , "");

	# ask if we want more remailers (Y/N)
	$done_remailers = "XXX" ;
	while ( !($done_remailers =~ /^Y/i ) && !($done_remailers =~ /^N/i ) )
	{
	    $done_remailers=prompt_for_input("Add more remailers to chain?",
					     "Y");
	}
       
	################################################################
	# encrypt one layer
	################################################################
	local($prev_index) = $remailer_count -1;
	local ($target_address) = $remailer_list[$prev_index];
	local ($pgp_keyname) = @remailer_list[$remailer_count] ;
	# if this is the first one, then there is no previous file 
	#   to incorporate
	local($last_file)="$base_filename"."$prev_index";
	if ($remailer_count == 1) {$last_file=""} ;
	# 
	add_pgp_layer($pgp_keyname ,  # PGP key of this remailer, or "" 
		                      # if outer layer
		      $target_address,     # your address, or next remailer
		      @remailer_latent_time[$remailer_count],
                      @remailer_pass[$remailer_count],
		      "$last_file",   # use the last file as a starting point
		      "$base_filename"."$remailer_count", #  name of next file
		      0);  # no ** for conv encr. until the end
	unlink("$base_filename"."$prev_index");            # wipe the last file
	################################################################
	################################################################
			

.	
    }  while ( $done_remailers =~ /^Y/i  );

    # and put on the final header that the nym machine sees
    local($target_address)=@remailer_list[$remailer_count];
    local($infilename)="$base_filename"."$remailer_count";
    local($outfilename)="$base_filename"."nym";
.	
    add_pgp_layer( "",		               # no encryption
		  $target_address,
		  $nym_latent,
		  $nym_passwd,
		  $infilename,
		  $outfilename,
		  1);       # put the ** in the block
    unlink($infilename);

    # and rename the final block
    rename($outfilename , $block_name );

    # open file and write out description of the chain
    open (chain_desc, ">$block_name.desc");
    print(chain_desc "Final destination:  $final_dest\n");
    print(chain_desc "Latent-Time at nym: $nym_latent\n");
    print(chain_desc "Encrypt-Key at nym: $nym_passwd\n\n");
.	
    print(chain_desc  
	  "Remailers ordered closest to furthest from destination\n\n");
    for ($i=1; $i<=$remailer_count; $i++)
    {	
	print(chain_desc 
	      "\nRemailer $i\n".
	      "    Name:                  $remailer_list[$i]\n".
	      "    Encrypt-Key:           $remailer_pass[$i]\n".
	      "    Latent-Time:           $remailer_latent_time[$i]\n");
    }
    close(chain_desc);
			    

.}

#######################################################
###### the main part of the program ###################
#######################################################

prompt_params();
exit;























