0

I have a unsigned int[16] array that when printed out looks like this:

4418703544ED3F688AC208F53343AA59

The code used to print it out is this:

for (i = 0; i < 16; i++)
    printf("%X", CipherBlock[i] / 16), printf("%X",CipherBlock[i] % 16);
printf("\n");

I need to pass this unsigned int array "CipherBlock" into a decrypt() method that only takes unsigned char *. How do correctly memcpy everything from the "CipherBlock" array into an unsigned char array without losing information?

My understanding is an unsigned int is 4 bytes and unsigned char 1 byte. Since "CipherBlock" is 16 unsigned integers, the total size in bytes = 16 * 4 = 64 bytes. Does this mean my unsigned char[] array needs to be 64 in length?

If so, would the following work?

unsigned char arr[64] = { '\0' };
memcpy(arr,CipherBlock,64); 

This does not seem to work. For some reason it only copies the the first byte of "CipherBlock" into "arr". The rest of "arr" is '\0' thereafter.

user1068636
  • 1,871
  • 7
  • 33
  • 57
  • Apparently, only the least 8 bits of each element `CipherBlock[i]` matter, so they are not arbitrary ints (or their 24 highest bits don't matter to you). – Basile Starynkevitch Sep 09 '12 at 20:55
  • 1
    Is your `decrypt` function specified to accept arbitrary zero terminated strings, or can it only accept hex string (with hex digit in ASCII)? – Basile Starynkevitch Sep 09 '12 at 20:56
  • @Basile Starynkevitch: That's the question. What are we passing in the form of an `unsigned char*`? (See my answer for speculations.) – aib Sep 09 '12 at 21:45
  • I think the question is inadequately specified. There are several different ways to convert or reinterpret 16 `unsigned int` values as a number of `unsigned char` values, and it's not possible to tell from the question which one you want. For example, you don't say whether you want the first `unsigned char` in `arr` to represent the most significant 8 bits of the first `unsigned int`, or the least significant 8 bits, or something else. It rather depends how the CipherBlock was generated and transmitted to you in the first place. – Steve Jessop Sep 09 '12 at 22:24
  • 1
    Regarding your observation that `memcpy` with a last argument of 64 only copies one byte -- on the face of it this is impossible, there must be some bug in the code you've left out. – Steve Jessop Sep 09 '12 at 22:26

3 Answers3

2

Why don't you just cast the CipherBlock pointer to unsigned char * and pass that?

decrypt((unsigned char *)CipherBlock);
Kent
  • 1,691
  • 4
  • 19
  • 27
  • As @James has suggested, this will be wrong unless `decrypt()` actually expects a pointer to an unsigned int array cast to a pointer to unsigned char. The only way to decode this would be to cast the pointer back to an `unsigned int*` (in which case asking for an `unsigned char*` would be pointless) or be very, very sure of the underlying representation and decode the ints byte by byte (error prone and quite as unnecessary). – aib Sep 09 '12 at 21:43
  • Though this is the correct reduction of the code in the question's body. – aib Sep 09 '12 at 21:47
  • Yes. He doesn't mention what type the underlying data is. The int's could be ASCII chars, 16-bit Unicode chars, or a mish-mash data struct. His routine to print out the hex values is also wrong because it doesn't take into account leading zeros. – Kent Sep 09 '12 at 21:53
2

An int is at least 16 bits, same as a short in that regard.

It looks like every unsigned int has values 0-255 or 00-FF in your case, which is a safe range for an unsigned char. However, the proper way to convert one to the other is a cast:

for (int i=0; i<16; ++i) arr[i] = (unsigned char) CipherBlock[i];

But you have not specified what kind of data decrypt() expects. From the signature, I suspect integral data (strings are usually char* or const char*) but it's hard to be sure without a context.

Note that you could also do printf("%02X", CipherBlock[i]); for printing.

aib
  • 45,516
  • 10
  • 73
  • 79
1

You need to repack the numbers so you can not use memcpy or cast it directly. Aib has it correct.

unsigned char array[16];
for(int i = 0; i < 16; i++) {
    array[i] = CipherBlock[i];
}
James
  • 1,341
  • 7
  • 13
  • What? No, it indicates that CipherBlock[i] holds the value verbatim. The encoding is probably 4 bytes 2's complement little endian, which means the value is in the first byte and the other 3 are either 00 or FF. – aib Sep 09 '12 at 21:21
  • @aib Yea you are right. I was thinking shift by 16 instead of divide by 16 (which is shift by 4). – James Sep 09 '12 at 21:26
  • @aib Still can not use memcpy. Your answer is correct, but I can't up vote. Sorry. – James Sep 09 '12 at 21:32
  • Note that there are (at least) two characters printed per CipherBlock element. The first two are 44, meaning CB[0]/16 = 4 and CB[0]%16 = 4. That would give it value 0x44 or 0x00000044. If there were more than 32 characters, that would make at least one element >FF and throw all bets off. – aib Sep 09 '12 at 21:33
  • s'ok. We all occasionally get thrown off by all this bit mangling :) – aib Sep 09 '12 at 21:37
  • Agree. You need to comment on the up voted answer which is wrong. – James Sep 09 '12 at 21:37