Advertisement
DanFloyd

Affine Cipher

Aug 9th, 2015
337
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.34 KB | None | 0 0
  1. /* README */
  2. /*
  3.   This program implements a version of the famous 'affine cipher', the function it uses are
  4.   cipher(plain_char) = ((plain_char * a) + b) mod 26
  5.   decipher(cip_char) = ((cip_char - b)*(a^-1)) mod 26
  6.  
  7.   N.B. Due to mathematical reasons, this cipher only allows 312 different keys (one is the neutral key)
  8.   so it's not kinda secure... It can be violated with a very simple brute force attack.
  9.  
  10.   For further informations or suggestions feel free to contact me on PasteBin : @DanFloyd
  11. */
  12.  
  13. /* LIBRARIES */
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <time.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <stdlib.h>
  20.  
  21. /* FUNCTIONS DEFINITION */
  22. static void print_usage(); /* prints an help message */
  23. static void failure(char* fail); /* prints an error message and exit */
  24. static void cipher(FILE* msg, int k1, int k2); /* core cipher function */
  25. static void decipher(FILE* msg, int k1, int k2); /* core decipher function */
  26. static int mod_inv(int a, int b); /* calculates the modular inverse */
  27.  
  28. /* GLOBAL VARIABLES */
  29. int log_f = 0;         /* log file flag */
  30. FILE* log_file = NULL; /* log file */
  31.  
  32. /* MAIN FUNCTION */
  33. int main (int argc, char** argv) {
  34.  
  35.   char o;                /* used for getopt */
  36.   char tstamp[200];      /* used for create different titles for log files*/
  37.   FILE *msg_file = NULL; /* message file */
  38.   int dec_f = 0,         /* dechiper mode flag */
  39.       K1,                /* first key */
  40.       K2,                /* second key */
  41.       offset;            /* offset for command line */
  42.  
  43.   /* searching options */
  44.   while ((o = getopt(argc, argv, "dwh")) != -1) {
  45.     switch (o) {
  46.       case 'd' :
  47.         dec_f = 1;
  48.         break;
  49.       case 'w' :
  50.         log_f = 1;
  51.         break;
  52.       case 'h' :
  53.         print_usage();
  54.         exit(EXIT_SUCCESS);
  55.       case '?' :
  56.         failure("Unknown option. Please use option -h for help.");
  57.         break;
  58.     }
  59.   }
  60.  
  61.   /* timestamp setting */
  62.   sprintf(tstamp,"message-%u.txt",(unsigned) time(NULL));
  63.  
  64.   /* checking args number */
  65.   if(argc < 4)
  66.     failure("Missing arguments. Please use option -h for help.");
  67.  
  68.   /* setting offset for cmd line */
  69.   switch(argc) {
  70.     case 5 : {offset = 1;break;}
  71.     case 6 : {offset = 2;break;}
  72.     case 7 : {offset = 3;break;}
  73.     default: {offset = 0;}
  74.   }
  75.  
  76.   /* opening message's file */
  77.   if((msg_file = fopen(argv[1+offset],"r")) == NULL){
  78.     perror("Cannot open the file you specified.");
  79.     failure("Fatal error.");
  80.   }
  81.  
  82.   /* opening log file if requested */
  83.   if(log_f){
  84.     if((log_file = fopen(tstamp,"ab+")) == NULL){
  85.       perror("Cannot open the log file.");
  86.       failure("Fatal error.");
  87.     }
  88.   }
  89.  
  90.   /* setting keys */
  91.   K1 = strtol(argv[2+offset], NULL, 10);
  92.   if(errno == ERANGE || errno == EINVAL){
  93.     failure("First key is too long or not in base 10.");
  94.   }
  95.   if(K1 < 1 || K1 == 13 || K1 > 25 || K1%2 == 0){
  96.     failure("First key is not valid. Please use option -h for help.");
  97.   }
  98.   K2 = strtol(argv[3+offset], NULL, 10);
  99.   if(errno == ERANGE || errno == EINVAL){
  100.     failure("Second key is too long or not in base 10.");
  101.   }
  102.   K2 = K2%26;
  103.   if(K1==1 && K2==0)
  104.     fprintf(stderr, "[!!!] WARNING: You chose the neutral key combination, the message will not be ciphered.\n");
  105.  
  106.   /* chosing the mode */
  107.   if(dec_f)
  108.     decipher(msg_file, K1, K2);
  109.   else
  110.     cipher(msg_file, K1, K2);
  111.  
  112.   /* closing files */
  113.   fclose(msg_file);
  114.   if(log_f)
  115.     fclose(log_file);
  116.  
  117.   return EXIT_SUCCESS;
  118.  
  119. }
  120.  
  121. /* FUNCTIONS IMPLEMENTATION */
  122.  
  123. static void failure(char* fail) {
  124.   fprintf(stderr,"[!!!] ERROR: %s\n",fail);
  125.   exit(EXIT_FAILURE);
  126. }
  127.  
  128. static void print_usage() {
  129.   fprintf(stderr,"Usage:\n");
  130.   fprintf(stderr,"./acipher [FILE PATH] [KEY 1] [KEY 2] [OPTIONS]\n");
  131.   fprintf(stderr,"Valid options are:\n");
  132.   fprintf(stderr,"  -d : activate decipher mode\n");
  133.   fprintf(stderr,"  -w : write a log file contains your ciphered/deciphered message\n");
  134.   fprintf(stderr,"  -h : display this help message\n");
  135.   fprintf(stderr,"Please note:\n");
  136.   fprintf(stderr,"  - FILE PATH must be a valid path to a file that contains your message\n");
  137.   fprintf(stderr,"  - KEY 1 must be an odd number between 1 and 12 or between 14 and 25\n");
  138. }
  139.  
  140. static void cipher(FILE* msg, int k1, int k2){
  141.   char ch, cip;
  142.   while(fscanf(msg,"%c",&ch) != EOF){
  143.     if(ch>=65 && ch <= 90){
  144.       /* uppercase */
  145.       cip = (((ch - 65)*k1)+k2)%26 + 65;
  146.     } else if(ch>=97 && ch <= 122){
  147.       /* lowercase */
  148.       cip = (((ch - 97)*k1)+k2)%26 + 97;
  149.     } else {
  150.       /* space or other characters */
  151.       cip = ch;
  152.     }
  153.     fprintf(stdout,"%c",cip);
  154.     if(log_f)
  155.       fprintf(log_file,"%c",cip);
  156.   }
  157. }
  158.  
  159. static void decipher(FILE* msg, int k1, int k2){
  160.   int inv = mod_inv(k1,26);
  161.   char ch, cip;
  162.   while(fscanf(msg,"%c",&ch) != EOF){
  163.     if(ch>=65 && ch <= 90){
  164.       /* uppercase */
  165.       cip = (((ch - 65)-k2)*inv + 26)%26 + 65;
  166.     } else if(ch>=97 && ch <= 122){
  167.       /* lowercase */
  168.       cip = (((ch - 97)-k2)*inv + 26)%26 + 97;
  169.     } else {
  170.       /* space or other characters */
  171.       cip = ch;
  172.     }
  173.     fprintf(stdout,"%c",cip);
  174.     if(log_f)
  175.       fprintf(log_file,"%c",cip);
  176.   }
  177. }
  178.  
  179. static int mod_inv(int n, int m){
  180.   int x = 0;
  181.   while(x<=m){
  182.     if((n*x)%m == 1)
  183.       return x;
  184.     x++;
  185.   }
  186.   failure("Fatal error. Wrong key.");
  187.   return EXIT_FAILURE;
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement