/* This code is released into the public domain under the GNU Public
        License. The MD5 and SHS routines retain the rights of their
        respective authors.

        This code was written by Michael Graffam (mgraffam@mhv.net).
        It is pretty dirty, but shows the basics of implementing a
        deniable encryption system based on Ron Rivest's
        chaffing/winnowing concept.
*/               

#include <stdio.h>
#include <stdlib.h>
#include "shs.h"
#include "md5.h"

void help(void);
int wino(char hash, char *passphrase, int i, char *filename);
int main(int argc, char **argv)
{
	int i;
	char hash_function = 's';
	char filename[256] = "";
	char passphrase[1024] = "";
	FILE *fp;

	for (i=1; i<=argc-1; i++)
	{
		if ( argv[i][0]=='-' )
		{
			switch (argv[i][1])
			{
				case 'h':
					if ( (argv[i][2]=='s') || (argv[i][2]=='5') )
						hash_function=argv[i][2];
					break;
				case 'a':
					strcpy(passphrase,argv[i+1]);
					break;
				case 'f':
					strcpy(filename,argv[i+1]);
					break;
				default:
					fprintf(stderr,"Bad option: %s\n", argv[i]);
					help();
					return -1;
			}
		}
	} /* end parsing of option */
	if (passphrase[0]==0)
	{
		fprintf(stderr,"Requires passphrase.\n");
		help();
		return 0;
	}
	else
	i = strlen(passphrase);
	wino(hash_function, passphrase, i, filename);
} /* end of main */
void help(void)
{
	fprintf(stderr,"Valid options:\n");
	fprintf(stderr,"     -hN             selects hash to use (s = SHA, 5 = MD5). Default: SHA\n");
	fprintf(stderr,"     -a phrase       Defines passphrase when using valid MACs\n");
	fprintf(stderr,"     -f filename     Defines the input file to use.\n");
	fprintf(stderr,"                     Default: none.\n");
	fprintf(stderr,"     Input is from stdin or a file, Output is always stdout.\n\n");
	fprintf(stderr,"Example: wino -hs -a password -f secret.field > secret.txt \n");
	fprintf(stderr,"This will use SHA  with 'password' as the MAC phrase.\n");
	fprintf(stderr,"secret.txt  will get decoded from secret.field\n");
 }
int wino(char hash, char *passphrase, int passlen, char *filename)
{
	int i,j,k;
	unsigned long seq = 1;
	char *buffer;
	char *buffer1;
	int hashsize;
#define blocksize 1
	SHS_INFO shsInfo; /* data for SHA */
	MD5_CTX  md5Info; /* data for MD5 */
	char hash_digest[20] = "";

	if ( hash=='s' )
		hashsize=20; /* SHA hash size = 160 bits */
	if ( hash=='5' )
		hashsize=16; /* MD5 hash size = 128 bits */

	buffer=(char *)malloc(blocksize+hashsize+sizeof(long));
	buffer1=(char *)malloc(blocksize+hashsize+sizeof(long)+passlen);
	while ( (i=fread(buffer, 1, blocksize+hashsize, stdin)) )
	{
		memcpy(buffer1,buffer,blocksize);
		memcpy(buffer1+blocksize, passphrase, passlen);
		memcpy(buffer1+blocksize+passlen, &seq, sizeof(long));
		if (hash=='s') {
			shsInit(&shsInfo); 
			shsUpdate(&shsInfo, buffer1, passlen+blocksize+sizeof(long));
			shsFinal(&shsInfo);
			memcpy(hash_digest, shsInfo.digest, hashsize);
		} else {
			MD5Init(&md5Info);
			MD5Update(&md5Info, buffer1, passlen+blocksize+sizeof(long));
			MD5Final(&md5Info);
			memcpy(hash_digest, md5Info.digest, hashsize);
		}
 		if ( (memcmp(buffer+blocksize, hash_digest, hashsize) == 0 ))
		{
			fwrite(buffer,1,1,stdout);
			seq++;
		}

/*		printf("\n");
		fwrite(hash_digest,1,hashsize,stdout);
		printf("\n");
		fwrite(buffer+1, 1,hashsize,stdout);
		printf("\n");
*/		
	}
	free(buffer);
	free(buffer1);
}
