The New Logon System (NLS) is based on the Secure Remote Password protocol (SRP) which was designed to obviate the need to send a password, or its cryptographic equivalent, across a network. This page exists to provide a basic introduction to this protocol. For detailed explanations and information, see RFC 2945.
The Random Value / Private Key (a/b)
- A random value generated by the client, such that
0 <= a <= N.
- The server also generates its own random value (b).
The Client Key (A)
- The client public key, referred to in the SRP specification as
A, is a 256-bit value generated by the client. A new key is generated for each session.
- The formula is: A = ga % N
- This value is sent to the server along with the client's username in C > S [0x53] SID_AUTH_ACCOUNTLOGON
The Server Key (B)
- The server public key, referred to in the SRP specification as
B, is a 256-bit value generated by the server. A new key is generated for each session.
- The formula is: B = v + (gb % N)
- The server sends this key to the client in S > C [0x53] SID_AUTH_ACCOUNTLOGON.
The Generator (g)
- This value is a constant used generate public keys. Its value is 47 (
The Modulus (N)
Nis a large (256-bit) unsigned integer. All SRP calculations are done modulo
N. Its value in NLS version 2 is:
Decimal: 112624315653284427036559548610503669920632123929604336254260115573677366691719 Hex: 0xF8FF1A8B619918032186B68CA092B5557E976C78C73212D91216F6658523C787
Or, in C:
unsigned char N = 0x87, 0xc7, 0x23, 0x85, 0x65, 0xf6, 0x16, 0x12, 0xd9, 0x12, 0x32, 0xc7, 0x78, 0x6c, 0x97, 0x7e, 0x55, 0xb5, 0x92, 0xa0, 0x8c, 0xb6, 0x86, 0x21, 0x03, 0x18, 0x99, 0x61, 0x8b, 0x1a, 0xff, 0xf8
For NLS version 1 the byte order is reversed.
The Salt (s)
- The salt is a 256-bit random value generated by the client when an account is created. After creation, it is never changed.
- It is sent to the server in C > S [0x52] SID_AUTH_ACCOUNTCREATE, and received from the server during logons in S > C [0x53] SID_AUTH_ACCOUNTLOGON.
The Verifier (v)
- The verifier is a 256-bit value calculated by the client when an account is created. After creation, it is never changed.
- It is sent to the server in C > S [0x52] SID_AUTH_ACCOUNTCREATE.
- It is generated thus: v = gx % N
Username & Password Hash (x)
xis a value generated by the client based on the username, password, and salt value. In this formula, a comma (
,) indicates concatenation:
SHA1(s, SHA1(Username, ":", Password))
- Username and password are converted to UPPER CASE before hashing.
- The hash is converted to an integer in LITTLE-endian format.
- Todo: Explain me.
- This value is the first four bytes of
SHA1(B). This differs slightly from standard SRP, in which this value is generated by the server and sent to the client along with the server key (
- This value is converted to an integer in BIG-endian format.
The Shared Secret (S)
Sis where the magic of NLS happens. Both the client and the server calculate
S, using different formula, and end up with the same result.
- Client: S = ((N + B - v) % N)(a + u * x) % N
- Server: S = (A * (vu % N))b % N
- If the Server and Client agree on the value of
S, the logon succeeds, otherwise, it fails.
Password Proof (K)
- This value is generated by the client and the server as proof that they actually know the value of
S. This is another value which differs from standard SRP, which justs sends
- Blizzard's version calculates
- Place the even bytes of
Sinto one buffer, and the odd bytes into another.
- Create a SHA-1 hash of each buffer.
Kby combining the even bytes of the first buffer, and the odd bytes of the second.
- Place the even bytes of
Client Password Proof (M1)
- This value is sent to Battle.net to prove that you know your own password. Again, this differs from standard SRP. In this formula, commas (
,) indicate concatenation:
M1 = SHA1(SHA1(g) xor SHA1(N), SHA1(Username), s, A, B, K)
- Username and password are converted to UPPER CASE prior to hashing.
- This value is sent to the server in C > S [0x54] SID_AUTH_ACCOUNTLOGONPROOF
Server Password Proof (M2)
- This value is returned by the server in S > C [0x54] SID_AUTH_ACCOUNTLOGONPROOF. The client should calculate this value on its own and compare it to the server's value to verify that the server knows your password.
M2 = SHA1(A, M1, K)
Most of the information on this page has come from iago's notes. For more, see his page on the topic.
A Java implementation of the algorithm (using code directly from iago's notes) can be found in JBLS.
A Python implementation can be found in Davnit's bncs.py.