- SID_AUTH_ACCOUNTLOGONPROOF (C -> S)
- (byte[20]) M[1]

- SID_AUTH_ACCOUNTLOGONPROOF (C <- S)
- (byte[20]) M[2]

% is Modulo Division

* is Multiplication

- is Subtraction

+ is Addition

Decimal: 112624315653284427036559548610503669920632123929604336254260115573677366691719

Hex: 0xF8FF1A8B619918032186B68CA092B5557E976C78C73212D91216F6658523C787

Decimal: 1415864289515498529999010855430909456942718455404

Hex: F8018CF0A425BA8BEB8958B1AB6BF90AED970E6C

Which means that you hash the salt along with the hash of the username, a colon, and the password. Here is a sample implementation of it:

MessageDigest mdx = getSHA1(); mdx.update(username.getBytes()); mdx.update(":".getBytes()); mdx.update(password.getBytes()); byte []hash = mdx.digest(); mdx = getSHA1(); mdx.update(salt); mdx.update(hash); hash = mdx.digest();

A sample implementation of this might be:

g.modPow(x, N);

A sample implementation for this might be:

g.modPow(a, N);

byte []hash = getSHA1().digest(B); // Get the SHA-1 digest of B byte []u = new byte[4]; // Allocate 4 bytes for U u[0] = hash[3]; u[1] = hash[2]; u[2] = hash[1]; u[3] = hash[0];

If you really enjoy math, you can go ahead and figure out how these work out to the same value. It's actually a pretty interesting equation. Here is my Java implementation:

S_base = N.add(B).subtract(v).mod(N); S_exp = a.add(get_u(B).multiply(x)); S = S_base.modPow(S_exp, N);

- 2 buffers are created; one is the even bytes of S, and the other is the odd bytes of S.
- Each buffer is hashed with SHA-1.
- The even bytes of K are the even bytes of S, and the odd bytes of K are the odd bytes of S.

byte []K = new byte[40]; // Create the buffer for K byte []hbuf1 = new byte[16]; // Create the 2 buffers to each hold half of S byte []hbuf2 = new byte[16]; for(int i = 0; i < hbuf1.length; i++) // Loop through S { hbuf1[i] = S[i * 2]; hbuf2[i] = S[(i * 2) + 1]; } byte []hout1 = getSHA1().digest(hbuf1); // Hash the values byte []hout2 = getSHA1().digest(hbuf2); for(int i = 0; i < hout1.length; i++) { K[i * 2] = hout1[i]; // Put them into K K[(i * 2) + 1] = hout2[i]; }Pretty stupid, if you ask me, but that's life.

My Java implementation looks like this:

MessageDigest totalCtx = getSHA1(); totalCtx.update(I); totalCtx.update(getSHA1().digest(username.getBytes())); totalCtx.update(s); totalCtx.update(A); totalCtx.update(B); totalCtx.update(K); M1 = totalCtx.digest();

-iago

- Maddix, UserLoser, SneakCharm -- Reverse engineering the code with me

- Arta -- For convincing me to figure out what it did, and get it on BNetDocs

- Cloaked - For actually reading it and pointing out mistakes :)

All information on this page is public domain. If for any reason you want to copy/use this, feel free and have fun. All software and source directly distributed by me is public domain, and may be used in any way. Any copyrights I use (Particularely Starcraft, Brood War, Diablo, Warcraft, and Blizzard) are copyrights of their respective owners (in this case, Blizzard). Please respect all copyrights, and enjoy any public domain source code and software.