XOR and String

  • Thread starter Thread starter Adriano
  • Start date Start date
A

Adriano

Hello,

I have the following string headers:

Header 1, 2, 3, 4:

1.00TJ123456PPC
00000000DLGLGN
00000001TXBEG
Login:user=a, pswd=a"

As written in documentation, the checksum is "a negative value of the result
of an exclusive or operation of 'Header1 + Header2 + Header3 + Header4' in
32-digit format". The result is something like B8DEA5DC (8 digit hex.)
I would really appreciate if someone could help me on that, by examples,
anyhow.

Thanks in advance,
Adrano.
 
Adriano said:
Hello,

I have the following string headers:

Header 1, 2, 3, 4:

1.00TJ123456PPC
00000000DLGLGN
00000001TXBEG
Login:user=a, pswd=a"

As written in documentation, the checksum is "a negative value of the
result of an exclusive or operation of 'Header1 + Header2 + Header3 +
Header4' in 32-digit format". The result is something like B8DEA5DC (8
digit hex.)
I would really appreciate if someone could help me on that, by examples,
anyhow.

Thanks in advance,
Adrano.

I don't know what kind of format the documentation is meaning. I
searched for "32-digit format", and the few occurances that I found were
either totally unrelated or typos. It's possible that there is some 32
bit format, that would correspond with the format of the checksum, but
there is no logical way to interpret the strings as 32 bit values.

You have to find out how the text is interpreted as numbers, and how the
numbers are arranged and calculated.

Using an 8 bit character encoding, you can decode each character to an 8
bit value, but you have to arrange them into some larger entities. If
you simply xor the character codes and then add the result from each
header, you end up with a 10 bit number, not the 32 bit number needed to
fill up the 8 digit hexadecimal representation.
 
One possible procedure that makes partial sense for that description is:

Working from the start of each header, take one character from each string,
Combine them into a 32 bit value (ie, 4 characters at 8 bits each by bitwise
concatenation - left to right). Then XOR each 32-bit value. The strings are
assumed to be left-aligned, and missing characters are assumed to have a bit
value of zero.

The following Sub implements the above rule

Note that I have not attempted to work out what "a negative value of the
result" might mean. Does it mean the two's complement, or is it simply
confirming tha tthe result could be a negative number? You will need to get
some actual examples of headers and checksums then do a bitwise comparison
to the results of this operation to see what 'negative value' might mean
(assuming, of course, that this process correctly implements what the rest
of the description means).

Dim a(3) As String
Dim v(3) As Byte
a(0) = TextBox1.Text
a(1) = TextBox2.Text
a(2) = TextBox3.Text
a(3) = TextBox4.Text
Dim flag = True
Dim k As Integer = 0
While flag
flag = False
For i = 0 To 3
v(i) = 0
If a(i) <> "" Then
flag = True
v(i) = BitConverter.GetBytes(CChar(a(i)))(0)
a(i) = a(i).Substring(1)
End If
Next
If flag Then
k = k Xor BitConverter.ToInt32(v, 0)
End If
End While
TextBox5.Text = Hex(k).PadLeft(8, "0")
 
Hello James,

Many thanks for your reply. I tried your example, but it does not produce
the correct checksum. Maybe I was wrong in explaining situation, sorry for
my bad English! See what they gave me for checking if I'm generating correct
packet and checkum:
2008-09-30 11:35:00 `SC`00541.00TJ123456PPC 00000000DLGLGN
00000001TXBEG Login:user=mmlos, pswd=osmp 9afb81c7
Complete description of the packet is here:
http://www.epay.tj/img/MML-Packets.jpg
The packet I created seems okay, remote server is responding, now I get
"checksum error".
I'd really appreciate if you could help me to solve this headache.

Thanks in advance,
Adriano
 
I think you have sufficient example code to solve the problem. What you now
need is a proper description of the algorithm. The description provided at
the page you have referenced is not a complete description by any means. As
mentioned, I have no idea what "a negative value of the result" might mean,
and that's obviously going to be important in getting the correct answer.
Also, it is purely guesswork that my bit concatenation is what is meant by
"'Header1 + Header2 + Header3 + Header4' in 32-digit format".

Without a proper specification of the problem it's not possible to provide a
comprehensive answer.
 
This is the sort of thing that drives me crazy...

So I did it for you.

I just had to fudge the result by "-1" to get it right, probably something
to do with how the two's-complement is used.

Note the the input strings have to be padded with spaces to conform to the
packet description. The spaces have been removed here by Outlook express
(GRRR)

Have fun working out how it works.

Public Class Form1
Dim MessageHeader As String = "1.00TJ123456PPC " '20 bytes
Dim SessionHeader As String = "00000000DLGLGN " '18 bytes
Dim TransactionHeader As String = "00000001TXBEG " '18 bytes
Dim OpInfo As String = "Login:user=mmlos, pswd=osmp " 'N bytes, where N
is a multiple of 4 (probably pad it to 4 byte boundary?)
Dim targetChecksum As String = "9afb81c7"

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim MessageForXOR As String
Dim Hash As String
MessageForXOR = MessageHeader & SessionHeader & TransactionHeader &
OpInfo
If MessageForXOR.Length \ 4 <> MessageForXOR.Length / 4 Then
MessageBox.Show("Incorrect length") 'Message is not a multiple
of 4 bytes
Else
Hash = CalcHash(MessageForXOR, 4)
MsgBox(Hash)
End If
End Sub

Private Function CalcHash(ByVal StringToHash As String, ByVal Bytes As
Int16) As String
Dim I As Integer
Dim J As Integer
Dim Dummy As Int32
Dim Result As Int32
Dim temp As Int32
If Bytes > 4 Then Return "overflow"
For I = 0 To Len(StringToHash) - 1 Step Bytes 'step along the string
in chunks of Bytes
Dummy = 0
For J = Bytes - 1 To 0 Step -1 ' Build a "Bytes" long
representation of the chunk
' extract the byte we're interested in
temp = Asc(StringToHash.Substring(I + (Bytes - J - 1), 1))
' shift bits to left
temp = temp << 8 * J
' add to running total for this block
Dummy = Dummy + temp
Next J
If I = 0 Then ' first block, noting to xor with
Result = Dummy
Else ' subsequent blocks, xor with running hash for the message
Result = Result Xor Dummy
End If
Next I
Result = -Result - 1 'take the negative
Return Conversion.Hex(Result)
End Function
End Class
 
Thank you very much Clive!

I really appreciate your help, that's really working!!!

Adriano
 
Clive said:
This is the sort of thing that drives me crazy...

So I did it for you.

I just had to fudge the result by "-1" to get it right, probably something
to do with how the two's-complement is used.

Note the the input strings have to be padded with spaces to conform to the
packet description. The spaces have been removed here by Outlook express
(GRRR)

Have fun working out how it works.

Public Class Form1
Dim MessageHeader As String = "1.00TJ123456PPC " '20 bytes
Dim SessionHeader As String = "00000000DLGLGN " '18 bytes
Dim TransactionHeader As String = "00000001TXBEG " '18 bytes
Dim OpInfo As String = "Login:user=mmlos, pswd=osmp " 'N bytes, where N
is a multiple of 4 (probably pad it to 4 byte boundary?)
Dim targetChecksum As String = "9afb81c7"

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim MessageForXOR As String
Dim Hash As String
MessageForXOR = MessageHeader & SessionHeader & TransactionHeader &
OpInfo
If MessageForXOR.Length \ 4 <> MessageForXOR.Length / 4 Then
MessageBox.Show("Incorrect length") 'Message is not a multiple
of 4 bytes
Else
Hash = CalcHash(MessageForXOR, 4)
MsgBox(Hash)
End If
End Sub

Private Function CalcHash(ByVal StringToHash As String, ByVal Bytes As
Int16) As String
Dim I As Integer
Dim J As Integer
Dim Dummy As Int32
Dim Result As Int32
Dim temp As Int32
If Bytes > 4 Then Return "overflow"
For I = 0 To Len(StringToHash) - 1 Step Bytes 'step along the string
in chunks of Bytes
Dummy = 0
For J = Bytes - 1 To 0 Step -1 ' Build a "Bytes" long
representation of the chunk
' extract the byte we're interested in
temp = Asc(StringToHash.Substring(I + (Bytes - J - 1), 1))
' shift bits to left
temp = temp << 8 * J
' add to running total for this block
Dummy = Dummy + temp
Next J
If I = 0 Then ' first block, noting to xor with
Result = Dummy
Else ' subsequent blocks, xor with running hash for the message
Result = Result Xor Dummy
End If
Next I
Result = -Result - 1 'take the negative
Return Conversion.Hex(Result)
End Function
End Class

Nice work. :)

Let's clean up the code a bit. Making it always put four bytes in an int
makes the code simpler. Initialising the result removes the need to
check if it's the first block.

Private Function CalcHash(ByVal stringToHash As String) As String
' get character codes into an array
Dim chars As Byte() = Encoding.ASCII.GetBytes(stringToHash)
Dim result As Integer = 0
'step along the string in chunks of bytes
For i As Integer = 0 To chars.Length - 1 Step 4
' get 4 bytes as an int and xor into the result
result = result Xor BitConverter.ToInt32(chars, i)
Next
' get the negative result, no idea where the extra -1 comes from
result = -result - 1
' make sure that the resulting string is always 8 hex digits
Return result.ToString("x8")
End Function
 
Göran Andersson said:
Nice work. :)

Let's clean up the code a bit. Making it always put four bytes in an int
makes the code simpler. Initialising the result removes the need to check
if it's the first block.

Private Function CalcHash(ByVal stringToHash As String) As String
' get character codes into an array
Dim chars As Byte() = Encoding.ASCII.GetBytes(stringToHash)
Dim result As Integer = 0
'step along the string in chunks of bytes
For i As Integer = 0 To chars.Length - 1 Step 4
' get 4 bytes as an int and xor into the result
result = result Xor BitConverter.ToInt32(chars, i)
Next
' get the negative result, no idea where the extra -1 comes from
result = -result - 1
' make sure that the resulting string is always 8 hex digits
Return result.ToString("x8")
End Function

Nicely done Göran,
After I had posted I was wondering how to grab 4 bytes at a time (I'm fairly
new to .Net), now I know.
 
Back
Top