Plaintext Steganography
The most common form of Steganography is to hide messages inside images, but what about hiding messages inside (plaintext) messages? This is the question I asked myself before creating this set of programs to do exactly that.
There are several ways to do this, but the approach I used was to utilize the whitespace (spaces and newlines) to hide the message. Basically, the amount of words (odd or even) on a line will indicate if the hidden bit is a one or zero. This works on all kind of text, but unfortunately requires a lot of it to hide even the smallest amounts of data. The only practical usage I can think of right now, is to hide passwords.
Here is the encoder:
#include <stdio.h> #define WRAP 80 static int getbit(FILE *fh) { static int x = 7; static int c = '\0'; if (x == -1) x = 7; if (x == 7) { c = fgetc(fh); if (c == EOF) return -1; } return (c >> x--) & 0x1; } int main(int argc, char *argv[]) { int c, n, spaces, bit, index, had_space, new_index; unsigned char buffer[WRAP]; FILE *fh; if (argc != 2) { fprintf(stderr, "Usage: %s <text file>\n", argv[0]); return 1; } fh = fopen(argv[1], "r"); if (fh == NULL) { fprintf(stderr, "Error: Unable to open text file for reading.\n"); return 1; } n = spaces = index = had_space = 0; while (1) { bit = getbit(stdin); while ((c = fgetc(fh)) != EOF) { if (c == '\n' || c == '\r' || c == '\t') c = ' '; /* Convert. */ if (c == ' ') { if (had_space) continue; had_space = 1; spaces++; if (bit == -1) { if ((spaces % 2) == 0) /* Pad output with zeros. */ index = n; } else { if ((spaces % 2) == bit) index = n; } } else { had_space = 0; } buffer[n] = c; n++; if (n >= WRAP) { if (index == 0) { fprintf(stderr, "Error: Words in text are too large.\n"); fclose(fh); return 1; } for (n = 0; n < index; n++) { fputc(buffer[n], stdout); } fputc('\n', stdout); spaces = new_index = had_space = 0; index++; for (n = index; n < WRAP; n++) { buffer[n - index] = buffer[n]; if (buffer[n] == ' ') { spaces++; new_index = n; } } n = WRAP - index; index = new_index; break; } } if (feof(fh)) { fclose(fh); if (bit == -1) { return 0; } else { fprintf(stderr, "Error: Not enough text to cover data.\n"); return 1; } } } return 0; }
And here is the decoder:
#include <stdio.h> static int power_of_two(int n) { if (n == 0) return 1; else return 2 * power_of_two(n - 1); } int main(int argc, char *argv[]) { int n, c, spaces, value; n = 7; spaces = value = 0; while ((c = fgetc(stdin)) != EOF) { if (c == '\n') { if ((spaces % 2) == 0) value += power_of_two(n); n--; if (n < 0) { fputc(value, stdout); value = 0; n = 7; } spaces = 0; } else if (c == ' ') { spaces++; } } return 0; }