home *** CD-ROM | disk | FTP | other *** search
/ The Elite Hackers Toolkit / TheEliteHackersToolkitVolume1_1998.rar / HACKERS.BIN / hackers / snow_tar.gz / snow.tar / snow / encode.c < prev    next >
C/C++ Source or Header  |  1997-01-09  |  8KB  |  495 lines

  1. /*
  2.  * Whitespace encoding routines for the SNOW steganography program.
  3.  *
  4.  * Written by Matthew Kwan - December 1996
  5.  */
  6.  
  7. #include "snow.h"
  8.  
  9.  
  10. /*
  11.  * Local variables used for encoding.
  12.  */
  13.  
  14. static int    encode_bit_count;
  15. static int    encode_value;
  16. static char    encode_buffer[BUFSIZ];
  17. static BOOL    encode_buffer_loaded;
  18. static int    encode_buffer_length;
  19. static int    encode_buffer_column;
  20. static BOOL    encode_first_tab;
  21. static BOOL    encode_needs_tab;
  22. static int    encode_bits_used;
  23. static int    encode_bits_available;
  24. static int    encode_lines_extra;
  25.  
  26.  
  27. /*
  28.  * Return the next tab position.
  29.  */
  30.  
  31. static int
  32. tabpos (
  33.     int    n
  34. ) {
  35.     return ((n + 8) & ~7);
  36. }
  37.  
  38.  
  39. /*
  40.  * Read a line of text, like fgets, but strip off trailing whitespace.
  41.  */
  42.  
  43. static char *
  44. wsgets (
  45.     char        *buf,
  46.     int        size,
  47.     FILE        *fp
  48. ) {
  49.     int        n;
  50.  
  51.     if (fgets (buf, BUFSIZ, fp) == NULL)
  52.         return (NULL);
  53.  
  54.     n = strlen (buf) - 1;
  55.     while (n >= 0 && (buf[n] == ' ' || buf[n] == '\t' || buf[n] == '\n')) {
  56.         buf[n] = '\0';
  57.         n--;
  58.     }
  59.  
  60.     return (buf);
  61. }
  62.  
  63.  
  64. /*
  65.  * Write a line of text, adding a newline.
  66.  * Return FALSE if the write fails.
  67.  */
  68.  
  69. static BOOL
  70. wsputs (
  71.     char        *buf,
  72.     FILE        *fp
  73. ) {
  74.     int        len = strlen (buf);
  75.  
  76.     buf[len++] = '\n';
  77.     if (fwrite (buf, sizeof (char), len, fp) != len) {
  78.         perror ("Text output");
  79.         return (FALSE);
  80.     }
  81.  
  82.     return (TRUE);
  83. }
  84.  
  85.  
  86. /*
  87.  * Calculate, approximately, how many bits can be stored in the line.
  88.  */
  89.  
  90. static void
  91. whitespace_storage (
  92.     const char    *buf,
  93.     int        *n_lo,
  94.     int        *n_hi
  95. ) {
  96.     int        n, len = strlen (buf);
  97.  
  98.     if (len > line_length - 2)
  99.         return;
  100.  
  101.     if (len / 8 == line_length / 8) {
  102.         *n_hi += 3;
  103.         return;
  104.     }
  105.  
  106.     if ((len & 7) > 0) {
  107.         *n_hi += 3;
  108.         len = tabpos (len);
  109.     }
  110.     if ((line_length & 7) > 0)
  111.         *n_hi += 3;
  112.  
  113.     n = ((line_length - len) / 8) * 3;
  114.     *n_hi += n;
  115.     *n_lo += n;
  116. }
  117.  
  118.  
  119. /*
  120.  * Load the encode buffer.
  121.  * If there is no text to read, make it empty.
  122.  */
  123.  
  124. static void
  125. encode_buffer_load (
  126.     FILE        *fp
  127. ) {
  128.     int        i;
  129.  
  130.     if (wsgets (encode_buffer, BUFSIZ, fp) == NULL) {
  131.         encode_buffer[0] = '\0';
  132.         encode_lines_extra++;
  133.     }
  134.  
  135.     encode_buffer_length = strlen (encode_buffer);
  136.  
  137.     encode_buffer_column = 0;
  138.     for (i=0; encode_buffer[i] != '\0'; i++)
  139.         if (encode_buffer[i] == '\t')
  140.         encode_buffer_column = tabpos (encode_buffer_column);
  141.         else
  142.         encode_buffer_column++;
  143.  
  144.     encode_buffer_loaded = TRUE;
  145.     encode_needs_tab = FALSE;
  146. }
  147.  
  148.  
  149. /*
  150.  * Append whitespace to the loaded buffer, if there is room.
  151.  */
  152.  
  153. static BOOL
  154. encode_append_whitespace (
  155.     int        nsp
  156. ) {
  157.     int        col = encode_buffer_column;
  158.  
  159.     if (encode_needs_tab)
  160.         col = tabpos (col);
  161.  
  162.     if (nsp == 0)
  163.         col = tabpos (col);
  164.     else
  165.         col += nsp;
  166.  
  167.     if (col >= line_length)
  168.         return (FALSE);
  169.  
  170.     if (encode_needs_tab) {
  171.         encode_buffer[encode_buffer_length++] = '\t';
  172.         encode_buffer_column = tabpos (encode_buffer_column);
  173.     }
  174.  
  175.     if (nsp == 0) {
  176.         encode_buffer[encode_buffer_length++] = '\t';
  177.         encode_buffer_column = tabpos (encode_buffer_column);
  178.         encode_needs_tab = FALSE;
  179.     } else {
  180.         int        i;
  181.  
  182.         for (i=0; i<nsp; i++) {
  183.         encode_buffer[encode_buffer_length++] = ' ';
  184.         encode_buffer_column++;
  185.         }
  186.  
  187.         encode_needs_tab = TRUE;
  188.     }
  189.  
  190.     encode_buffer[encode_buffer_length] = '\0';
  191.  
  192.     return (TRUE);
  193. }
  194.  
  195.  
  196. /*
  197.  * Write a value into the text.
  198.  */
  199.  
  200. static BOOL
  201. encode_write_value (
  202.     int        val,
  203.     FILE        *inf,
  204.     FILE        *outf
  205. ) {
  206.     int        nspc;
  207.  
  208.     if (!encode_buffer_loaded)
  209.         encode_buffer_load (inf);
  210.  
  211.     if (!encode_first_tab) {    /* Tab shows start of data */
  212.         while (tabpos (encode_buffer_column) >= line_length) {
  213.         if (!wsputs (encode_buffer, outf))
  214.             return (FALSE);
  215.         encode_buffer_load (inf);
  216.         }
  217.  
  218.         encode_buffer[encode_buffer_length++] = '\t';
  219.         encode_buffer[encode_buffer_length] = '\0';
  220.         encode_buffer_column = tabpos (encode_buffer_column);
  221.         encode_first_tab = TRUE;
  222.     }
  223.  
  224.             /* Reverse the bit ordering */
  225.     nspc = ((val & 1) << 2) | (val & 2) | ((val & 4) >> 2);
  226.  
  227.     while (!encode_append_whitespace (nspc)) {
  228.         if (!wsputs (encode_buffer, outf))
  229.         return (FALSE);
  230.         encode_buffer_load (inf);
  231.     }
  232.  
  233.     if (encode_lines_extra == 0)
  234.         encode_bits_available += 3;
  235.  
  236.     return (TRUE);
  237. }
  238.  
  239.  
  240. /*
  241.  * Flush the rest of the text to the output.
  242.  */
  243.  
  244. static BOOL
  245. encode_write_flush (
  246.     FILE        *inf,
  247.     FILE        *outf
  248. ) {
  249.     char        buf[BUFSIZ];
  250.     int        n_lo = 0, n_hi = 0;
  251.  
  252.     if (encode_buffer_loaded) {
  253.         if (!wsputs (encode_buffer, outf))
  254.         return (FALSE);
  255.         encode_buffer_loaded = FALSE;
  256.         encode_buffer_length = 0;
  257.         encode_buffer_column = 0;
  258.     }
  259.  
  260.     while (wsgets (buf, BUFSIZ, inf) != NULL) {
  261.         whitespace_storage (buf, &n_lo, &n_hi);
  262.         if (!wsputs (buf, outf))
  263.         return (FALSE);
  264.     }
  265.  
  266.     encode_bits_available += (n_lo + n_hi) / 2;
  267.  
  268.     return (TRUE);
  269. }
  270.  
  271.  
  272. /*
  273.  * Initialize the encoding routines.
  274.  */
  275.  
  276. void
  277. encode_init (void)
  278. {
  279.     encode_bit_count = 0;
  280.     encode_value = 0;
  281.     encode_buffer_loaded = FALSE;
  282.     encode_buffer_length = 0;
  283.     encode_buffer_column = 0;
  284.     encode_first_tab = FALSE;
  285.     encode_bits_used = 0;
  286.     encode_bits_available = 0;
  287.     encode_lines_extra = 0;
  288. }
  289.  
  290.  
  291. /*
  292.  * Encode a single bit.
  293.  */
  294.  
  295. BOOL
  296. encode_bit (
  297.     int        bit,
  298.     FILE        *inf,
  299.     FILE        *outf
  300. ) {
  301.     encode_value = (encode_value << 1) | bit;
  302.     encode_bits_used++;
  303.  
  304.     if (++encode_bit_count == 3) {
  305.         if (!encode_write_value (encode_value, inf, outf))
  306.         return (FALSE);
  307.  
  308.         encode_value = 0;
  309.         encode_bit_count = 0;
  310.     }
  311.  
  312.     return (TRUE);
  313. }
  314.  
  315.  
  316. /*
  317.  * Flush the contents of the encoding routines.
  318.  */
  319.  
  320. BOOL
  321. encode_flush (
  322.     FILE        *inf,
  323.     FILE        *outf
  324. ) {
  325.     if (encode_bit_count > 0) {
  326.         while (encode_bit_count < 3) {    /* Pad to 3 bits */
  327.         encode_value <<= 1;
  328.         encode_bit_count++;
  329.         }
  330.  
  331.         if (!encode_write_value (encode_value, inf, outf))
  332.         return (FALSE);
  333.     }
  334.  
  335.     if (!encode_write_flush (inf, outf))
  336.         return (FALSE);
  337.  
  338.     if (!quiet_flag) {
  339.         if (encode_lines_extra > 0) {
  340.         fprintf (stderr,
  341.     "Message exceeded available space by approximately %.2f%%.\n",
  342.     ((double) encode_bits_used / encode_bits_available - 1.0) * 100.0);
  343.  
  344.         fprintf (stderr, "An extra %d lines were added.\n",
  345.                             encode_lines_extra);
  346.         } else {
  347.         fprintf (stderr,
  348.         "Message used approximately %.2f%% of available space.\n",
  349.         (double) encode_bits_used / encode_bits_available * 100.0);
  350.         }
  351.     }
  352.  
  353.     return (TRUE);
  354. }
  355.  
  356.  
  357. /*
  358.  * Decode the space count into actual bits.
  359.  */
  360.  
  361. static BOOL
  362. decode_bits (
  363.     int        spc,
  364.     FILE        *outf
  365. ) {
  366.     int        b1 = 0, b2 = 0, b3 = 0;
  367.  
  368.     if (spc > 7) {
  369.         fprintf (stderr, "Illegal encoding of %d spaces\n", spc);
  370.         return (FALSE);
  371.     }
  372.  
  373.     if ((spc & 1) != 0)
  374.         b1 = 1;
  375.     if ((spc & 2) != 0)
  376.         b2 = 1;
  377.     if ((spc & 4) != 0)
  378.         b3 = 1;
  379.  
  380.     if (!decrypt_bit (b1, outf))
  381.         return (FALSE);
  382.     if (!decrypt_bit (b2, outf))
  383.         return (FALSE);
  384.     if (!decrypt_bit (b3, outf))
  385.         return (FALSE);
  386.  
  387.     return (TRUE);
  388. }
  389.  
  390.  
  391. /*
  392.  * Decode the whitespace contained in the string.
  393.  */
  394.  
  395. static BOOL
  396. decode_whitespace (
  397.     const char    *s,
  398.     FILE        *outf
  399. ) {
  400.     int        spc = 0;
  401.  
  402.     for (;; s++) {
  403.         if (*s == ' ') {
  404.         spc++;
  405.         } else if (*s == '\t') {
  406.         if (!decode_bits (spc, outf))
  407.             return (FALSE);
  408.         spc = 0;
  409.         } else if (*s == '\0') {
  410.         if (spc > 0 && !decode_bits (spc, outf))
  411.             return (FALSE);
  412.         return (TRUE);
  413.         }
  414.     }
  415. }
  416.  
  417.  
  418. /*
  419.  * Extract a message from the input stream.
  420.  */
  421.  
  422. BOOL
  423. message_extract (
  424.     FILE        *inf,
  425.     FILE        *outf
  426. ) {
  427.     char        buf[BUFSIZ];
  428.     BOOL        start_tab_found = FALSE;
  429.  
  430.     decrypt_init ();
  431.  
  432.     while (fgets (buf, BUFSIZ, inf) != NULL) {
  433.         char    *s, *last_ws = NULL;
  434.  
  435.         for (s = buf; *s != '\0' && *s != '\n'; s++) {
  436.         if (*s != ' ' && *s != '\t')
  437.             last_ws = NULL;
  438.         else if (last_ws == NULL)
  439.             last_ws = s;
  440.         }
  441.  
  442.         if (*s == '\n')
  443.         *s = '\0';
  444.  
  445.         if (last_ws == NULL)
  446.         continue;
  447.  
  448.         if (!start_tab_found && *last_ws == ' ')
  449.         continue;
  450.  
  451.         if (!start_tab_found && *last_ws == '\t') {
  452.         start_tab_found = TRUE;
  453.         last_ws++;
  454.         if (*last_ws == '\0')
  455.             continue;
  456.         }
  457.  
  458.         if (!decode_whitespace (last_ws, outf))
  459.         return (FALSE);
  460.     }
  461.  
  462.     return (decrypt_flush (outf));
  463. }
  464.  
  465.  
  466. /*
  467.  * Calculate the amount of covert information that can be stored
  468.  * in the file.
  469.  */
  470.  
  471. void
  472. space_calculate (
  473.     FILE        *fp
  474. ) {
  475.     int        n_lo = 0, n_hi = 0;
  476.     char        buf[BUFSIZ];
  477.  
  478.     while (wsgets (buf, BUFSIZ, fp) != NULL)
  479.         whitespace_storage (buf, &n_lo, &n_hi);
  480.  
  481.     if (n_lo > 0) {        /* Allow for initial tab */
  482.         n_lo--;
  483.         n_hi--;
  484.     }
  485.  
  486.     if (n_lo == n_hi) {
  487.         printf ("File has storage capacity of %d bits (%d bytes)\n",
  488.                             n_lo, n_lo / 8);
  489.     } else {
  490.         printf ("File has storage capacity of between %d and %d bits.\n",
  491.                                 n_lo, n_hi);
  492.         printf ("Approximately %d bytes.\n", (n_lo + n_hi) / 16);
  493.     }
  494. }
  495.