In: Computer Science
C PROGRAMMING – Steganography
In this assignment, you will write an C program that includes processing input, using control structures, and bitwise operations.
The input for your program will be a text file containing a large amount of English. Your program must extract the “secret message” from the input file. The message is hidden inside the file using the following scheme.
The message is hidden in binary notation, as a sequence of 0’s and 1’s. Each block of 8-bits is the ASCII encoding of a single character in the “secret message”. Your program will scan the input, and for each period (aka, dot) encountered, your program will count the number of spaces (ASCII 0x20) that immediately follow the dot.
If the number of spaces is 0, then your program will ignore that dot completely.
If the number of spaces is 1, then that corresponds to a single 0 bit of the secret message.
If the number of spaces is 2, then that corresponds to a single 1 bit of the secret message.
Finally, if the number of spaces is 3 or more, then that indicates that there are no more characters in the secret message.
Your program must scan the input file, and output to stdout the plain text secret message. If your program successfully completes its task, then the program should return an exit status of 0 to the operating system. If the number of bits in the message is not a multiple of 8 (8 bits for each ASCII character), then your program should return an exit status of 1. If the input file does not containing the “message over” signal, i.e., a dot followed by 3 or more spaces, then your program should return an exit status of 2.
You are provided several input files from which you should be able to extract the “secret message”. You are also provided input files where the “secret message” is incorrectly encoded,i.e., your program should return a non-zero exit status. You can write your program foo.c to read input from stdin (e.g., using getchar()), and then test your program on the given files using input redirection, as follows:
$ gcc foo.c; ./a.out < goodInputFile
Your program should output the “secret message” to stdout.
This program is an example of “stream processing”. You will read the input file, character by character, in a single pass. You must not use arrays of any kind, since there is no need to do so, and using arrays is simply inefficient (i.e., overkill).
To clarify further, we only want to be using the string literal as a placeholder for the message to be printed at the end of the program. When decoding each character we should only be using one char, not an array of chars. Remember that a char is 1 byte or 8 bits in total and that each char is technically just a binary number.
Note: there was a typo in the original clarification which should have said the sequence of chars can be stored in a string literal not sequence of bits.
SUGGESTION: This means your program should do something along the lines of the following to produce the decoded message:
1. Use getchar() to retrieve each character from the input file,
which is provided to your program through std in, e.g.,
$ myfile.out < inputfilename
2. Interpret each sequence of '.' and ' ' characters to produce
either a 1, a 0, or a signal for your program to exit with an error
status.
3. Collect the 1 or 0 bit values you find in order to produce an
8-bit value; recall that a character in C is given by an 8-bit
decimal value, which means to C, 65 == 'A'.
4. Store your 8-bit value in a buffer or container, e.g. a
character array or string literal (char *ptr, for example).
5. Continue looping over the input until you reach the character
that signals the end of the file. Once you have reached the end of
the file, if you have a number of bits that %8 == 0 and you have
not reached the signal to exit with an error status, print your
decoded message to the std output.
inputFiles:
badInputFile_1
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
goodInputFile_1
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
I. a. m. S. a. m. S. a. m
Code:
#include <stdio.h>
#include <stdlib.h> // to use exit()
#include <string.h> // to use strlen()
#include <math.h> // to use pow()
//variables:
char c; // each input char is rewritten onto this variable, one at a time
short spaceCounter; // count up each pack of white spaces
char bytes[1000]; //string for representing the bytes of the secret message
int i; //reusable index
int len; //will be used to store the length of the bit string
/* ************************************
* Description: This function gets the input one char at a time, looks for
* dots, counts spaces, stores 0 or 1 as described above, and
* terminates the program when necessary(see above).
* Parameters: int argc: the number of command line args
* char *argv[]: the string array of command line args
* Return: int: return zero for no problems,
* return 1 for failure
************************************ */
int main(int argc, char *argv[]) {
// make sure there is one command line arg (a.out) and the input file
// from this command: ./a.out < someInputFile
if (argc != 1) {
printf("Required: one cmd line arg and then the input file name.\n");
return 3; //error code 1 is used for a "non-modulo 8" result, so I'm using 3 for this arg error
}
// read through the input and process any (dot + spaces) into bits:
i = 0;
while (c != EOF) {
c = getchar();
spaceCounter = 0;
//look for dots then count subsequent spaces:
if (c == '.') {
c = getchar();
while (c == ' ') {
spaceCounter++;
c = getchar();
}
}
//covert each package of spaces into a bit and add it to the bit string:
if (spaceCounter == 1) {
bytes[i] = '0';
i++;
} else if (spaceCounter == 2) {
bytes[i] = '1';
i++;
} else if (spaceCounter >= 3){
c = EOF;
}
}//END while() loop that reads input file
len = strlen(bytes);
//error messages:
if (c != EOF) {
printf("DANGER: you have been compromised. Courier message was bogus with no 3-space termination. Exfiltrate NOW.");
return 2;
}
//finally, if you made it this far, convert the bits and print the secret message:
int k = 7;
int decimalForAscii = 0;
int currentBit = 0;
//convert each string of 8 bits to decimal, then convert to ASCII:
for (int j = 0; j <= len; j++) {
currentBit = (int)bytes[j] - 48;
decimalForAscii += (currentBit * pow(2, k));
k--;
if (k == -1) {
printf("%c", (char)decimalForAscii);
k = 7;
decimalForAscii = 0;
}
}
printf("\n");
return 0;
}//END main()
Sreenshots:
-------------------------END---------------------
Please give a thumbs up(upvote) if you liked the answer.