AES-GCM decryption in C - c

I have token (base64url) that i need to decrypt with aes-gcm. The token contains:
16 bytes for IV, 17 bytes for TAG and the rest is the binary that needs to be decrypted.
I can't seem to be able to figure out, this is my code:
{
unsigned char * source = "BASE64-ENCODED-BINARY";
unsigned char key_raw[] = "KEY";
unsigned char key[2048];
int key_len = 0;
unsigned char output[2048];
int output_len = 0;
unsigned char * plaintext;
int c, r;
size_t out;
int dest_len = 4*(sizeof(source)/3);
// int key_len = 4*(sizeof(key_raw)/3);
unsigned char iv[16];
unsigned char tag[16];
unsigned char content[2048];
int content_len = 0;
b64ud_t s;
EVP_CIPHER_CTX *ctx;
int outlen, tmplen, rv;
unsigned char outbuf[2048];
/* token decode */
base64url_decode_reset(&s);
//memset( output,0, dest_len );
base64url_decode( output, 2048, source, strlen(source), NULL );
/* Just look through the output to get the decode result len */
for(;;)
{
if( output[output_len] )
{
output_len++;
} else {
break;
}
}
printf("decoded-token: [length: %d]\n", output_len );
BIO_dump_fp(stdout, output, output_len);
/* ket decode */
base64url_decode_reset(&s);
memset( key, 0, key_len );
base64url_decode( key, key_len-1, key_raw, strlen(key_raw), NULL );
/* Just look through the key to get the decode result len */
for(;;)
{
if( key[key_len] )
{
key_len++;
} else {
break;
}
}
printf("decoded-key: [Length: %d]\n", key_len );
BIO_dump_fp(stdout, key, key_len);
/*
The token is composed like so:
[16bytes IV] + [16 bytes TAG] + [Encrypted Message]
*/
printf("getting 16 bytes out of the decode output and storing them in IV\n");
for(int v=0;v<16;v++)
{
iv[v] = output[v];
}
printf("getting the NEXT 16 bytes out of the decode output and storing them in TAG\n");
for(int v=16;v<32;v++)
{
tag[v-16] = output[v];
}
printf("Just count haw many non-00 bytes remain and store it in content_len\n");
for(int i=32;i<output_len;i++)
{
if(output[i])
{
content_len++;
} else {
break;
}
}
printf("%d\n", content_len);
printf("We now use content_len and get the remaining bytes and store them in content\n");
for(int v=0; v<content_len;v++)
{
content[v] = output[v+32];
}
printf( "iv:\n" );
BIO_dump_fp(stdout, iv, sizeof(iv));
printf("tag:\n" );
BIO_dump_fp(stdout, tag, sizeof(tag));
printf("content :\n" );
BIO_dump_fp(stdout, content, content_len);
printf("AES GCM Decrypt:\n");
unsigned char * key_final;
key_final = key;
unsigned char * ciphertext;
ciphertext = content;
printf("Ciphertext:\n");
BIO_dump_fp(stdout, content, content_len);
ctx = EVP_CIPHER_CTX_new();
/* Select cipher */
EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
/* Set IV length, omit for 96 bits */
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(iv), NULL);
/* Specify key and IV */
EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv);
/* Zero or more calls to specify any AAD */
//EVP_DecryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad));
/* Decrypt plaintext */
EVP_DecryptUpdate(ctx, outbuf, &outlen, ciphertext, content_len);
/* Output decrypted block */
printf("Plaintext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
/* Set expected tag value. */
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), (void *)tag);
/* Finalise: note get no output for GCM */
rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
/*
* Print out return value. If this is not successful authentication
* failed and plaintext is not trustworthy.
*/
printf("outbuf: %s", outbuf);
printf("Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
My output is:
decoded-token: [length: 57]
0000 - ae 3f d9 92 46 54 39 93-31 64 e7 ce 98 ba 44 50 .?..FT9.1d....DP
0010 - 1d ec 89 4e ee e9 18 d9-15 e3 3d b3 e8 1b ff 10 ...N......=.....
0020 - 91 e7 a5 85 28 50 09 88-cc 85 d9 3e 82 05 19 a5 ....(P.....>....
0030 - 87 f4 b2 d2 2f e5 7f 24-fd ..../..$.
decoded-key: [Length: 33]
0000 - 0e 0b e4 0a b9 32 04 d4-b2 f7 21 cf d5 8c e7 c9 .....2....!.....
0010 - cd 83 90 74 c8 51 76 8e-e8 d9 44 c3 80 92 ab 40 ...t.Qv...D....#
0020 - e3 .
doing iv
doing tag
getting content length: 25
copying content length to content var
iv:
0000 - ae 3f d9 92 46 54 39 93-31 64 e7 ce 98 ba 44 50 .?..FT9.1d....DP
tag:
0000 - 1d ec 89 4e ee e9 18 d9-15 e3 3d b3 e8 1b ff 10 ...N......=.....
content :
0000 - 91 e7 a5 85 28 50 09 88-cc 85 d9 3e 82 05 19 a5 ....(P.....>....
0010 - 87 f4 b2 d2 2f e5 7f 24-fd ..../..$.
AES GCM Decrypt:
Ciphertext:
0000 - 91 e7 a5 85 28 50 09 88-cc 85 d9 3e 82 05 19 a5 ....(P.....>....
0010 - 87 f4 b2 d2 2f e5 7f 24-fd ..../..$.
Plaintext:
0000 - f3 6d 72 13 d9 dd 5b a3-b6 af 73 8d a2 93 8b f7 .mr...[...s.....
0010 - 0e 9e 2a 87 6c 82 84 bd-46 ..*.l...F
outbuf: �mr��[���s������*�l���FTag Verify Failed!
I can't be 100% I'm doing it right, but anyway i'm getting Verify Failed!
Help is GREATLY appreciated!

I'm not very familiar with AES, but this code looks suspicious:
int dest_len = 4*(sizeof(source)/3);
because source is defined as:
unsigned char * source = "BASE64-ENCODED-BINARY";
and in consequence sizeof(source) gives you the size of a pointer.
Try:
int dest_len = 4*(strlen(source)/3);
or define source as:
const unsigned char source[] = "BASE64-ENCODED-BINARY";

Related

Reading Hex from an file

So my knowledge of pointers is a bit rusty and I think thats where I'm getting messed up, I am trying to write a function that will grab hex values (an amount n) at a specified offset in the file. And write those values to an array.
File I'm reading from, Example
0 1 2 3 4 5 6 7 8 9 A B C D E F
0 F6 EA 9D DE D8 40 1C 44 19 24 59 D2 6A 2C 48 1D
1 FC 96 DE 94 AF 95 FC 42 9B 6D DA 15 D4 CE 88 BB
2 B8 24 99 8F 65 B5 D3 7E D9 5D 51 44 89 97 61 85
3 2D 40 1A DC D5 16 1F 70 84 F9 85 58 C8 0E 13 80
4 32 AC 10 97 61 B3 16 3B 40 67 7A CA FE E1 4F 2B
5 21 A9 07 F6 80 26 66 04 20 EC 5C E8 FA 70 68 2C
6 1C 78 C4 7E 5C DA B9 9C 41 38 66 3F 19 B6 6A 3A
Here's the function I've written thus far.
aDest point's to an array of size nBytes + 1
bAddr point's to firstbyte of the memory region
OffsetAmt is a location which is relative bAddr
nBytes is just the number of bytes that I want to copy
Heres the function
void getHexBytesAt(uint8_t* const aDest, const uint8_t* const bAddr,
uint16_t OffsetAmt, uint8_t nBytes)
{
const uint8_t *point1 = bAddr; //set he address of point1 to base address value
//front point1 shift until we get to the specified offset value
for (int i = 0; i < Offset; i++)
{
point1 = (point1 + 1);
}
//set the values of *aDest to the value of point1;
//increment point1
for (int k = 0; k < nBytes; k++)
{
*aDest = point1;
point1 = (point1 + 1);
}
The problem I'm having is im not even getting the first byte copied into the array correctly,
My output looks like this Getting 9 bytes,
starting at the offset 2C
MY OUTPUT: 84 CA CA CA CA CA CA CA CA
FILE: 89 97 61 85 2D 40 1A DC D5
If you want to read the data from the Memory bAddr then you must
dereference the pointer for reading
increment the Destination pointer
This would be implemented like this:
void getHexBytesAt(uint8_t* const aDest, const uint8_t* const bAddr,
uint16_t OffsetAmt, uint8_t nBytes)
{
const uint8_t *point1 = bAddr; //set he address of point1 to base address value
//front point1 shift until we get to the specified offset value
for (int i = 0; i < OffsetAmt; i++) // fixed typo
{
point1 = (point1 + 1);
}
//set the values of *aDest to the value of point1;
//increment point1
for (int k = 0; k < nBytes; k++)
{
*aDest = *point1; // copy data from address the point1 points to
aDest = aDest + 1; // increment destination pointer
point1 = (point1 + 1);
}
}
But this can be done much simpler:
void getHexBytesAt(uint8_t* const aDest, const uint8_t* const bAddr,
uint16_t OffsetAmt, uint8_t nBytes)
{
memcpy(aDest, bAddr + OffsetAmt, nBytes);
}
You should consider replacing the function with the one-liner that implements it in your code.
BTW: There is no file used in the code. You should review your question.

convert hex code (in packet) to UTF-8

sturct ptr info
struct ptr { // packet struct
unsigned long srcip;
unsigned long dstip;
unsigned short srcport;
unsigned short dstport;
unsigned char *str; // payload data of packet
unsigned short len; // payload length
unsigned long ts;
};
find file path and save module code
char *msg = NULL; // to save file path
int j = 0;
/* find file path and save */
for (i=84; i < ptr->len; i++) {
if (ptr->str[i] > 0x00 && ptr->str[i] < 0x7f) {
msg[j] = ptr->str[i];
j++;
}
if (ptr->str[i] > 0x7f) {
msg[j] = 0x23;
j++;
}
}
This is file path in SMB packet, i captured on Wireshark.
0000 5c 00 e0 ac c8 b2 5c 00 73 00 65 00 63 00 72 00 \.....\.s.e.c.r.
0010 65 00 74 00 5c 00 78 c7 ac c0 2e 00 74 00 78 00 e.t.\.x.....t.x.
0020 74 00 00 00 t...
current result =
msg : \####\secret\x###.txt
I just put '#' (0x23) temporarily..
and this is what i want =
msg : \고니\secret\인사.txt
I just found "e0 ac" are part of letter '고' , "c8 b2" are part of letter '니'
But i don't know how to convert..
In sum, i want convert hex code (in packet) to UTF-8.

How to parse hex dump

I have a flash memory dump file that spits out addresses and data.
I want to parse the data so that it will tell me the valid tags
The '002F0900' column are the starting addresses.
An example of a valid tag is "DC 08 00 06 00 00 07 26 01 25 05 09" where "DC 08" = tag number, "00 06" = tag data length, "00 00" = tag version. Tag data starts after the version and in this case would be "07 26 01 25 05 09" and the next tag would start "DC 33".
I'm able to print out the first tag up to the data length but I'm not sure how to print the data because I have to consider if the data will go onto the next line so I'd have to skip the address somehow. Each line contains 58 columns. Each address is 8 characters long plus a colon and 2 spaces until the next hex value starts.
I also will eventually have to consider when "DC" shows up in the address column.
If anyone could give some advice because I know how I'm doing this isn't the best way to do this. I'm just trying to get it to work first.
The text file is thousands of lines that look like this:
002F0900: 09 FF DC 08 00 06 00 00 07 26 01 25 05 09 DC 33
002F0910: 00 07 00 00 1F A0 26 01 25 05 09 FF 9C 3E 00 08
002F0920: 00 01 07 DD 0A 0D 00 29 35 AD 9C 41 00 0A 00 01
002F0930: 07 DD 0A 0D 00 29 36 1C 1D 01 9C 40 00 02 00 01
002F0940: 01 00 9C 42 00 0A 00 01 07 DD 0A 0D 00 29 36 21
002F0950: 1D AD 9C 15 00 20 00 00 01 00 00 00 00 04 AD AE
002F0960: C8 0B C0 8A 5B 52 01 00 00 00 00 00 FF 84 36 BA
002F0970: 4E 92 E4 16 28 86 75 C0 DC 10 00 05 00 00 00 00
002F0980: 00 00 01 FF DC 30 00 04 00 01 00 00 00 01 9C 41
Example output would be:
Tag Number: DC 08
Address: 002E0000
Data Length: 06
Tag Data: 07 26 01 25 05 09
Source Code:
#include<stdio.h>
FILE *fp;
main()
{
int i=0;
char ch;
char address[1024];
char tag_number[5];
char tag_length[4];
int number_of_addresses = 0;
long int length;
fp = fopen(FILE_NAME,"rb");
if(fp == NULL) {
printf("error opening file");
}
else {
printf("File opened\n");
while(1){
if((address[i]=fgetc(fp)) ==':')
break;
number_of_addresses++;
i++;
}
printf("\nAddress:");
for (i = 0; i < number_of_addresses;i++)
printf("%c",address[i]);
while((ch = fgetc(fp)) != 'D'){ //Search for valid tag
}
tag_number[0] = ch;
if((ch = fgetc(fp)) == 'C') //We have a valid TAG
{
tag_number[1] = ch;
tag_number[2] = fgetc(fp);
tag_number[3] = fgetc(fp);
tag_number[4] = fgetc(fp);
}
printf("\nNumber:");
for(i=0;i<5;i++)
printf("%c",tag_number[i]);
fgetc(fp); //For space
tag_length[0] = fgetc(fp);
tag_length[1] = fgetc(fp);
fgetc(fp); //For space
tag_length[2] = fgetc(fp);
tag_length[3] = fgetc(fp);
printf("\nLength:");
for(i=0;i<4;i++)
printf("%c",tag_length[i]);
length = strtol(tag_length,&tag_length[4], 16);
printf("\nThe decimal equilvant is: %ld",length);
for (i = 0;i<165;i++)
printf("\n%d:%c",i,fgetc(fp));
}
fclose(fp);
}
Update #ooga:The tags are written arbitrarily. If we also consider invalid tag in the logic then I should be able to figure out the rest if I spend some time. Thanks
This is just an idea to get you started since I'm not entirely sure what you need. The basic idea is that read_byte returns the next two-digit hex value as a byte and also returns its address.
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "UA201_dump.txt"
void err(char *msg) {
fprintf(stderr, "Error: %s\n", msg);
exit(EXIT_FAILURE);
}
// read_byte
// Reads a single two-digit "byte" from the hex dump, also
// reads the address (if necessary).
// Returns the byte and current address through pointers.
// Returns 1 if it was able to read a byte, 0 otherwise.
int read_byte(FILE *fp, unsigned *byte, unsigned *addr_ret) {
// Save current column and address between calls.
static int column = 0;
static unsigned addr;
// If it's the beginning of a line...
if (column == 0)
// ... read the address.
if (fscanf(fp, "%x:", &addr) != 1)
// Return 0 if no address could be read.
return 0;
// Read the next two-digit hex value into *byte.
if (fscanf(fp, "%x", byte) != 1)
// Return 0 if no byte could be read.
return 0;
// Set return address to current address.
*addr_ret = addr;
// Increment current address for next time.
++addr;
// Increment column, wrapping back to 0 when it reaches 16.
column = (column + 1) % 16;
// Return 1 on success.
return 1;
}
int main() {
unsigned byte, addr, afterdc, length, version, i;
FILE *fp = fopen(FILE_NAME,"r");
if (!fp) {
fprintf(stderr, "Can't open %s\n", FILE_NAME);
exit(EXIT_FAILURE);
}
while (read_byte(fp, &byte, &addr)) {
if (byte == 0xDC) {
// Read additional bytes like this:
if (!read_byte(fp, &afterdc, &addr)) err("EOF 1");
if (!read_byte(fp, &length, &addr)) err("EOF 2");
if (!read_byte(fp, &byte, &addr)) err("EOF 3");
length = (length << 8) | byte;
if (!read_byte(fp, &version, &addr)) err("EOF 4");
if (!read_byte(fp, &byte, &addr)) err("EOF 5");
version = (version << 8) | byte;
printf("DC: %02X, %u, %u\n ", afterdc, length, version);
for (i = 0; i < length; ++i) {
if (!read_byte(fp, &byte, &addr)) err("EOF 6");
printf("%02X ", byte);
}
putchar('\n');
}
}
fclose(fp);
return 0;
}
Some explanation:
Every time read_byte is called, it reads the next printed byte (the two-digit hex values) from the hex dump. It returns that byte and also the address of that byte.
There are 16 two-digit hex values on each line. The column number (0 to 15) is retained in a static variable between calls. The column is incremented after reading each byte and reset to 0 every time the column reaches 16.
Any time the column number is 0, it reads the printed address, retaining it between calls in a static variable. It also increments the static addr variable so it can tell you the address of a byte anywhere in the line (when the column number is not zero).
As an example, you could use read_bye like this, which prints each byte value and it's address on a separate line:
// after opening file as fp
while (read_byte(fp, &byte, &addr))
printf("%08X- %02X\n", addr, byte);
(Not that it would be useful to do that, but to test it you could run it with the snippet you provided in your question.)

Not able to pack hex bytes into unsigned char array or pointer properly

I tried to imitate a struct with a unsigned char array or pointer, but I am not able to obtain the same hex values.
.input is correct with print().
I am trying to get the same effect from stringBytes_Data or data_hexStrFormatted with print().
Can anyone advise?
Given
struct _vector {
char *input;
unsigned char len;
};
static struct _vector tv2 = {
.input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
.len = 64,
};
And function to view the data:
static void print(char *intro_message, unsigned char *text_addr,
unsigned int size) {
unsigned int i;
for (i = 0; i < size; i++) {
printf("%2x ", text_addr[i]);
if ((i & 0xf) == 0xf)
printf("\n");
}
printf("\n");
}
How may I get the same effect with:
char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
I tried, but the result is wrong :
unsigned char* data_hexStrFormatted;
int lengthOfStr = strlen(stringBytes_Data);
int charCounterForNewStr = 0;
int formattedLength = (2*lengthOfStr)+1;
data_hexStrFormatted = (unsigned char*) malloc((formattedLength)*sizeof(unsigned char)); // x2 as we add \x to XX, and 1 for NULL end char
for(i=0; i<lengthOfStr; i=i+2) {
// prepend \x
data_hexStrFormatted[charCounterForNewStr++] = '\\';
data_hexStrFormatted[charCounterForNewStr++] = 'x';
data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i];
data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i+1];
}
data_hexStrFormatted[formattedLength-1] = '\0';
printf("%s\n", data_hexStrFormatted);
printf("%d byte length \n", strlen(data_hexStrFormatted)/4);
print("data_hexStrFormatted",
(unsigned char *)
data_hexStrFormatted,
(formattedLength)/4);
You seem to be asking:
Given a string containing pairs of hex digits, convert the hex digits to byte values?
If so, then code similar to the following can be used:
static inline int hexit(const unsigned char c)
{
static const char hex_digits[] = "0123456789ABCDEF";
return strchr(hex_digits, toupper(c)) - hex_digits;
}
This function works correctly for valid hex digits; it will produce nonsense for invalid inputs. If you decide you need to detect erroneous input, you'll need to improve it. There are other ways to write this function (lots of them, in fact). One that can be effective is an array of 256 bytes statically initialized with the correct values, so you simply write return hex_array[c];.
char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
size_t len = strlen(stringBytes_Data);
char buffer[len / 2];
assert(len % 2 == 0);
for (size_t i = 0; i < len; i += 2)
buffer[i / 2] = hexit(stringBytes_Data[i]) << 4 | hexit(stringBytes_Data[i+1]);
printf("%.*s\n", (int)len/2, buffer);
This code sets the array buffer to contain the converted code. It won't work correctly if there's an odd number of characters in the array (that's what the assertion states).
Working code - #2
Using the print() function from the question with the info_message argument removed since it is unused:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
struct Vector
{
char *input;
unsigned char len;
};
static struct Vector tv2 =
{
.input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
.len = 64,
};
static inline int hexit(const unsigned char c)
{
static const char hex_digits[] = "0123456789ABCDEF";
return strchr(hex_digits, toupper(c)) - hex_digits;
}
static void print(unsigned char *text_addr, unsigned int size)
{
unsigned int i;
for (i = 0; i < size; i++)
{
printf("%2x ", text_addr[i]);
if ((i & 0xf) == 0xf)
printf("\n");
}
printf("\n");
}
static void print2(const char *tag, const unsigned char *data, size_t size)
{
printf("%s:\n", tag);
for (size_t i = 0; i < size; i++)
{
printf("%2x ", data[i]);
if ((i & 0x0F) == 0x0F)
printf("\n");
}
printf("\n");
}
static void print_text(const char *tag, const char *data, size_t datalen)
{
char buffer[datalen / 2];
assert(datalen % 2 == 0);
for (size_t i = 0; i < datalen; i += 2)
buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);
//printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
assert(memcmp(buffer, tv2.input, tv2.len) == 0);
print((unsigned char *)buffer, datalen / 2);
print2(tag, (unsigned char *)buffer, datalen / 2);
}
int main(void)
{
char *stringBytes_Data =
"6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710"
;
print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
return 0;
}
Sample output:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
Working code - #1
Redone — previous versions had various 'off by a factor of two' errors which were partially concealed by the system zeroing a buffer.
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
struct Vector
{
char *input;
unsigned char len;
};
static struct Vector tv2 =
{
.input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
.len = 64,
};
static inline int hexit(const unsigned char c)
{
static const char hex_digits[] = "0123456789ABCDEF";
return strchr(hex_digits, toupper(c)) - hex_digits;
}
static void print(const char *tag, const unsigned char *data, size_t size)
{
printf("%s:\n", tag);
for (size_t i = 0; i < size; i++)
{
printf("%2x ", data[i]);
if ((i & 0x0F) == 0x0F)
printf("\n");
}
printf("\n");
}
static void print_text(const char *tag, const char *data, size_t datalen)
{
char buffer[datalen / 2];
assert(datalen % 2 == 0);
for (size_t i = 0; i < datalen; i += 2)
buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);
printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
assert(memcmp(buffer, tv2.input, tv2.len) == 0);
print(tag, (unsigned char *)buffer, datalen / 2);
}
int main(void)
{
char *stringBytes_Data =
"6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710"
;
print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
return 0;
}
Raw output on a UTF-8 terminal (it isn't valid UTF-8 data, hence the question marks):
buffer: [[k???.#???=~s?*?-?W????o?E??Q0?F?\????
R???$E?O??+A{?l7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
Raw output converted into UTF-8 as if it was ISO 8859-15 (or 8859-1):
buffer: [[kÁŸâ.#é=~s*®-W¬·o¬E¯Q0ÈF£\äåûÁ
Rïö$EßO­+A{æl7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
The data doesn't seem to have any particular meaning, but beauty is in the eye of the beholder.

Serialization issues while sending struct over socket

I am developing a Client/Server based on UDP I want to send different messages to the client from the server. There are different C structures defined for each message.
I would like to understand what is wrong in the way I am serializing the data.
struct Task
{
int mType;
int tType;
int cCnt;
int* cId;
char data[128];
};
Serialization/Deserialization functions
unsigned char * serialize_int(unsigned char *buffer, int value)
{
buffer[0] = value >> 24;
buffer[1] = value >> 16;
buffer[2] = value >> 8;
buffer[3] = value;
return buffer + 4;
}
unsigned char * serialize_char(unsigned char *buffer, char value)
{
buffer[0] = value;
return buffer + 1;
}
int deserialize_int(unsigned char *buffer)
{
int value = 0;
value |= buffer[0] << 24;
value |= buffer[1] << 16;
value |= buffer[2] << 8;
value |= buffer[3];
return value;
}
char deserialize_char(unsigned char *buffer)
{
return buffer[0];
}
Sender side code to serialize the structure
unsigned char* serializeTask(unsigned char* msg, const Task* t)
{
msg = serialize_int(msg,t->mType);
msg = serialize_int(msg,t->tkType);
msg = serialize_int(msg,t->cCnt);
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i*4]);
for(int i=0; i<strlen(data); i++)
msg = serialize_char(msg,t->data[i]);
return msg;
}
Receiver side code to de-serialize data
printf("Msg type:%d\n", deserialize_int(message) );
printf("Task Type:%d\n", deserialize_int(message+4) );
printf("Task Count:%d\n", deserialize_int(message+8));
Output
Msg type:50364598 //Expected value is 3
Task Type:-2013036362 //Expected value is 1
Task Count:1745191094 //Expected value is 3
Question 1:
Why is the de-serialized value not same as expected?
Question 2:
How is serialization/de-serialization method different from memcpy?
Task t;
memcpy(&t, msg, sizeof(t)); //msg is unsigned char* holding the struct data
EDIT
Code which invokes serializeTask
void addToDatabase(unsigned char* message, int msgSize, Task* task)
{
message = new unsigned char[2*msgSize+1];
unsigned char* msg = message; //To preserve start address of message
message = serializeTask(message, task); //Now message points to end of the array
//Insert serialized data to DB
//msg is inserted to DB
}
Serialized data stored in DB
Message:
00
03 70 B6 88 03 70 B6 68 05 70 B6 68 05 70 B6 00
00 00 00 00 00 00 00 A8 05 70 B6 AC 05 70 B6 B4
05 70 B6 C9 05 70 B6 DE 05 70 B6 E6 05 70 B6 EE
05 70 B6 FB 05 70 B6 64 65 66 00 63 6F 68 6F 72
74 73 00 70 65 6E 64 69 6E 67 5F 61 73 73 69 67
6E 5F 74 61 73 6B 73 00 70 65 6E 64 69 6E 67 5F
61 73 73 69 67 6E 5F 74 61 73 6B 73 00 6D 65 73
73 61 67 65 00 6D 65 73 73 61 67 65 00 3F 00 FF
FF 00 00 FC 90 00 00 00 00 00 00 00 C9 2D B7 00
00 00 00 10 06 70 B6 00 00 00 00 00 00 00 00 30
06 70 B6 34 06 70 B6 3C 06 70 B6
OP has 2 problems in serializeTask()
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i*4]); [i*4]
...
for(int i=0; i<strlen(data); i++)
msg = serialize_char(msg,t->data[i]); strlen(data)
Should be (assuming i<strlen(data) should have been i<strlen(t->data)
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i]); // [i]
...
for(int i=0; i<strlen(t->data); i++) // strlen(data) + 1
msg = serialize_char(msg,t->data[i]);
The first for loop serialize every 4th cId[]. OP certainly wanted to serialize consecutive cId[].
Only the length of the data string was serialized. OP certainly wanted to serialize all that and a NUL terminating byte.
The data in the posted buffer is more likely the below, which does not match the serialization code. This implies the higher level code populating Task* t is wrong. I am confident that the values seen in fields mType and tkType are either pointers or float, again Task* t is likely amiss before the serialization.
0xb6700300 or -3.576453e-06
0xb6700388 or -3.576484e-06
0xb6700568 or -3.576593e-06
0xb6700568 or -3.576593e-06
0x000000 or 0.000000e+00
0x000000 or 0.000000e+00
0xb67005a8 or -3.576608e-06
0xb67005ac or -3.576609e-06
0xb67005b4 or -3.576611e-06
0xb67005c9 or -3.576615e-06
0xb67005de or -3.576620e-06
0xb67005e6 or -3.576622e-06
0xb67005ee or -3.576624e-06
0xb67005fb or -3.576627e-06
def\0cohorts\0pending_assign_tasks\0pending_assign_tasks\0message\0message\0?\0
...

Resources