/*
 *  0x333crypt <= MD5 & xor
 *
 *  process:
 *
 *  xor1 -> | mainkey in MD5 | 32 chars plain text readed by file
 *  xor2 -> | subkey1 in MD5 | 32 chars plain text readed by file
 *  xor3 -> | subkey2 in MD5 | 32 chars plain text readed by file
 *
 *  etc etc..
 *
 *  based on subkey generation in base a mainkey specified by user.
 *  key isn't written in file.
 *
 *  coded by nsn
 *
 *  developed and tested on linux slackware
 *  gcc -lssl source.c -o out
 *
 * ~ www.0x333.org ~
 *
 */

#include <stdio.h>
#include <openssl/md5.h>
#include <string.h>
#include <unistd.h>

/* constants, variables and prototipes */

#define VERSION "0.5"
#define PASSLEN 128

typedef enum {FALSE,TRUE} BOOLEAN;

static char *MDString(char *string); 
char xor(char, char); /* make xor between two chars and return result */
void help(char *); /* prints help for user. */
void gen(char *, char *, char *, BOOLEAN); 

char      *mainkey     = NULL; /* can be changed with option -k */
char      *infile      = NULL; /* can be changed with option -i */
char      *outfile     = NULL; /* can be changed with option -o */
BOOLEAN   operation    = TRUE; 

/* functions source codes */

char xor(char a, char b) { return a^b; }

static char 
*MDString (char *string) 
{
    static char ret[33]={"\0"}, hex[2];
    unsigned char digest[16];
    unsigned int len = strlen(string), i;
    MD5_CTX context;

        MD5_Init(&context);
        MD5_Update(&context, string, len);
        MD5_Final(digest, &context);

        for (i = 0; i < 16; ++i) {
           sprintf(hex,"%02x", digest[i]);
           strcat(ret,hex);
        }

return ret;
}

void
usage (char *prg)
{

   fprintf (stderr, "\n [~] 0x333crypt %s <= files with a key [~]\n",VERSION);
   fprintf (stderr, " [~]     coded by nsn of 0utSid3rs      [~]\n\n");
   fprintf (stderr, " Usage: %s [ -k password ] [-e/d ] [ -i infile ] [-o outfile] [ -h ]\n\n", prg);       
   fprintf (stderr, " \t-k   = key for encrypt/decrypt [ lentgh <= %d ]\n",PASSLEN);
   fprintf (stderr, " \t-e/d = operation encrypt/decrypt\n");
   fprintf (stderr, " \t-i   = infile\n");
   fprintf (stderr, " \t-o   = outfile\n");
   fprintf (stderr, " \t-h   = show this help\n\n");

   exit(-333);
}

void 
gen(char *infile, char *outfile, char *mainkey, BOOLEAN operation)
{
    FILE *instream = NULL, *outstream = NULL;
    unsigned long int subkeyscounter = 1;
    static char *hashMD5, tempkey[1024]={"\0"}, data[33]={"\0"}, byte;
    unsigned short int i = 0;
    size_t len;

        if (!(instream = fopen(infile,"rb")) || (!(outstream = fopen(outfile,"wb"))))
           printf("\n[*] error in opening %s or %s aborting!\n",infile,outfile);
        else {
   
           memset(data,0,sizeof(data));
           memset(tempkey,0,sizeof(tempkey));
           hashMD5 = (char *)alloca(sizeof(data)); 
           memset(hashMD5,0,sizeof(hashMD5));
                      
           printf("\n[*] reading data... wait pls\n\n");
       
           /* reading all chars of file */

           while ((len = fread(&data[i++], 1, 32,instream)))
           {
          
              strcpy(tempkey,mainkey);
              sprintf(tempkey,"%s%d",mainkey,subkeyscounter);
              hashMD5 = MDString(tempkey);
              ++subkeyscounter;    
              
               /* xor subkey and plain text i,j */
               
                for (i = 0; i < len; ++i)
                {
                
              byte = data[i];
                 
              if ((data[i] != hashMD5[i]) && (data[i] != 0))                       
              byte = ((operation) ? xor(hashMD5[i],data[i]) : xor(data[i],hashMD5[i]));
                      
              fwrite(&byte,1,1,outstream);
                }   
              i = 0;
              memset(data,0,sizeof(data));
              memset(tempkey,0,sizeof(tempkey));
              memset(hashMD5,0,sizeof(hashMD5));
            }                 
         printf("\n[*] work completed.\n[*] file generated with %d subkeys.\n",subkeyscounter);
         fclose(instream);
         fclose(outstream);
       }      
}

int
main (int argc, char **argv)
{
int c;

       while (( c = getopt (argc,argv,"edh:k:i:o:")) != EOF)
       {
          switch(c) 
          {
             case 'e' : operation = TRUE;break;
             case 'd' : operation = FALSE;break;
             case 'k' : mainkey = optarg;break;
             case 'i' : infile = optarg;break; 
             case 'o' : outfile = optarg;break;
             case 'h' : usage(argv[0]);break;
             default  : 
	     usage( argv[0] );
          }
       }

      if ( argc != 8 )  { usage ( argv[0] ); }
       
      if (strlen(mainkey) <= PASSLEN)
         gen(infile,outfile,mainkey,operation); 
      else
         printf("Password have to be with length <= %d\n",PASSLEN);   

 return 0;
}