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;
}