The final part of the decoding program performs the actual decoding: A two-byte hexadecimal string is converted into a value. That value is then manipulated by the XOR 0xAA operation. The result is output. Yep, it took a long time to get to this point.
The final modification takes place in the process_line() function. That’s where an if–else decision detects the end of formatted input (if) or processes the line of bytes (else):
int process_line(char *line) { int len,x,a,b,v; if( strncmp(line,"END HEX CODE",12) == 0 ) { return(TRUE); } else { len = strlen(line)-1; /* count bytes per line */ len/=3; for(x=0;x<len;x++) { a = char2int(*(line+1)); /* first character */ b = char2int(*(line+2)); /* second char */ v = (a << 4) + b; /* build value from hex */ putchar(v ^= 0xAA); /* decode */ line+=3; } return(FALSE); } }
The strlen() function (above, and in Line 82 of the final code) grabs the length of the line of text read from standard input. This function is necessary because the final line of hex bytes might be shorter than the other lines, which are set to a maximum length of 73 bytes. The line length is saved in the len
variable, which is manipulated to reflect the actual number of hex byte pairs (characters) on a line. A for loop then processes each individual pair.
The char2int() function translates each hexadecimal digit. The left shift operator << manipulates each digit to reassemble the hex byte pair to a byte value.
At Line 89, the putchar() function contains the XOR 0xAA operation, which restores the original input value and outputs the result.
The pointer line
is incremented at Line 90, referencing the next hex byte pair in the string.
Click here to view the entire code.
To work the code, you need to supply input from a hexencoded file, such as the gettysburg.hexc
file used in earlier Lessons. Here’s how it works:
hexdecode < gettysburg.hexc
Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal.
The entire encoding operation could be done a lot simpler. The standard rot13 or Caesarian Cipher filter is an example of such an encoding/decoding system. But rot13 isn't formal; it's output is presented as plain text.
The hexencode/hexdecode examples for this series of Lessons can be modified further, which is why I formatted the encoded output. So if you wanted to add compression or encryption, it's a lot easier when the data is regimented. That's why the decoding program is more involved than the encoding program.