/*
http://ardoino.altervista.org/crypto-security/articles/openssl_all
*/
//-------------------block_ciphers.c-------------------------------------
#include <openssl/des.h>
#include <openssl/blowfish.h>
//#include <openssl/idea.h>

#define MAXPASSLEN 31

/* DES
 * If mode = 1 encrypts *filein file with DES algorithm
 * If mode = 0 decrypts *filein file with DES algorithm
 * output is written in *fileout file
 * Returns 1 if the function runs successfully
 * Works on 8 bytes blocks
 *
 */
void des_encrypt_decrypt(int mode, char *filein, char *fileout)
{
   FILE *fpin,*fpout;
   char buf[MAXPASSLEN];
   des_cblock key,inmsg,outmsg; /* key, plaintext, ciphertext must  be 8 byte blocks */
   des_key_schedule sched;

   if (strcmp(filein,fileout) == 0) {
      fprintf(stderr,"Error: input and output files must not be the same file.\n");
      exit(EXIT_FAILURE);
   }
   /* des_read_pw_string reads password from stdin and stores it   in buf this function automatically asks to re-enter password   and checks it */
   memset(buf,'\0',MAXPASSLEN);
   if (mode == 1) {
      printf("Encrypting file '%s' with des cipher.\n", \
      filein);
      if (des_read_pw_string(buf,MAXPASSLEN - 1,"Enter the \
      password:\n",1) != 0) {
         fprintf(stderr,"Error: failed to read \
         password.\n");
         exit(EXIT_FAILURE);
      }
   } else {
      printf("Decrypting file '%s' with des cipher.\n",\
      filein);
      if (des_read_pw_string(buf,MAXPASSLEN - 1,"Enter the \
      password:\n",0) != 0) {
         fprintf(stderr,"Error: failed to read \
         password.\n");
         exit(EXIT_FAILURE);
      }
   }
   /* des_string to key convers the password to a key */
   des_string_to_key(buf,&key);
   /* des_set_key_checked checks that a key passed in of odd  parity and set up the key schedule */
   des_set_key_checked(&key,sched);
   fpin = fopen(filein,"r");
   if ((fpout = fopen(fileout,"w")) == NULL) {
      fprintf(stderr,"Error: failed to open output file.\n");
      exit(EXIT_FAILURE);
   }
   /* reads 8 bytes at a time(block=8bytes),encrypts/decrypts   each block with ecb */
   while (fread(inmsg,1,8,fpin)) {
      memset(outmsg,'\0',8);
      des_ecb_encrypt(&inmsg,&outmsg,sched,mode);
      fwrite(outmsg,1,8,fpout);
      memset(inmsg,'\0',8);
   }
   fclose(fpin);
   fclose(fpout);
   printf("Done.\n");
   return;
}

/* Blowfish
 * If mode = 1 encrypts *filein file with Blowfish algorithm
 * If mode = 0 decrypts *filein file with Blowfish algorithm
 * output is written in *fileout file
 * Returns 1 if the function runs successfully
 * Works on 8 bytes blocks
 *
 */
void bf_encrypt_decrypt(int mode, char *filein, char *fileout)
{
   FILE *fpin,*fpout;
   char buf[MAXPASSLEN];
   unsigned char inmsg[8],outmsg[8]; /* blowfish operates on 8 
   byte blocks */
   BF_KEY key;

   if (strcmp(filein,fileout) == 0) {
      fprintf(stderr,"Error: input and output files must \
      not be the same file.\n");
      exit(EXIT_FAILURE);
   }
   /* reads password from stdin using the same function used 
   for des passwords */
   memset(buf,'\0',MAXPASSLEN);
   if (mode == 1) {
      printf("Encrypting file '%s' with BlowFish cipher.\n",\
      filein);
      if (des_read_pw_string(buf,MAXPASSLEN - 1,"Enter the \
      password:\n",1) != 0) {
         fprintf(stderr,"Error: failed to read \
         password.\n");
         exit(EXIT_FAILURE);
      }
   } else {
      printf("Decrypting file '%s' with BlowFish cipher.\n",\
      filein);
      if (des_read_pw_string(buf,MAXPASSLEN - 1,"Enter the \
      password:\n",0) != 0) {
         fprintf(stderr,"Error: failed to read \
         password.\n");
         exit(EXIT_FAILURE);
      }
   }
   /* set up the key using password stored in buf from 
   des_read_pw_string */
   BF_set_key(&key,strlen(buf),buf);
   fpin = fopen(filein,"r");
   if ((fpout = fopen(fileout,"w")) == NULL) {
      fprintf(stderr,"Error: failed to open output file.\n");
      exit(EXIT_FAILURE);
   }
   /* reads 8 bytes at a time(block=8bytes),encrypts/decrypts each
   block with ecb */
   while (fread(inmsg,1,8,fpin)) {
      memset(outmsg,'\0',8);
      BF_ecb_encrypt(inmsg,outmsg,&key,mode);
      fwrite(outmsg,1,8,fpout);
      memset(inmsg,'\0',8);
   }
   fclose(fpin);
   fclose(fpout);
   printf("Done.\n");
   return;
}
//-------------------end block_ciphers.c---------------------------------