Board index » cppbuilder » unsigned values back into byte arrays

unsigned values back into byte arrays


2008-04-08 01:39:18 AM
cppbuilder31
Hi,
I'm getting a MD4 hash which is stored as either 4 unsigned
ints or a string
typedef unsigned LongWord; // 0..4294967295
typedef System::StaticArray<LongWord, 4>T4x4LongWordRecord;
T4x4LongWordRecord
or
AnsiString (Hex format)
I need to put this hash/hash string into a 16 byte array but am
clueless as to where to start.
I have a few other hashes that I get from 16 byte arrays using
the following functions
byte* buf11 = new byte[16];
ReadFile(fl, buf11, 16);
AnsiString Hash = byteHashToString(buf11, 16);
...
long __fastcall TForm1::byteToLong(byte* number, byte size)
{
long retorno = 0;
for(int i=0;i<size;i++)
{
if(number[i]>=0)
retorno += (number[i]*pow(256,i));
else
retorno += ((256+number[i])*pow(256,i));
}
return retorno;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TForm1::byteHashToString(byte* temp, byte size)
{
AnsiString retorno = "";
AnsiString tempStr = "";
byte* pedacito = new byte[1];
for(int i=0;i<size;i++)
{
pedacito[0] = temp[i];
tempStr = IntToHex((int)byteToLong(pedacito, 1), 2);
if (tempStr.Length()<2)
retorno += "0" + tempStr;
else
retorno += tempStr;
}
delete [] pedacito;
return retorno;
}
Can someone point me in the right direction please...
Thanks
 
 

Re:unsigned values back into byte arrays

Hey Lads,
Any pointers as to what I should be looking into inorder to get the result I'm after?
Thanks
 

Re:unsigned values back into byte arrays

"test" < XXXX@XXXXX.COM >写入消息新闻:47fa5c46$ XXXX@XXXXX.COM ...
Quote

Hi,

I'm getting a MD4 hash which is stored as either 4 unsigned
ints or a string


typedef unsigned LongWord; // 0..4294967295
typedef System::StaticArray<LongWord, 4>T4x4LongWordRecord;

I seldom use StaticArray, so, I assume it's equal to:
LongWord T4x4LongWordRecord[4];
Quote
T4x4LongWordRecord

or

AnsiString (Hex format)



I need to put this hash/hash string into a 16 byte array but am
clueless as to where to start.
if that 16 bytes array is binary format, then, it's ok just copy
T4x4LongWordRecord to a 16 bytes array, eg:
memcpy(buf, &T4x4LongWordRecord, sizeof(T4x4LongWordRecord));
if that bytes array is ascii format, after conversion,
it needs 2 times memory.
eg:
byte b = 0x01;// it just needs only 1 byte memory
ascii string
char* asciiB = "01"; // it needs 2 bytes memory (ignore the tail '\0')
Quote


I have a few other hashes that I get from 16 byte arrays using
the following functions

so, if to save a 16 bytes value, after convert to ascii,
it will need 32 bytes to hold the 16 binary value.
does the file use the binary format to save the hash value ?
Quote
byte* buf11 = new byte[16];
ReadFile(fl, buf11, 16);
AnsiString Hash = byteHashToString(buf11, 16);
...
long __fastcall TForm1::byteToLong(byte* number, byte size)
{
long retorno = 0;

for(int i=0;i<size;i++)
{
if(number[i]>=0)
retorno += (number[i]*pow(256,i));
else
retorno += ((256+number[i])*pow(256,i));
}

return retorno;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TForm1::byteHashToString(byte* temp, byte size)
{
AnsiString retorno = "";
AnsiString tempStr = "";
byte* pedacito = new byte[1];

for(int i=0;i<size;i++)
{
pedacito[0] = temp[i];
tempStr = IntToHex((int)byteToLong(pedacito, 1), 2);

if (tempStr.Length()<2)
retorno += "0" + tempStr;
else
retorno += tempStr;
}

delete [] pedacito;

return retorno;
}

consider use following code:
AnsiString __fastcall TForm1::byteHashToString(byte* temp, byte size)
{
AnsiString retorno = "";
AnsiString tempStr = "";
byte pedacito;
for(int i=0;i<size;i++)
{
pedacito = temp[i];
tempStr = IntToHex((int)pedacito , 2);
if (tempStr.Length()<2)
retorno += "0" + tempStr;
else
retorno += tempStr;
}
return retorno;
}
Quote

Can someone point me in the right direction please...

Thanks

 

{smallsort}

Re:unsigned values back into byte arrays

"chenzero" < XXXX@XXXXX.COM >wrote:
Quote
if that 16 bytes array is binary format, then, it's ok just copy
T4x4LongWordRecord to a 16 bytes array, eg:
memcpy(buf, &T4x4LongWordRecord, sizeof(T4x4LongWordRecord));

if that bytes array is ascii format, after conversion,
it needs 2 times memory.
eg:
byte b = 0x01;// it just needs only 1 byte memory
ascii string
char* asciiB = "01"; // it needs 2 bytes memory (ignore the tail '\0')

I ended up using
T4x4LongWordRecord tmp;
...
byte* b = new byte[16];
memcpy(b, &tmp.data, sizeof(tmp.data));
and it works great, thanks for the tips!
Quote

so, if to save a 16 bytes value, after convert to ascii,
it will need 32 bytes to hold the 16 binary value.
does the file use the binary format to save the hash value ?
yes.
I'm still having a bit of a problem trying to convert the hash
string into either a T4x4LongWordRecord or a byte[16] array.
as in
void__fastcall TForm1::StringTobyteHash(AnsiString Hash, byte* byteHash)
or
void __fastcall TForm1::StringTobyteHash(AnsiString Hash, T4x4LongWordRecord* byteHash)
Quote
consider use following code:

AnsiString __fastcall TForm1::byteHashToString(byte* temp, byte size)
{
AnsiString retorno = "";
AnsiString tempStr = "";
byte pedacito;

for(int i=0;i<size;i++)
{
pedacito = temp[i];
tempStr = IntToHex((int)pedacito , 2);

if (tempStr.Length()<2)
retorno += "0" + tempStr;
else
retorno += tempStr;
}
return retorno;
}

isn't this just a better version of the orignal code?
 

Re:unsigned values back into byte arrays

"test" < XXXX@XXXXX.COM >写入消息新闻:4815e20a$ XXXX@XXXXX.COM ...
Quote

"chenzero" < XXXX@XXXXX.COM >wrote:

>if that 16 bytes array is binary format, then, it's ok just copy
>T4x4LongWordRecord to a 16 bytes array, eg:
>memcpy(buf, &T4x4LongWordRecord, sizeof(T4x4LongWordRecord));
>
>if that bytes array is ascii format, after conversion,
>it needs 2 times memory.
>eg:
>byte b = 0x01;// it just needs only 1 byte memory
>ascii string
>char* asciiB = "01"; // it needs 2 bytes memory (ignore the tail
>'\0')
>


I ended up using

T4x4LongWordRecord tmp;
...
byte* b = new byte[16];
memcpy(b, &tmp.data, sizeof(tmp.data));

and it works great, thanks for the tips!

>
>so, if to save a 16 bytes value, after convert to ascii,
>it will need 32 bytes to hold the 16 binary value.
>does the file use the binary format to save the hash value ?

yes.

I'm still having a bit of a problem trying to convert the hash
string into either a T4x4LongWordRecord or a byte[16] array.

as in

void__fastcall TForm1::StringTobyteHash(AnsiString Hash, byte* byteHash)

or

void __fastcall TForm1::StringTobyteHash(AnsiString Hash,
T4x4LongWordRecord* byteHash)
I think the problem is brought by the trick between the binary and the
string(ascii) format.
for binary format byte array, it can contain any values,
but for a string format byte array, it can not contain a specail char '\0'
since
this char is used to indicate the tail of the string. ('\0' == 0 )
so, to convert a binary byte array (the hash value) to a string (string
format byte array)
and not lost any data, other approach needs to choose instread of directly
memcpy.
one choice is ,
convert the binary byte array to hex string, eg,
[0x1, 0x2, 0x0, 0x4] -->
"01020004" which equals to the string byte array:['0','1', '0','2','0','0',
'0','4'] (ignore the last '\0')
if the file is really saving things in binary format, then there is not need
this conversion.
Hope this help.
Quote


>consider use following code:
>
>AnsiString __fastcall TForm1::byteHashToString(byte* temp, byte size)
>{
>AnsiString retorno = "";
>AnsiString tempStr = "";
>byte pedacito;
>
>for(int i=0;i<size;i++)
>{
>pedacito = temp[i];
>tempStr = IntToHex((int)pedacito , 2);
>
>if (tempStr.Length()<2)
>retorno += "0" + tempStr;
>else
>retorno += tempStr;
>}
>return retorno;
>}
>


isn't this just a better version of the orignal code?
yes :)

 

Re:unsigned values back into byte arrays

Hey chenzero,
Thanks again for the pointers!
I think I didn't explain the result I after right as there
still a little confusion.
Reading from my database file I get my hash in byte[16] format
I then convert this into user readable from using the
byteHashToString() function.
If I get a hash of a new file I get it in 4 unsigned's format
which I then convert to readable format using an indy
component.
byte[16] to Hash
or
4 unsigned's to Hash
eg. (4 unsigned's)
1977224294
1379868071
2551413036
2395249891
660CDA75A71D3F522C791398E39CC48E
I am now able to get the 4 unsigneds into the byte[16] format
to store in my database file thanks to your feedback but I
still can't get the Hash back to either the byte[16] format or
the 4 unsignes's format.
Some of the hashes I have are just stored as readable format
so I can't add these to my database unless I can figure out
the correct convertion to get them into the byte[16] format.
Thanks again!
 

Re:unsigned values back into byte arrays

"test" < XXXX@XXXXX.COM >写入消息新闻:4816c0ca$ XXXX@XXXXX.COM ...
Quote

Hey chenzero,
Hi test, :)

Hope following code is what you want.
/**
* convert char(ascii) to hex
*/
byte charToByte(char c)
{
if (c>='0' && c<='9') {
return c-'0';
}
else if (c>='A' && c<='F') {
return c-'A'+10;
}
else if (c>='a' && c<='f') {
return c-'a'+10;
}
throw Exception("invalid hash string");
}
/**
* convert 2 digits hex string to byte
*/
byte __fastcall convert2DigitsToByte(AnsiString str)
{
byte ret = charToByte(str[1]);
ret = ret*16 + charToByte(str[2]);
return ret;
}
/**
* convert hex string to byte hash
*/
void __fastcall stringToByteHash(AnsiString str, byte* buf, int size)
{
str = str.Trim();
if (str.Length()!= size*2 || buf==NULL ) {
throw Exception("invalid parameter");
}
AnsiString t;
// convert each 2 digits to byte
for(int i=0;i<size;i++) {
t = str.SubString(i*2+1, 2);
buf[i] = convert2DigitsToByte(t);
}
}
// some test code
void __fastcall TForm1::Button2Click(TObject *Sender)
{
const int LEN=16;
byte x[LEN] = {0};
stringToByteHash("660CDA75A71D3F522C791398E39CC48E", x, LEN);
AnsiString t = byteHashToString(x,LEN);
ShowMessage(t);
}
//---------------------------------------------------------------------------