/*
 * Vernash v0.1
 * Coded by Shen139  07-02-2006
 *    shen139 (at_) eviltime [.dot.] com
 *
 * Stream chiper based on the Vernam cipher and Variable Length Hashes
 *
 * Compile with: $ gcc vernash.c -o vernash
 *
 * Usage for encrypting a text:  ./vernash <text> <password>
 *  or
 * Usage for generating an Hash: ./vernash -g <text> <length>
 *
 */

/* UnComment the following line to enable debugs */
//#define DEBUG

/*
 * Hashes
 *
aa   xehocwxedanmfahummikawdohycvbesqowwmwfycaaoptpiony
bb   ldhqhgzjzgnzlmculdzkqmxkbatkhczmtbzyvzosxywinbuggj
ab   dubqjabkvcltfujcjofapxuoicngxofubafcqypwbzziavxajb
ba   cykojmhyeodmuimhtgrpfwduyykwhmfwurlylxanfqbsthtsag
aba  xeyschfskiaeuszolynurfxeegkvnfjspjzjoyvypdlinhtagp
baa  ltwxtegphmyoxmlqsiugydzqtypalubyrighraqzlajcooklgq
 *
 */

/*
 * Vernash Test
 *
Text:           ---hello world! I'm Shen139---
Password:       ---1pz3zw9---

oqzshqscukijevnohgbpgego
hello world! I'm Shen139  +
vu' v0+q(vl*$^4{'Yitt59G  =

oqzshqscukijevnohgbpgego
vu' v0+q(vl*$^4{'Yitt59G  -
hello world! I'm Shen139  =
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


char RotCharUp(unsigned int value, char lBound, char rBound)
{
    while(value>rBound)
        value=(unsigned int)lBound + (value-rBound-1);

return (char)value;
}

char RotCharDown(int value, char lBound, char rBound)
{
    while(value<lBound)
        value=(unsigned int)rBound - (lBound-value-1);

return (char)value;
}

int avgDispersion(char* text)
{
int c;
int textLen=strlen(text);
int avg=0;

    for(c=0;c<textLen;c++)
        if(c)
            avg += (text[c]>text[c-1]) ? text[c]-text[c-1] : text[c-1]-text[c];

    if(c)
        avg /= textLen;

return avg+1;
}

int charWSum(char* text)
{
int c;
int textLen = strlen(text);
int sum = 0;
    
    for(c=0;c<textLen;c++)
		if(sum > 0xABC)
			sum = sum - ((text[c] * ((c*10)%0x10)) % 0xABC);
		else
			sum += text[c] * ((c*10)%0x12);

return sum;
}

char* hashum(char* word, int length)
{
int wordLen = strlen(word);
char* hash = (char*)malloc(length+1);

int i;
unsigned int curC=0;

    if(hash == NULL || wordLen<1)
        return NULL;

    hash[0]='\0';

    for(i=0;i<length;i++)
    {
        if(i==0)
            curC = wordLen + avgDispersion(word) + charWSum(word);
        else
            curC = i + avgDispersion(hash) + charWSum(hash) + word[i%wordLen] + (wordLen^i);
       
        curC += 'a' ;
        curC = RotCharUp(curC,'a','z');
        
        hash[i]=hash[curC%(i+1)];
        hash[curC%(i+1)]=curC;
        hash[i+1]='\0';
    }
return hash;
}

char* vernash(char* text, char* key)
{
int textLen = strlen(text);
char* hashKey;
char* crtText;
int i;

    if(text==NULL)
        return NULL;

    crtText = (char*)malloc(textLen);
    hashKey = hashum(key, textLen);

    if(crtText==NULL || hashKey==NULL)
        return NULL;

    for(i=0; i<textLen;i++)
        crtText[i] = RotCharUp( 'a' + (hashKey[i]-'a') + (text[i]-'a') ,' ','}' );

    crtText[i]='\0';

#ifdef DEBUG
	printf("\nC:\n%s\n%s  +\n",hashKey,text);
    printf("%s  =\n\n",crtText);
#endif

    free(hashKey);
return crtText;
}

char* unVernash(char* text, char* key)
{
int textLen = strlen(text);
char* hashKey;
char* crtText;
int i;

    if(text==NULL)
        return NULL;

    crtText = (char*)malloc(textLen);
    hashKey = hashum(key, textLen);

    if(crtText==NULL || hashKey==NULL)
        return NULL;

    for(i=0; i<textLen;i++)
        crtText[i] = RotCharDown( 'a' + (text[i]-'a') - (hashKey[i]-'a') ,' ','}' );

    crtText[i]='\0';

#ifdef DEBUG
	    printf("\nD:\n%s\n%s  -\n",hashKey,text);
        printf("%s  =\n\n",crtText);
#endif

    free(hashKey);
return crtText;
}

int main(int argc, char* argv[])
{
char* encryptedText;
#ifdef DEBUG
    printf("aa   %s\n",hashum("aa",50));
    printf("bb   %s\n",hashum("bb",50));
    printf("ab   %s\n",hashum("ab",50));    
    printf("ba   %s\n",hashum("ba",50));
    printf("aba  %s\n",hashum("aba",50));
    printf("baa  %s\n",hashum("baa",50));

    unVernash(vernash("hello world! I'm Shen139","1pz3zw9"),"1pz3zw9");

    printf("\n============debug=========\n\n");
#endif
    
    if(argc==4 && strcmp(argv[1],"-g")==0)
    {
        printf("Hash(%s) for ---%s---:\n---%s---\n\n",argv[3], argv[2], hashum(argv[2],atoi(argv[3])) );
        return 1;
    }
    else
    if(argc!=3)
    {
        printf("Usage for encrypting a text: %s <text> <password>\n or\nUsage for generating an Hash: %s -g <text> <length>\n",argv[0],argv[0]);
        return 0;
    }

    printf("Text:           ---%s---\nPassword:       ---%s---\n",argv[1],argv[2]);

    encryptedText = vernash(argv[1], argv[2]);

    if( strcmp(unVernash(encryptedText, argv[2]) ,argv[1]) == 0 )
        printf("\nEncrypted-Text: ---%s---\n\n", encryptedText);
    else
        printf("\n (ERROR) :@# \n\n");

return 1;
}

/* EOF */


