简体   繁体   中英

Appending an Int to a char * in C

So I am looking to append the length of a cipher text onto the end of the char array that I am storing the cipher in. I am not a native to C and below is a test snippet of what I have devised that I think works.

...
int cipherTextLength = 0;
unsigned char *cipherText = NULL;
...
EVP_EncryptFinal_ex(&encryptCtx, cipherText + cipherTextLength, &finalBlockLength);
cipherTextLength += finalBlockLength;
EVP_CIPHER_CTX_cleanup(&encryptCtx);

// Append the length of the cipher text onto the end of the cipher text
// Note, the length stored will never be anywhere near 4294967295 
char cipherLengthChar[1];
sprintf(cipherLengthChar, "%d", cipherTextLength);
strcat(cipherText, cipherLengthChar);
printf("ENC - cipherTextLength: %d\n", cipherTextLength);
...

The problem is I don't think using strcat when dealing with binary data is going to be trouble free. Could anyone suggest a better way to do this?

Thanks!

EDIT

Ok, so I'll add a little context as to why I was looking to append the length. In my encrypt function, the function EVP_EncryptUpdate requires the length of the plainText being encrypted. As this is much more easy to obtain, this part isn't a problem. However, similarly, using EVP_DecryptFinal_ex in my decrypt function requires the length of the ciperText being decrypted, so I need to store it somewhere.

In the application where I am implementing this, all I am doing is changing some poor hashing to proper encryption. To add further hassle, the way the application is I first need to decrypt information read in from XML, do something with it, then encrypt it and rewrite it to XML again, so I need to have this cipher length stored in the cipher somehow. I also don't have scope to redesign this.

I hope you are having enough big arrays both for cipherText and cipheLegthChar to store the required text. Hence instead of

unsigned char *cipherText = NULL;

You can have

unsigned char cipherText[MAX_TEXT];

similarly for

cipherLenghthChar[MAX_INT];

Or you can have them dynamically allocated.

where MAX_TEXT and MAX_INT max buffer size to store text and integer. Also after first call of EVP_EncryptFinal_ex NULL terminate cipherText so that you strcat works.

The problem is I don't think using strcat when dealing with binary data is going to be trouble free.

Correct! That's not your only problem though:

// Note, the length stored will never be anywhere near 4294967295 
char cipherLengthChar[1];
sprintf(cipherLengthChar, "%d", cipherTextLength);

Even if cipherTextLength is 0 here, you've gone out of bounds, since sprintf will add a null terminator, making a total of two chars -- but cipherLengthChar only has room for one. If you consider, eg 4294967295, as a string, that's 10 chars + '\\0' = 11 chars.

It would appear that finalBlockLength is the length of the data put into cipherText . However, the EVP_EncryptFinal_ex() call will probably fail in one way or another, or at least not do what you want, since cipherText == NULL . You then add 0 to that (== 0 aka. still NULL) and submit it as a parameter. Either you need a pointer to a pointer there (if EVP_EncryptFinal_ex is going to allocate space for you), or else you have to make sure there is enough room in cipherText to start with.

With regard to tacking text (or whatever) onto the end, you can just use sprintf directly:

sprintf(cipherText + finalBlockLength, "%d", cipherTextLength);

Presuming that cipherText is non-NULL and has enough extra room in it (see first couple of paragraphs).

However, I'm very dubious that doing that will be useful later on, but since I don't have any further context, I can't say more.

Instead of what you are doing now, it may be smarter to encode the ciphertext size to a location before the ciphertext itself. Once you start decrypting, it is not very useful to find the size at the end. You need to know the end to get the size to find the end, not very helpful.

Furthermore, the ciphertext is binary, so you don't need to convert anything to string. You would like to convert it to a fixed number of bytes (otherwise you don't know the size of the size :P ). So create a bigger buffer (4 bytes more than you require for the ciphertext), and start encrypting to offset 4 forwards. Then copy the size of the ciphertext in at the start of the buffer.

If you don't know how to encode an integer, take a look at - for instance - this question/ answer . Note, this will only encode 32 bits for a maximum size of the ciphertext of 2^32 , about 4 GiB. Furthermore, the link pointed to use Big Endian encoding. You should use either Big Endian (preferred for crypto code) or Little Endian encoding - but don't mix the two.

Neither the ciphertext nor the encoded size should be used as a character string. If you need a character string, my suggestion is to base 64 encode the buffer up to the end of the ciphertext.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM