fork download
  1. /*****************************************************//**
  2.  * @brief Vigenere cipher of texts or text-files, with flexible alphabet.
  3.  * @file vigenere.c
  4.  * @version 0.3
  5.  * @date 19 Feb, 2012
  6.  * @author migf1 <mig_f1@hotmail.com>
  7.  * @par Language:
  8.  * ANSI C (C89)
  9.  * @remark Source code tab-size: 8
  10.  * @note http://e...content-available-to-author-only...a.org/wiki/Vigen%C3%A8re_cipher.
  11.  *********************************************************
  12.  */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <time.h>
  17. #include <limits.h>
  18.  
  19. const short int DEBUGMODE = 1; /* set it to 0 to disable own error messages */
  20. const short int ABSHUFFLE = 1; /* set it to 0 to disable alphabet shuffling */
  21.  
  22. #define MAXINPUT (1024+1) /* limit in chars for reading the stdin line */
  23.  
  24. /* Macro for outputting our own error-messages */
  25. #define MSG_ERROR( msg ) \
  26. do { \
  27. extern const short int DEBUGMODE; \
  28. if ( DEBUGMODE ) { \
  29. fprintf(stderr, "\n*** ERR [%s()|ln:%d]: %s\n", \
  30. __func__, __LINE__, msg ); \
  31. fputc('\n', stderr); \
  32. } \
  33. } while(0)
  34.  
  35. /* Portable alternative to Windows system("pause"); */
  36. #define pressENTER() \
  37. do{ \
  38. char mYcHAr; \
  39. printf( "press ENTER..." ); \
  40. while ( (mYcHAr=getchar()) != '\n' && mYcHAr != EOF ) \
  41. ; \
  42. }while(0)
  43.  
  44. /* Typedefs for passing arrays of unsigned strings as arrays of constant unsigned
  45.   strings to functions (this makes sure that those functions will not alter any
  46.   of the array contents).
  47.  */
  48. typedef const unsigned char *const ConstUString;
  49. typedef const unsigned char *const * ArrayOfConstUString;
  50.  
  51. /*********************************************************//**
  52.  * @par Prototype:
  53.  * int fname_exists( const char *fname );
  54.  *
  55.  * @brief Check whether a file exits or not.
  56.  * @param[in] fname (const char *) A c-string holding the name of the file
  57.  * to be chacked.
  58.  * @return 1 (TRUE) if the file exists, 0 (FALSE) otherwise.
  59.  *************************************************************
  60.  */
  61. int fname_exists( const char *fname )
  62. {
  63. FILE *fp = NULL;
  64.  
  65. if ( !fname || !*fname || !(fp=fopen(fname,"r")) )
  66. return 0; /* FALSE */
  67.  
  68. if ( fp )
  69. fclose(fp);
  70.  
  71. return 1; /* TRUE */
  72. }
  73.  
  74. /*********************************************************//**
  75.  * @par Prototype:
  76.  * int int_read( int *intvar );
  77.  *
  78.  * @brief Read an integer from stdin.
  79.  * @param[in,out] intvar (int *) A pointer to the integer variable to be read.
  80.  * @return The integer value read, or INT_MAX on error.
  81.  *************************************************************
  82.  */
  83. int int_read( int *intvar )
  84. {
  85. int try = 0;
  86. char input[ MAXINPUT ] = {'\0'};
  87.  
  88. if ( !fgets(input, MAXINPUT, stdin) )
  89. return INT_MAX;
  90.  
  91. if ( EOF == (try=sscanf(input, "%d", intvar)) || try < 1 )
  92. return INT_MAX;
  93.  
  94. return *intvar;
  95. }
  96.  
  97. /*********************************************************//**
  98.  * @par Prototype:
  99.  * char *s_read( char *s );
  100.  *
  101.  * @brief Read a c-string from stdin.
  102.  * @param[in,out] s (char *) The c-string to be read.
  103.  * @return The c-string (it remains unchanged on error)
  104.  *************************************************************
  105.  */
  106. char *s_read( char *s )
  107. {
  108. int lenstr = 0;
  109.  
  110. if ( !s || !fgets(s, MAXINPUT, stdin) )
  111. return s;
  112.  
  113. lenstr = strlen(s);
  114. if ( s[ lenstr - 1 ] == '\n' )
  115. s[ lenstr -1 ] = '\0';
  116.  
  117. return s;
  118. }
  119.  
  120. /*********************************************************//**
  121.  * @par Prototype:
  122.  * int s_cindex( const char *s, const char c );
  123.  *
  124.  * @brief Get the index of a given char c in a given c-string s.
  125.  * @param[in] s (const char *) The c-string to be searched.
  126.  * @param[in] c (const char ) The character to be looked for.
  127.  * @return The zero-based index of c in s, or -1 on error.
  128.  *************************************************************
  129.  */
  130. int s_cindex( const char *s, const char c )
  131. {
  132. char *cp = NULL;
  133. char *str = (char *)s;
  134.  
  135. if ( !s || !*s )
  136. return -1;
  137.  
  138. return (cp = strchr(str,c)) ? (int)(cp - str) : -1;
  139. }
  140.  
  141. /*********************************************************//**
  142.  * @par Prototype:
  143.  * char *s_shuffle( char *s );
  144.  *
  145.  * @brief Shuffle the contents of a given c-string s.
  146.  * @param[in,out] s (char *) The c-string to be shuffled.
  147.  * @return The shuffled c-string (it remains unchanged on error).
  148.  * @note It requires the constant SHUFFLE to contain an non-zero value.
  149.  *************************************************************
  150.  */
  151. char *s_shuffle( char *s )
  152. {
  153. char *cp = NULL, c = '\0';
  154. int len = 0;
  155. int i = 0;
  156.  
  157. /* sanity check */
  158. if ( !s || !*s || (len = strlen(s)) < 2 )
  159. return s;
  160.  
  161. srand( time(NULL) );
  162.  
  163. for (cp=s; *cp; cp++)
  164. {
  165. i = rand() % len;
  166. c = *cp;
  167. *cp = s[i];
  168. s[i] = c;
  169. }
  170.  
  171. return s;
  172. }
  173.  
  174. /*********************************************************//**
  175.  * @par Prototype:
  176.  * char *s_rotate_left( char *s, int rotby, const size_t len );
  177.  *
  178.  * @brief Roatate to the left a given c-string s of length len,
  179.  * by rotby characters.
  180.  * @param[in,out] s (char *) The c-string to be rotated.
  181.  * @param[in] rotby (int) The amount of characters the c-string will be rotated by.
  182.  * @param[in] len (const int) The length of the c-string in characters,
  183.  * excluding the nil terminator.
  184.  * @return The rotated c-string (remains unchanged on error).
  185.  *************************************************************
  186.  */
  187. char *s_rotate_left( char *s, int rotby, const size_t len )
  188. {
  189. char *temp = NULL;
  190.  
  191. if ( !s || rotby < 1 || len < 2 || (rotby %= len) == 0 )
  192. return s;
  193.  
  194. if ( NULL == (temp = malloc( rotby * sizeof(char) )) )
  195. return s;
  196. memcpy( temp, s, rotby * sizeof(char) );
  197.  
  198. memmove( s, &s[ rotby ], (len-rotby) * sizeof(char) );
  199. memcpy( &s[ len-rotby ], temp, rotby * sizeof(char) );
  200.  
  201. free( temp );
  202. return s;
  203. }
  204.  
  205. /*********************************************************//**
  206.  * @par Prototype:
  207.  * void sarr_print( ConstUString sarr[] );
  208.  *
  209.  * @brief Print to stdout the contents of a NULL terminated
  210.  * array of unsigned c-strings.
  211.  * @param[in] sarr (ConstUString *) The NULL terminated array of c-strings.
  212.  *************************************************************
  213.  */
  214. void sarr_print( ConstUString sarr[] )
  215. {
  216. int i = 0;
  217.  
  218. if ( !sarr )
  219. return;
  220.  
  221. for (i=0; sarr[i]; i++ )
  222. printf("%2d: %s\n", i, sarr[i] );
  223.  
  224. return;
  225. }
  226.  
  227. /*********************************************************//**
  228.  * @par Prototype:
  229.  * void sarr_free( char ***sarr );
  230.  *
  231.  * @brief Free memory reserved for a NULL terminated array of c-strings.
  232.  * @param[in,out] sarr (char ***) Pointer to the NULL terminated array of c-strings.
  233.  * @remark The array pointer \a *sarr is reset to NULL (that's why it
  234.  * passed <em>by reference</em> to the function).
  235.  *************************************************************
  236.  */
  237. void sarr_free( char ***sarr )
  238. {
  239. size_t i = 0;
  240.  
  241. if ( !sarr || !*sarr )
  242. return;
  243.  
  244. while ( (*sarr)[i] )
  245. free( (*sarr)[i++] );
  246.  
  247. *sarr = NULL;
  248. }
  249.  
  250. /*********************************************************//**
  251.  * @par Prototype:
  252.  * char **sarr_new( const int nstrings, const int lenstr );
  253.  *
  254.  * @brief Reserve memory for a NULL terminated array of c-strings.
  255.  * @param[in] nstrings (const int) The number of c-strings to be allocated,
  256.  * not counting the terminating NULL string.
  257.  * @param[in] lenstr (const int) The number of character to be allocated for
  258.  * each c-string, excluding the nil-terminator character.
  259.  * @return A pointer to the newly allocated memory, or NULL on error.
  260.  *************************************************************
  261.  */
  262. char **sarr_new( const int nstrings, const int lenstr )
  263. {
  264. char **sarr = NULL;
  265. int i=0;
  266.  
  267. if ( nstrings < 1 || lenstr < 1 )
  268. return NULL;
  269.  
  270. if ( NULL == (sarr = calloc( nstrings+1, sizeof(char *) )) )
  271. return NULL;
  272.  
  273. for (i=0; i < nstrings; i++)
  274. {
  275. if ( NULL == (sarr[i] = calloc( lenstr+1, sizeof(char) )) )
  276. {
  277. int j;
  278. for (j=i-1; j > -1; j--)
  279. free( sarr[j] );
  280. free( sarr );
  281. return NULL;
  282. }
  283. }
  284.  
  285. return sarr;
  286. }
  287.  
  288. /*********************************************************//**
  289.  * @par Prototype:
  290.  * unsigned char c_encrypt_vigenere(
  291.  * const unsigned char c, const unsigned char kc, ConstUString tabrecta[] );
  292.  *
  293.  * @brief Encrypt an unsigned character according to its corresponding
  294.  * Vigenere key-character.
  295.  * @param[in] c (const unsigned char) The character to be encrypted.
  296.  * @param[in] kc (const unsigned char) The corresponding Vigenere key-character.
  297.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  298.  * alphabets.
  299.  * @return The encrypted character, or '\0' on error (if either c or kc
  300.  * is out of the basic alphabet, c is returned unchanged).
  301.  * @remark http://e...content-available-to-author-only...a.org/wiki/Vigen%C3%A8re_cipher
  302.  * @sa s_encrypt_vigenere(), f_encrypt_vigenere().
  303.  ************************************************************/
  304. unsigned char c_encrypt_vigenere(
  305. const unsigned char c, const unsigned char kc, ConstUString tabrecta[] )
  306. {
  307. int ci = -1; /* index of c in the basic alphabet */
  308. int kci = -1; /* index of kc in the basic alphabet */
  309.  
  310. /* sanity checks */
  311. if ( !tabrecta || !tabrecta[0] || c == '\0' )
  312. return '\0';
  313.  
  314. /* characters out of alphabet are returned unchanged */
  315. if ( -1 == (ci=s_cindex( (const char *)tabrecta[0], (const char)c ))
  316. || -1 == (kci=s_cindex( (const char *)tabrecta[0], (const char)kc)) )
  317. return c;
  318.  
  319. return tabrecta[kci][ci];
  320. }
  321.  
  322. /*********************************************************//**
  323.  * @par Prototype:
  324.  * unsigned char c_decrypt_vigenere(
  325.  * const unsigned char c, const unsigned char kc, ConstUString tabrecta[] );
  326.  *
  327.  * @brief Decrypt an unsigned character according to its corresponding
  328.  * Vigenere key-character.
  329.  * @param[in] c (const unsigned char) The enrypted character.
  330.  * @param[in] kc (const unsigned char) The corresponding Vigenere key-character.
  331.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  332.  * alphabets.
  333.  * @return The decrypted character, or '\0' on error (if either c or kc
  334.  * is out of the basic alphabet, c is returned unchanged).
  335.  * @remark http://e...content-available-to-author-only...a.org/wiki/Vigen%C3%A8re_cipher
  336.  * @sa s_decrypt_vigenere(), f_decrypt_vigenere().
  337.  ************************************************************/
  338. unsigned char c_decrypt_vigenere(
  339. const unsigned char c, const unsigned char kc, ConstUString tabrecta[] )
  340. {
  341. int ci = -1; /* index of c */
  342. int kci = -1; /* index of kc */
  343.  
  344. /* sanity checks (including both c & kc being valid chars of basic alphabet) */
  345. if ( !tabrecta || !tabrecta[0] || c == '\0' )
  346. return '\0';
  347.  
  348. /* characters out of alphabet are returned unchanged */
  349. if ( -1 == (ci=s_cindex((const char *)tabrecta[0], (const char)c))
  350. || -1 == (kci=s_cindex((const char *)tabrecta[0], (const char)kc)) )
  351. return c;
  352.  
  353. /* index of c in the kci'th alphabet */
  354. ci = s_cindex((const char *)tabrecta[kci], (const char)c);
  355.  
  356. return tabrecta[0][ci]; /* ci'th char in the basic alphabet */
  357. }
  358.  
  359. /*********************************************************//**
  360.  * @par Prototype:
  361.  * int vigkey_repeat( unsigned char *skey, const size_t txtlen );
  362.  *
  363.  * @brief Repeat or truncate a Vigenere base key-string
  364.  * so that its length matches a given length.
  365.  * @param[in,out] skey (unsigned char *) The Vigenere base key-string
  366.  * to be modified.
  367.  * @param[in] txtlen (const int) The length to be matched.
  368.  * @return 1 (TRUE) or 0 (FALSE) on error.
  369.  * @remark The length to be matched should be equal to
  370.  * the length of the encrypted/decrypted text.
  371.  *************************************************************
  372.  */
  373. int vigkey_repeat( unsigned char *skey, const size_t txtlen )
  374. {
  375. size_t i=0, len=0;
  376.  
  377. /* sanity checks */
  378. if ( !skey || !*skey || txtlen > MAXINPUT-1)
  379. return 0; /* FALSE */
  380.  
  381. /* when base key is longer than plain text, truncate it */
  382. len = strlen( (char *)skey );
  383. if (len > txtlen) {
  384. skey[ txtlen ] = '\0';
  385. }
  386. /* when base key is shorter than plain text, repeat it */
  387. else {
  388. for (i=len; i+len < txtlen; i += len)
  389. memmove( &skey[i], skey, len * sizeof(char) );
  390. memmove( &skey[i], skey, (txtlen-i) * sizeof(char) );
  391. }
  392.  
  393. return 1; /* TRUE */
  394. }
  395.  
  396. /*********************************************************//**
  397.  * @par Prototype:
  398.  * unsigned char *s_encrypt_vigenere(
  399.  * unsigned char *s, const unsigned char *repkey, ConstUString tabrecta[]
  400.  * );
  401.  *
  402.  * @brief Encrypt an unsigned c-string according to a Vigenere
  403.  * repetitive key c-string.
  404.  * @param[in,out] s (unsigned char *) The unsigned c-string to be encrypted.
  405.  * @param[in] repkey (const unsigned char *) The Vigenere repetitive key c-string.
  406.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  407.  * alphabets.
  408.  * @return The encrypted unsigned c-string, or NULL on error.
  409.  * @note Contrary to the function f_encrypt_vigenere() which expects the
  410.  * base key-string, this one expects the repetitive key-string.
  411.  * @sa c_encrypt_vigenere(), f_encrypt_vigenere().
  412.  ************************************************************/
  413. unsigned char *s_encrypt_vigenere(
  414. unsigned char *s, const unsigned char *repkey, ConstUString tabrecta[] )
  415. {
  416. size_t i = 0; /* to parse s & repkey */
  417.  
  418. /* sanity checks */
  419. if ( !s || !*s || !repkey || !*repkey || !tabrecta ) {
  420. MSG_ERROR("Sanity check failed!");
  421. return NULL;
  422. }
  423. if ( strlen( (char *)s) != strlen((char *)repkey) ) {
  424. MSG_ERROR("Key length does not match text length!");
  425. return NULL;
  426. }
  427.  
  428. for (i=0; s[i]; i++)
  429. {
  430. s[i] = c_encrypt_vigenere(s[i], repkey[i], (ArrayOfConstUString)tabrecta);
  431. if ( '\0' == s[i] ) {
  432. MSG_ERROR("Invalid character found during encryption!");
  433. return NULL;
  434. }
  435. }
  436.  
  437. return s;
  438.  
  439. }
  440.  
  441. /*********************************************************//**
  442.  * @par Prototype:
  443.  * unsigned char *s_decrypt_vigenere(
  444.  * unsigned char *s, const unsigned char *repkey, ConstUString tabrecta[]
  445.  * );
  446.  *
  447.  * @brief Decrypt an unsigned c-string according to a Vigenere
  448.  * repetitive key c-string.
  449.  * @param[in,out] s (unsigned char *) The unsigned c-string to be decrypted.
  450.  * @param[in] repkey (const unsigned char *) The repetitive Vigenere key c-string.
  451.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  452.  * alphabets.
  453.  * @return The decrypted unsigned c-string, or NULL on error.
  454.  * @note Contrary to the function f_decrypt_vigenere() which expects the
  455.  * base key-string, this one expects the repetitive key-string.
  456.  * @sa c_decrypt_vigenere(), f_decrypt_vigenere().
  457.  ************************************************************/
  458. unsigned char *s_decrypt_vigenere(
  459. unsigned char *s, const unsigned char *repkey, ConstUString tabrecta[] )
  460. {
  461. int i = 0; /* to parse s & repkey */
  462.  
  463. /* sanity checks */
  464. if ( !s || !*s || !repkey || !*repkey || !tabrecta
  465. || strlen((char *)s) != strlen((char *)repkey) ) {
  466. MSG_ERROR("Sanity check failed!");
  467. return NULL;
  468. }
  469.  
  470. for (i=0; s[i]; i++)
  471. {
  472. if ( '\0' == (s[i] = c_decrypt_vigenere(s[i], repkey[i], tabrecta)) ) {
  473. MSG_ERROR("Invalid character found during decryption!");
  474. return NULL;
  475. }
  476. }
  477.  
  478. return s;
  479.  
  480. }
  481.  
  482. /*********************************************************//**
  483.  * @par Prototype:
  484.  * int f_encrypt_vigenere(
  485.  * const char *, const unsigned char *, ConstUString *, const char *
  486.  * );
  487.  *
  488.  * @brief Encrypt the contents of a text-file, and save them to another
  489.  * text-file.
  490.  * @param[in] fname (const char *fname) A c-string holding the name of the file
  491.  * whose contents are about to get encrypted.
  492.  * @param[in] skey (const unsigned char *) An unsigned c-string holding the
  493.  * Vigenere base key (that is, without being repititive).
  494.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  495.  * alphabets.
  496.  * @param[in] decfname (const char *fname) A c-string holding the name of the file
  497.  * to be created with the encrypted contents.
  498.  * @return 1 (TRUE) or 0 (FALSE) on error.
  499.  * @note Contrary to the function s_encrypt_vigenere() which expects the
  500.  * repetitive key-string, this one expects the base key-string.
  501.  * @sa c_encrypt_vigenere(), s_encrypt_vigenere().
  502.  *************************************************************
  503.  */
  504. int f_encrypt_vigenere(
  505. const char *fname,
  506. const unsigned char *skey,
  507. ConstUString tabrecta[],
  508. const char *encfname )
  509. {
  510. FILE *fp = NULL, *encfp = NULL;
  511. int cin = '\0', cout = '\0';
  512. size_t i = 0;
  513.  
  514. if ( !fname || !*fname || NULL == (fp = fopen(fname, "r")) )
  515. goto ret_failure;
  516. if ( !encfname || !*encfname || NULL == (encfp = fopen(encfname, "w")) )
  517. goto ret_failure;
  518.  
  519. while ( EOF != (cin = fgetc(fp)) )
  520. {
  521. if ( '\0' == skey[i] )
  522. i = 0;
  523.  
  524. cout = (int)c_encrypt_vigenere((unsigned char)cin, skey[i], tabrecta);
  525. if ( 0 == cout )
  526. goto ret_failure;
  527.  
  528. if ( EOF == fputc(cout, encfp) )
  529. goto ret_failure;
  530.  
  531. i++;
  532. }
  533.  
  534. if ( !feof(fp) )
  535. fputs("\nf_encrypt_vigenere() failed!\n", stderr);
  536.  
  537. fflush(encfp);
  538. fclose(encfp);
  539. fclose(fp);
  540.  
  541. return 1; /* TRUE */
  542.  
  543. ret_failure:
  544. if ( encfp ) {
  545. fflush( encfp );
  546. fclose( encfp );
  547. }
  548. if ( fp )
  549. fclose( fp );
  550. return 0; /* FALSE */
  551. }
  552.  
  553. /*********************************************************//**
  554.  *
  555.  *************************************************************
  556.  */
  557. #if 0
  558. int _f_encrypt_vigenere(
  559. const char *fname,
  560. char *skey,
  561. ConstUString tabrecta[],
  562. const char *encfname )
  563. {
  564. FILE *fp = NULL, *encfp = NULL;
  565. char line[ MAXINPUT ] = {'\0'};
  566. char repkey[ MAXINPUT ] = {'\0'};
  567. size_t lenskey = 0;
  568.  
  569. if ( !fname || !*fname || NULL == (fp = fopen(fname, "r")) )
  570. goto ret_failure;
  571. if ( !encfname || !*encfname || NULL == (encfp = fopen(encfname, "w")) )
  572. goto ret_failure;
  573.  
  574. lenskey = strlen(skey);
  575. while ( fgets(line, MAXINPUT, fp) )
  576. {
  577. strncpy( repkey, skey, MAXINPUT-1 );
  578. if ( !vigkey_repeat(repkey, strlen(line)) )
  579. goto ret_failure;
  580. if ( !s_encrypt_vigenere(line, repkey, tabrecta ) )
  581. goto ret_failure;
  582. if ( EOF == fputs(line, encfp) )
  583. goto ret_failure;
  584. }
  585.  
  586. if ( ferror(fp) )
  587. goto ret_failure;
  588.  
  589. fclose(encfp);
  590. fclose(fp);
  591. return 1; /* TRUE */
  592.  
  593. ret_failure:
  594. if ( encfp )
  595. fclose( encfp );
  596. if ( fp )
  597. fclose( fp );
  598. return 0; /* FALSE */
  599. }
  600. #endif
  601.  
  602. /*********************************************************//**
  603.  * @par Prototype:
  604.  * int f_decrypt_vigenere(
  605.  * const char *, const unsigned char *, ConstUString *, const char *
  606.  * );
  607.  *
  608.  * @brief Decrypt the contents of a text-file, and save them to another
  609.  * text-file.
  610.  * @param[in] fname (const char *fname) A c-string holding the name of the file
  611.  * whose contents are about to get decrypted.
  612.  * @param[in] skey (const unsigned char *) An unsigned c-string holding the
  613.  * Vigenere base key (that is, without being repititive).
  614.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  615.  * alphabets.
  616.  * @param[in] decfname (const char *fname) A c-string holding the name of the file
  617.  * to be created with the decrypted contents.
  618.  * @return 1 (TRUE) or 0 (FALSE) on error.
  619.  * @note Contrary to the function s_decrypt_vigenere() which expects the
  620.  * repetitive key-string, this one expects the base key-string.
  621.  * @sa c_decrypt_vigenere(), s_decrypt_vigenere().
  622.  *************************************************************
  623.  */
  624. int f_decrypt_vigenere(
  625. const char *fname,
  626. const unsigned char *skey,
  627. ConstUString tabrecta[],
  628. const char *decfname )
  629. {
  630. FILE *fp = NULL, *decfp = NULL;
  631. int cin = 0, cout = 0;
  632. size_t i = 0;
  633.  
  634. if ( !skey || !fname || !*fname || !(fp = fopen(fname, "r")) )
  635. goto ret_failure;
  636. if ( !decfname || !*decfname || !(decfp = fopen(decfname, "w")) )
  637. goto ret_failure;
  638.  
  639. i = 0;
  640. while ( EOF != (cin = fgetc(fp)) )
  641. {
  642. if ( '\0' == skey[i] )
  643. i = 0;
  644.  
  645. cout = (int)c_decrypt_vigenere((unsigned char)cin, skey[i], tabrecta);
  646. if ( 0 == cout )
  647. goto ret_failure;
  648.  
  649. if ( EOF == fputc(cout, decfp) )
  650. goto ret_failure;
  651.  
  652. i++;
  653. }
  654.  
  655. if ( !feof(fp) )
  656. goto ret_failure;
  657.  
  658. fflush( decfp );
  659. fclose(decfp);
  660. fclose(fp);
  661. return 1; /* TRUE */
  662.  
  663. ret_failure:
  664. if ( decfp ) {
  665. fflush( decfp );
  666. fclose( decfp );
  667. }
  668. if ( fp )
  669. fclose( fp );
  670. return 0; /* FALSE */
  671. }
  672.  
  673. /*********************************************************//**
  674.  * @par Prototype:
  675.  * int do_file_vigenere( ConstUString tabrecta[] );
  676.  *
  677.  * @brief Handle menu-selection "input from file".
  678.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  679.  * alphabets.
  680.  * @return 1 (TRUE) or 0 (FALSE) on error.
  681.  *************************************************************
  682.  */
  683. int do_file_vigenere( ConstUString tabrecta[] )
  684. {
  685. char fname[ MAXINPUT ] = {'\0'};
  686. char *encfname = "enc.txt";
  687. char *decfname = "dec.txt";
  688. unsigned char vigkey[ MAXINPUT ] = {'\0'};
  689.  
  690. /* get the name of the text file to be encrypted */
  691. do
  692. printf("Enter the name of the file: ");
  693. while ( '\0' == *s_read(fname) );
  694.  
  695. if ( !fname_exists(fname)) {
  696. perror(NULL);
  697. MSG_ERROR("No such file, try again...");
  698. return 0; /* FALSE */
  699. }
  700.  
  701. /* get a Vigenere base key-string */
  702. do
  703. printf("Enter a base key-string: ");
  704. while ( '\0' == *s_read((char *)vigkey) );
  705.  
  706. /* encrypt the file fname */
  707. if ( !f_encrypt_vigenere( fname, vigkey, (ArrayOfConstUString)tabrecta, encfname ) ) {
  708. MSG_ERROR("f_encrypt_vigenere() failed!");
  709. return 0; /* FALSE */
  710. }
  711. printf( "\nfile %s encrypted successfully, the resulting file is %s\n",
  712. fname, encfname);
  713.  
  714. /* decrypt the file out.txt */
  715. if ( !f_decrypt_vigenere( encfname, vigkey, (ArrayOfConstUString)tabrecta, decfname ) ) {
  716. MSG_ERROR("f_decrypt_vigenere() failed!");
  717. return 0; /* FALSE */
  718. }
  719. printf( "file %s decrypted successfully, the resulting file is %s\n",
  720. encfname, decfname);
  721.  
  722. return 1; /* TRUE */
  723. }
  724.  
  725. /*********************************************************//**
  726.  * @par Prototype:
  727.  * int do_stdin_vigenere( ConstUString tabrecta[] );
  728.  *
  729.  * @brief Handle menu-selection "input from keyboard".
  730.  * @param[in] tabrecta (ConstUString *) The Vigenere tabula recta, holding all the
  731.  * alphabets.
  732.  * @return 1 (TRUE) or 0 (FALSE) on error.
  733.  *************************************************************
  734.  */
  735. int do_stdin_vigenere( ConstUString tabrecta[] )
  736. {
  737. unsigned char text[ MAXINPUT ] = {'\0'}; /* plain text to en(de)crypt */
  738. unsigned char vigkey[ MAXINPUT ] = {'\0'};
  739.  
  740. /* get the text to be encrypted */
  741. do
  742. printf("Text to be encrypted : ");
  743. while ( *s_read((char *)text) == '\0' );
  744.  
  745. /* get a Vigenere base key-string */
  746. do
  747. printf("Enter base key-string: ");
  748. while ( *s_read((char *)vigkey) == '\0' );
  749.  
  750. /* convert the base key-string to a repetitive key-string */
  751. if ( !vigkey_repeat(vigkey, strlen((char *)text)) ) {
  752. MSG_ERROR("Key repetition failed, nothing more to do!");
  753. return 0; /* FALSE */
  754. }
  755. printf("\nRepetitive key-string: %s\n", vigkey);
  756.  
  757. /* encrypt given text with the given Vigenere key */
  758. if ( NULL == s_encrypt_vigenere(text, vigkey, (ArrayOfConstUString)tabrecta) ) {
  759. MSG_ERROR("encryption error (perhaps invalid char in text)!");
  760. return 0; /* FALSE */
  761. }
  762. printf("\nEncrypted text: %s\n", text );
  763.  
  764. /* decrypt given text using given Vigenere key */
  765. if ( NULL == s_decrypt_vigenere(text, vigkey, (ArrayOfConstUString)tabrecta) ) {
  766. MSG_ERROR("\tdecryption error (perhaps invalid char in text)");
  767. return 0; /* FALSE */
  768. }
  769. printf("Decrypted text: %s\n\n", text );
  770.  
  771. return 1; /* TRUE */
  772. }
  773.  
  774. /*********************************************************//**
  775.  * @par Prototype:
  776.  * char menu_selection( void );
  777.  *
  778.  * @brief Display the commands menu and the get user selection.
  779.  * @return (char) The menu selection, as a character.
  780.  *************************************************************
  781.  */
  782. char menu_selection( void )
  783. {
  784. char input[ MAXINPUT ] = {'\0'};
  785.  
  786. puts("\n-----------------------");
  787. puts("migf1 @ Vigenere Cipher");
  788. puts("-----------------------");
  789. puts("1. display the alphabet");
  790. puts("2. input from keyboard");
  791. puts("3. input form text file");
  792. puts("0. exit");
  793. puts("-----------------------");
  794.  
  795. printf("> ");
  796. s_read( input );
  797.  
  798. return *input;
  799. }
  800.  
  801. /*********************************************************//**
  802.  * @par Prototype:
  803.  * short int tabrecta_make(
  804.  * unsigned char ***, const unsigned char *, const unsigned char,const int
  805.  * );
  806.  *
  807.  * @brief Create & fill the Vigenere tabula recta (table of
  808.  * unsigned alphabets).
  809.  * @param[in,out] tabrecta (unsigned char ***) Pointer to an array of unsigned
  810.  * c-strings (tabula recta) to be created & filled-in.
  811.  * If the array is created successfully, its last
  812.  * c-string will be a NULL pointer (NULL terminated
  813.  * array of unsigned c-strings).
  814.  * @param[in] ab (const unsigned char *) An unsigned c-string to be
  815.  * used as basic alphabet (see notes).
  816.  * @param[in] cstart (const unsigned char) The 1st character in the basic
  817.  * alphabet (see notes).
  818.  * @param[in] ablen (const int) The basic alphabet length, in characters
  819.  * (see notes).
  820.  * @return The length of the newly created basic alphabet in
  821.  * characters, excluding the nil-terminator, or 0 on
  822.  * error. Since tabula recta is a square table, the
  823.  * return value of the function equals also to the
  824.  * number of c-string alphabets created, excluding the
  825.  * final NULL string.
  826.  * @note You may use this function differently depending on
  827.  * the arguments you pass to it. If you specify a valid,
  828.  * non-empty, c-string as the 2nd argument, then it is
  829.  * used as the basic alphabet and the rest of the
  830.  * arguments are ignored.
  831.  * However, if you pass the 2nd argument as NULL or as
  832.  * an empty c-string, then the basic alphabet is
  833.  * constructed from consecutive characters in the
  834.  * current ASCII table, starting from character \a
  835.  * cstart up to character <em>(cstart + ablen-1)</em>.
  836.  * Please note that in this case, the zero character
  837.  * '\0' is not allowed (the function returns error).
  838.  * In general, you should never include the zero
  839.  * character in your basic alphabet.
  840.  * @sa tabrecta_extend().
  841.  *************************************************************
  842.  */
  843. short int tabrecta_make(
  844. unsigned char ***tabrecta,
  845. const unsigned char *ab,
  846. const unsigned char cstart,
  847. const int ablen )
  848. {
  849. short int i, len = 0;
  850.  
  851. /* sanity check */
  852. if ( !tabrecta )
  853. return 0;
  854.  
  855. /* when tabrecta already exists, just return its alphabet length */
  856. if ( *tabrecta && (*tabrecta)[0] ) {
  857. MSG_ERROR("TabulaRecta already existed (stayed unchanged)");
  858. return strlen( (char *)(*tabrecta)[0] );
  859. }
  860.  
  861. /* when argument ab exists and it is not an empty c-string */
  862. if ( ab && *ab )
  863. {
  864. /* reserve memory for the tablula recta */
  865. len = strlen( (char *)ab );
  866. if ( NULL == (*tabrecta = (unsigned char **)sarr_new(len, len)) )
  867. return 0;
  868.  
  869. /* copy the basic alphabet ab to the 1st string of the tabula recta */
  870. strcpy( (char *)(*tabrecta)[0], (char *)ab );
  871. s_shuffle( (char *)(*tabrecta)[0] );
  872.  
  873. /* remaining strings have basic alphabet rotated by 1 char at a time */
  874. for (i=1; (*tabrecta)[i]; i++) {
  875. strcpy( (char *)(*tabrecta)[i], (char *)(*tabrecta)[0] );
  876. s_rotate_left( (char *)(*tabrecta)[i], i, len );
  877. }
  878. }
  879.  
  880. /* when ab is NULL or empty, make alphabet from cstart to (cstart+ablen-1) */
  881. else if (cstart > '\0' && ablen > 0 && cstart + ablen - 1 < 257)
  882. {
  883. /* reserve memory for the tablula recta */
  884. len = ablen;
  885. if (NULL == (*tabrecta = (unsigned char **) sarr_new(len, len)) )
  886. return 0;
  887.  
  888. /* construct the basic alphabet into the 1st string of tabula recta */
  889. for (i=0; i < len; i++)
  890. (*tabrecta)[0][i] = cstart + i;
  891. if ( ABSHUFFLE )
  892. s_shuffle( (char *)(*tabrecta)[0] ); /* shuffle alphabet */
  893.  
  894. /* remaining strings have basic alphabet rotated by 1 char at a time */
  895. for (i=1; (*tabrecta)[i]; i++) {
  896. strcpy( (char *)(*tabrecta)[i], (char *)(*tabrecta)[0] );
  897. s_rotate_left( (char *)(*tabrecta)[i], i, len );
  898. }
  899. }
  900.  
  901. /* error */
  902. else
  903. return 0;
  904.  
  905.  
  906. return len;
  907. }
  908.  
  909. /*********************************************************//**
  910.  * @par Prototype:
  911.  * short int tabrecta_extend( unsigned char ***, const unsigned char *extension );
  912.  *
  913.  * @brief Extend the alphabet of an existing tabula recta.
  914.  * @param[in,out] tabrecta (unsigned char ***) Pointer to a NULL terminated array
  915.  * of unsigned c-strings, holding the tabula recta to be
  916.  * modified.
  917.  * @param[in] extension (char **) An unsigned c-string holding the characters
  918.  * to be added to the existing tabula recta.
  919.  * @return The length of the extended basic alphabet in
  920.  * characters, excluding the nil-terminator, or 0 on
  921.  * error. Since tabula recta is a square table, the
  922.  * return value of the function equals also to the
  923.  * extended number of c-string alphabets, excluding
  924.  * the final NULL string.
  925.  * @note After the needed houskeeping and error-checking is done,
  926.  * the function comoletely destroys the old tabula recta
  927.  * and re-builds it from scratch. Thus, it is crucial to
  928.  * always check if it succeeded, before attempting to
  929.  * move on with the rest of the proggram.
  930.  *************************************************************
  931.  */
  932. short int tabrecta_extend( unsigned char ***tabrecta, const unsigned char *extension )
  933. {
  934. short int ablen = 0, newlen = 0;
  935. unsigned char *abnew = NULL; /* temp c-str for extended alphabet */
  936.  
  937. /* sanity checks */
  938. if ( !tabrecta || !*tabrecta )
  939. return 0;
  940.  
  941. /* when tabula recta exists, get its alphabet length */
  942. if ( (*tabrecta)[0] )
  943. ablen = strlen( (char *)(*tabrecta)[0] );
  944.  
  945. /* more sanity checks */
  946. if ( !extension || !*extension )
  947. return ablen;
  948.  
  949. /* allocate memory for the extended alphabet */
  950. newlen = ablen + strlen( (char *)extension );
  951. if ( NULL == (abnew = calloc( newlen+1, sizeof(unsigned char) )) )
  952. return 0;
  953. /* construct the extended alphabet */
  954. strcpy( (char *)abnew, (char *)(*tabrecta)[0] );
  955. strcat( (char *)abnew, (char *)extension );
  956.  
  957. /* destroy old tabula recta and re-build it with the extended alphabet */
  958. sarr_free( (char ***)tabrecta );
  959. newlen = tabrecta_make( tabrecta, abnew, 0, 0 );
  960.  
  961. /* free memory temporarily reserved for the c-string of the extended alphabet */
  962. free( abnew );
  963.  
  964. return newlen;
  965. }
  966.  
  967. /*********************************************************//**
  968.  *
  969.  *************************************************************
  970.  */
  971. int main( void )
  972. {
  973. char msel = '0'; /* menu selection */
  974. unsigned char **tabrecta = NULL; /* Vigenere tabula recta */
  975. short int ablen = 0; /* length of basic alphabet */
  976.  
  977. /* create the Vigenere tabula recta, with alphabet from ' ' to ASCII(254) */
  978. if ( 0 == (ablen=tabrecta_make( &tabrecta, NULL, ' ', 223 )) ) {
  979. MSG_ERROR("Tabula recta initialization failed!");
  980. goto exit_failure;
  981. }
  982. /* extend the alphabet of the created Vigenere tabula recta with 5 more chars*/
  983. if ( 0 == (ablen=tabrecta_extend( &tabrecta, (unsigned char *)"\t\v\n\r\f")) )
  984. {
  985. MSG_ERROR("Tabula recta extension failed!");
  986. goto exit_failure;
  987. }
  988.  
  989. /* display the commands menu and apply user selection */
  990. for (;;)
  991. {
  992. if ( '\0' == (msel=menu_selection()) ) /* just an ENTER was pressed */
  993. continue;
  994.  
  995. if ( '0' == msel ) /* exit was selected */
  996. break;
  997.  
  998. if ( '1' == msel ) /* display the alphabet */
  999. printf("\nAlphabet (%d chars):\n%s\n", ablen, tabrecta[0] );
  1000.  
  1001. else if ( '2' == msel ) { /* use stdin for input */
  1002. do_stdin_vigenere( (ArrayOfConstUString)tabrecta );
  1003. pressENTER();
  1004. }
  1005.  
  1006. else if ( '3' == msel ) { /* use a file for input */
  1007. do_file_vigenere( (ArrayOfConstUString)tabrecta );
  1008. pressENTER();
  1009. }
  1010.  
  1011. else
  1012. puts("\ninvalid option, try again...");
  1013.  
  1014. }
  1015.  
  1016. sarr_free( (char ***)&tabrecta );
  1017. exit( EXIT_SUCCESS );
  1018.  
  1019. exit_failure:
  1020. sarr_free( (char ***)&tabrecta );
  1021. pressENTER();
  1022. exit( EXIT_FAILURE );
  1023. }
  1024.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty