Discussion:
unsigned values back into byte arrays
(too old to reply)
test
2008-04-07 17:39:18 UTC
Permalink
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
test
2008-04-25 08:01:54 UTC
Permalink
Hey Lads,

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

Thanks
chenzero
2008-04-27 08:07:54 UTC
Permalink
Post by test
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];
Post by test
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')
Post by test
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 ?
Post by test
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;
}
Post by test
Can someone point me in the right direction please...
Thanks
test
2008-04-28 14:41:14 UTC
Permalink
Post by chenzero
if that 16 bytes array is binary format, then, it's ok just copy
memcpy(buf, &T4x4LongWordRecord, sizeof(T4x4LongWordRecord));
if that bytes array is ascii format, after conversion,
it needs 2 times memory.
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!
Post by chenzero
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)
Post by chenzero
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?
chenzero
2008-04-28 17:34:31 UTC
Permalink
Post by test
Post by chenzero
if that 16 bytes array is binary format, then, it's ok just copy
memcpy(buf, &T4x4LongWordRecord, sizeof(T4x4LongWordRecord));
if that bytes array is ascii format, after conversion,
it needs 2 times memory.
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!
Post by chenzero
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.
Post by test
Post by chenzero
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 :)
test
2008-04-29 06:31:38 UTC
Permalink
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!
chenzero
2008-04-29 13:27:26 UTC
Permalink
Post by test
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);
}
//---------------------------------------------------------------------------
Loading...