Vigenère cipher implementation in C

Published on 2007-10-14 17:57:25.

tags = {  "math" "crypto" "fun" "c"   };

bookmarks = {  Digg! , Del.icio.us! , Google! , Slashdot! , Netscape! , Technorati! , Yahoo! , Stumbleupon! };

Description

A simple implementation of the Vigenère cipher written in the C programming language.
It's not supposed to be bulletproof, it's supposed to be fun.

Content

   1  #include <stdlib.h>
   2  #include <stdio.h>
   3  #include <string.h>
   4  
   5  char *encrypt( char *, char * );
   6  char *decrypt( char *, char * );
   7  
   8  int main( int argc, char **argv ){
   9      char str[50], *key;
  10      int decrypt_on;
  11  
  12      if( argc < 2 ){
  13          printf( "Encryption key is missing, exiting cowardly!\n" );
  14          exit( 0 );
  15      }
  16     
  17      key = argv[1];
  18     
  19      // set the decrypt_on flag to 1 if user
  20      // requested the decryption mode
  21      if( argv[2] ){
  22          decrypt_on = 1;
  23      }
  24     
  25      for( ;; ){
  26          if( decrypt_on ){
  27              printf( "Enter string to decrypt:\n" );
  28          } else {
  29              printf( "Enter string to encrypt:\n" );
  30          }
  31         
  32          // read alpha-spaces-newlines only
  33          scanf( "%[a-zA-Z \n]", str );
  34         
  35          if( decrypt_on ){
  36              printf( "Decrypted string:\n%s\n" , decrypt( str, key ) );
  37          } else {
  38              printf( "Encrypted string:\n%s\n" , encrypt( str, key ) );
  39          }
  40  
  41      }
  42  
  43  }
  44  
  45  /**
  46   * Encrypts a string using the Vigenère cipher
  47   *
  48   * @param   char*    str   str to encrypt
  49   * @param   char*    str   the cipher key to use
  50   *
  51   * @return  char*    str   the ciphered text
  52   */

  53  char *encrypt( char *str, char *key ){
  54      unsigned char *encrypted, *reset_point;
  55      int len = 0;
  56     
  57      // put aside some space for the encrypted text
  58      encrypted = (unsigned char*) malloc( strlen( str ) );
  59     
  60      // save the original cipher key address
  61      reset_point = key;
  62      while( *str ){
  63          // if there are no more cipher key characters start from the
  64          // first one again
  65          if( !*key ){
  66              key = reset_point;
  67          }
  68         
  69          // don't encrypt newlines and spaces, just save them and go to
  70          // the top of the loop
  71          if( *str == '\n' || *str == ' ' ){
  72              *(encrypted++) = *(str++);
  73              len++;
  74              continue;
  75          }
  76         
  77          // simple math for our cipher
  78          *encrypted = tolower( *(str++) ) + tolower( *(key++) ) + 1 - 'a';
  79         
  80          // sanitize the out-of-range characters
  81          if( *encrypted > 'z' ){
  82              *encrypted -= 'z' - 'a' + 1;
  83          }
  84  
  85          len++;
  86          encrypted++;
  87      }
  88      // add a NULL at the end of our string...
  89      *encrypted = '\0';
  90     
  91      // return the address of the encrypted string
  92      return encrypted - len;
  93  }
  94  
  95  /**
  96   * Decrypts a string using the Vigenère cipher
  97   *
  98   * @param   char*    str   str to decrypt
  99   * @param   char*    str   the cipher key to use
 100   *
 101   * @return  char*    str   the deciphered text
 102   */

 103  char *decrypt( char *str, char *key ){
 104      unsigned char *decrypted, *reset_point;
 105      int len = 0;
 106     
 107      decrypted = (unsigned char*) malloc( strlen( str ) );
 108  
 109      reset_point = key;
 110      while( *str ){
 111          if( !*key ){
 112              key = reset_point;
 113          }
 114         
 115          if( *str == '\n' || *str == ' ' ){
 116              *(decrypted++) = *(str++);
 117              len++;
 118              continue;
 119          }
 120  
 121          *decrypted = tolower( *(str++) ) - tolower( *(key++) ) - 1 + 'a';
 122  
 123          if( *decrypted < 'a' ){
 124              *decrypted += 'z' - 'a' + 1;
 125          }
 126  
 127          len++;
 128          decrypted++;
 129      }
 130      *decrypted = '\0';
 131  
 132      return decrypted - len;
 133  
 134  }
 135   
Code statistics
Physical lines Code lines Comment lines Empty lines Size
134 [ 100.00% ] 77 [ 57.46% ] 30 [ 22.39% ] 27 [ 20.15% ] 3201 bytes
[ Download ]