NLS/SRP Protocol
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 (
0x2F
).
The Modulus (N)
N
is a large (256-bit) unsigned integer. All SRP calculations are done moduloN
. 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)
x
is 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.
Scrambler (u)
- 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 (B
). - This value is converted to an integer in BIG-endian format.
The Shared Secret (S)
S
is where the magic of NLS happens. Both the client and the server calculateS
, 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 sendsSHA1(S)
. - Blizzard's version calculates
K
as follows:- Place the even bytes of
S
into one buffer, and the odd bytes into another. - Create a SHA-1 hash of each buffer.
- Create
K
by 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.
Comments
Constants for Battle.Net 2.0
https://bitbucket.org/Greatwolf/starcrack/src/ccd08d31dc42/LaunchHelper/SRP6a.cpp
Now SRP uses 1 kbit modulus instead of 256 bit.