1. #### BNLS Checksum Algorithm

Ok, this is one of the most important parts of my application and it is becoming very hard to translate. This code is needed for my bot, otherwise, it will not connect. I would like to know if the following code can be easily (or anyway) translated into Python. I'm not saying you have to do this for me unless you wan't to, this has just become very hard to accomplish. The following code is C++. I also have this code in VB6 and C# incase anyone would like to see that instead.

Here is some information about the BNLS Checksum:
The BNLS checksum algorithm calculates the checksum of a password using the 32-bit server code received in BNLS_AUTHORIZE (0x0e). You should create the BNLS checksum as follows:
Create an ANSI string whose length is the length of the password + 8 characters.
Copy the password to the beginning. (Note that the password is case sensitive.)
In the last 8 characters, store the hexadecimal representation of the server code, in uppercase, padded with zeroes on the left.
Calculate the standard CRC-32 checksum (using the standard polynomial 0xEDB88320) of the string. The result is the BNLS checksum, to be sent in BNLS_AUTHORIZEPROOF (0x0f).

[C++]
Code:
```#define CRC32_POLYNOMIAL 0xEDB88320
unsigned long CRC32Table[256];

void InitCRC32()
{
static bool CRC32Initialized = false;
if(CRC32Initialized)
return;
CRC32Initialized = true;

for(unsigned long I = 0; I < 256; I++) {
unsigned long K = I;
for(unsigned long J = 0; J < 8; J++)
K = (K >> 1) ^ ((K & 1) ? CRC32_POLYNOMIAL : 0);
CRC32Table[I] = K;
}
}

unsigned long CRC32(unsigned char* Data, unsigned long Size)
{
InitCRC32();

unsigned long CRC = 0xffffffff;
while(Size--)
CRC = (CRC >> 8) ^ CRC32Table[(CRC & 0xff) ^ *Data++];
return ~CRC;
}

inline unsigned char Hex(unsigned char Digit)
{
if(Digit < 10)
return Digit + '0';
else
return Digit - 10 + 'A';
}

unsigned long BNLSChecksum(const char* Password, unsigned long ServerCode)
{
unsigned long Size = (unsigned long)strlen(Password);
unsigned char* Data = new unsigned char[Size + 8];
unsigned long I = 7;
do {
Data[Size + I] = Hex((unsigned char)ServerCode & 0xf);
ServerCode >>= 4;
}
while(I--);

unsigned long Checksum = CRC32(Data, Size + 8);
delete[] Data;
return Checksum;
}```
Update: I figured I'd just add the rest of the languages as well (remember, I did not created this code).

[C#]
Code:
```using System;

namespace Project1
{
/// <summary>
/// Summary description for BNLSChecksumCls 1.03.
///
///
/// My representation of the CRC32 in C#
/// this is horible get a real language.
///
/// 1.03 { Removed CRCTables and added a conversion of Yoni's VB InitCRC.,
/// 1.02 { N/A }
/// 1.01 { N/A }
/// 1.00 { N/A }
/// </summary>
public class BNLSChecksumCls
{
public BNLSChecksumCls()
{
//
// TODO: Add constructor logic here
//
}
static string[] HexValues = {   "00" ,"01" ,"02" ,"03" ,"04" ,"05" ,"06" ,"07" ,"08" ,"09" ,"0A" ,"0B" ,"0C" ,"0D" ,
"0E" ,"0F" ,"10" ,"11" ,"12" ,"13" ,"14" ,"15" ,"16" ,"17" ,"18" ,"19" ,"1A" ,"1B" ,
"1C" ,"1D" ,"1E" ,"1F" ,"20" ,"21" ,"22" ,"23" ,"24" ,"25" ,"26" ,"27" ,"28" ,"29" ,
"2A" ,"2B" ,"2C" ,"2D" ,"2E" ,"2F" ,"30" ,"31" ,"32" ,"33" ,"34" ,"35" ,"36" ,"37" ,
"38" ,"39" ,"3A" ,"3B" ,"3C" ,"3D" ,"3E" ,"3F" ,"40" ,"41" ,"42" ,"43" ,"44" ,"45" ,
"46" ,"47" ,"48" ,"49" ,"4A" ,"4B" ,"4C" ,"4D" ,"4E" ,"4F" ,"50" ,"51" ,"52" ,"53" ,
"54" ,"55" ,"56" ,"57" ,"58" ,"59" ,"5A" ,"5B" ,"5C" ,"5D" ,"5E" ,"5F" ,"60" ,"61" ,
"62" ,"63" ,"64" ,"65" ,"66" ,"67" ,"68" ,"69" ,"6A" ,"6B" ,"6C" ,"6D" ,"6E" ,"6F" ,
"70" ,"71" ,"72" ,"73" ,"74" ,"75" ,"76" ,"77" ,"78" ,"79" ,"7A" ,"7B" ,"7C" ,"7D" ,
"7E" ,"7F" ,"80" ,"81" ,"82" ,"83" ,"84" ,"85" ,"86" ,"87" ,"88" ,"89" ,"8A" ,"8B" ,
"8C" ,"8D" ,"8E" ,"8F" ,"90" ,"91" ,"92" ,"93" ,"94" ,"95" ,"96" ,"97" ,"98" ,"99" ,
"9A" ,"9B" ,"9C" ,"9D" ,"9E" ,"9F" ,"A0" ,"A1" ,"A2" ,"A3" ,"A4" ,"A5" ,"A6" ,"A7" ,
"A8" ,"A9" ,"AA" ,"AB" ,"AC" ,"AD" ,"AE" ,"AF" ,"B0" ,"B1" ,"B2" ,"B3" ,"B4" ,"B5" ,
"B6" ,"B7" ,"B8" ,"B9" ,"BA" ,"BB" ,"BC" ,"BD" ,"BE" ,"BF" ,"C0" ,"C1" ,"C2" ,"C3" ,
"C4" ,"C5" ,"C6" ,"C7" ,"C8" ,"C9" ,"CA" ,"CB" ,"CC" ,"CD" ,"CE" ,"CF" ,"D0" ,"D1" ,
"D2" ,"D3" ,"D4" ,"D5" ,"D6" ,"D7" ,"D8" ,"D9" ,"DA" ,"DB" ,"DC" ,"DD" ,"DE" ,"DF" ,
"E0" ,"E1" ,"E2" ,"E3" ,"E4" ,"E5" ,"E6" ,"E7" ,"E8" ,"E9" ,"EA" ,"EB" ,"EC" ,"ED" ,
"EE" ,"EF" ,"F0" ,"F1" ,"F2" ,"F3" ,"F4" ,"F5" ,"F6" ,"F7" ,"F8" ,"F9" ,"FA" ,"FB" ,
"FC" ,"FD" ,"FE" ,"FF" };

public long CRC32_POLYNOMIAL = 0xEDB88320;
public long[] CRC32Table;

private void InitCRC32()
{
long I, J, K, X, XorVal;

CRC32Table = new long[256];

for(I = 0; I < 256; I++)
{
K = I;

for(J = 0; J < 8; J++)
{
X = (K & ((long)1));

if(X > 0)
{
XorVal = CRC32_POLYNOMIAL;
}
else
{
XorVal = 0;
}
if(K < 0)
{
K = ((K & 0x7FFFFFFF) / 2) | 0x40000000;
}
else
{
K = K / 2;
}
K ^= XorVal;
}
CRC32Table[I] = K;
}
}
private long CRC32(string txt)
{
long c=-1;
int I = 0, J = 0, L = 0, U = 0, U2 = 0;
InitCRC32();

for(I = 0; I < txt.Length; I++)
{
L = (int)txt[I];
U2 = 0xFF;
U = (int)(c & U2);
J = (L ^ U);
if(c < 0)
{
c = (((c & 0x7FFFFFFF) / 0x100) | 0x800000);
}
else
{
c = (c / 0x100);
}
c ^= CRC32Table[J];
c = ConvertLong(c);
}
c = ((c * -1) - 1);
return c;
}
private long ConvertLong(long Value)
{
if(Value < 0xFFFFFFFF)
{
Value -= 0xFFFFFFFF;
Value -= 1;
}
if(Value > (0xFFFFFFFF * -1))
{
Value += 0xFFFFFFFF;
Value += 1;
}
return Value;
}
public string BNLSChecksum(string Password, long ServerCode)
{
string strSCode = "", strTm = "";
char[] scChC;

scChC = ServerCode.ToString().ToCharArray();
strSCode = MakeDW(ConvertLong(ServerCode));
strTm = reverse(strSCode);
strTm = tohex(strTm);

}
private string tohex(string inBuf)
{
int x, numVal;
string outBuf="";

for(x = 0; x < inBuf.Length; x++)
{
numVal = inBuf[x];
outBuf = outBuf+HexValues[numVal];
}
return outBuf;
}
private string reverse(string inBuf)
{
int x;
string outBuf = "";
for(x = inBuf.Length - 1; x > -1; x--)
{
outBuf = outBuf+inBuf[x];
}
return outBuf;
}

private string MakeDW(long lngInt)
{
char a, b, c, d;
long tmpLng;
int tmpint;
string outBuf;

if(lngInt < -1) { lngInt += 0xFFFFFFFF; lngInt += 1; }

tmpLng = lngInt;

tmpint = (int)(((tmpLng / 256) / 256) / 256);
a = (char)(tmpint);
tmpLng -= (((tmpint* 256)* 256)* 256);

tmpint = (int)((tmpLng / 256) / 256);
b = (char)(tmpint);
tmpLng -= ((tmpint*256)*256);

tmpint = (int)(tmpLng / 256);
c = (char)(tmpint);
tmpLng -= (tmpint*256);

tmpint = (int)(tmpLng);
d = (char)(tmpint);

outBuf = d.ToString()+c.ToString()+b.ToString()+a.ToString();

return outBuf;
}
}
}```
[VB6]
Code:
```Private Sub InitCRC32()
Dim i As Long, J As Long, K As Long, XorVal As Long

Static CRC32Initialized As Boolean
If CRC32Initialized Then Exit Sub
CRC32Initialized = True

For i = 0 To 255
K = i

For J = 1 To 8
If K And 1 Then XorVal = CRC32_POLYNOMIAL Else XorVal = 0
If K < 0 Then K = ((K And &H7FFFFFFF) \ 2) Or &H40000000 Else K = K \ 2
K = K Xor XorVal
Next

CRC32Table(i) = K
Next
End Sub

Private Function CRC32(ByVal Data As String) As Long
Dim i As Long, J As Long

Call InitCRC32

CRC32 = &HFFFFFFFF

For i = 1 To Len(Data)
J = CByte(Asc(Mid(Data, i, 1))) Xor (CRC32 And &HFF&)
If CRC32 < 0 Then CRC32 = ((CRC32 And &H7FFFFFFF) \ &H100&) Or &H800000 Else CRC32 = CRC32 \ &H100&
CRC32 = CRC32 Xor CRC32Table(J)
Next

CRC32 = Not CRC32
End Function

Public Function BNLSChecksum(ByVal Password As String, ByVal ServerCode As Long) As Long
BNLSChecksum = CRC32(Password & Right("0000000" & Hex(ServerCode), 8))
End Function```
2. No Profile Picture
sfb
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Nov 2003
Posts
624
Rep Power
35
I found on their website:

# Sample Checksums - These sample checksums can be used to check the correctness of your code.

BNLSChecksum("Sample", 0x0123ABCD) == 0x12FDED88

You're going to love this.

Code:
```>>> import binascii

>>> crc = binascii.crc32("Sample0123ABCD")
>>> print hex(crc)
0x12FDED88

>>> print hex(crc)
0x98F911```

All you need to do is work out if you're dealing with strings of hex, or if you need to convert the character codes into hex with ord() and worry about putting 0's at the front of the results.

3. So pretty much, in Python, the code you showed me will operate just like the codes written in the other 3 languages?
4. No Profile Picture
sfb
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Nov 2003
Posts
624
Rep Power
35
Yeah.

"You should create the BNLS checksum as follows:
Create an ANSI string whose length is the length of the password + 8 characters."

You don't need to explicitly create strings with a particular length in Python, so there's no need for this.

"Copy the password to the beginning. (Note that the password is case sensitive.)"
You don't have to do anything special like strcpy to copy strings in Python, and it is case sensitive anyway by default.

"In the last 8 characters, store the hexadecimal representation of the server code, in uppercase, padded with zeroes on the left"
This matters, but how you do it depends on how you are reading the code elsewhere in your program.

"test".zfill(n) will pad a string with zeros on the left up to n characters.

To remove the "0x" from the start of a hex string and pad with zeros, it might be:

I think you asked a while ago about changing a string into hex characters... so you could use that if you need to.

"Calculate the standard CRC-32 checksum"
Done with the library function binascii.crc32. I think this is what takes up most of the code in the other language examples.
5. Ok, this is very hard. I don't even know where to start.

This is what I've gotten so far:

Code:
```    def InitCRC32():
CRC32Initialized = True
for i in range(255)
K = i
for J in range(1, 8):
if K and 1:
XorVal = CRC32_POLYNOMIAL
else:
XorVal = 0
if K < 0:
K = K+0x7FFFFFFF/2 or 0x40000000
else:
K = K/2
return K # return CRC32Table(i)?
def CRC32():
InitCRC32()
CRC32 = 0xFFFFFFFF
for i in range(1, len(data))
J = CByte(ord(data[i:1)) or CRC32 and 0xFF
if CRC32 < 0:
CRC32 = CRC32 and 0x7FFFFFFF/0x100 or 0x800000
else:
CRC32 = CRC32/0x100
CRC32 = CRC32 or CRC32Table(J)
CRC32 != CRC32
def BNLSChecksum():
BNLSChecksum = CRC32(bnetpass+"0000000"+hex(ServerCode)[8])```
Now, the example code on the bnetdocs didn't make much sense to me. The copying things to something else the polynomial stuff, etc. So I tried converting the code. I know that there are many errors in there. CByte and CRC32 are not recognized in Python. And a few of the statements need to be fixed in order to in Python. Do you have any ideas?