WowSrp 0.1.0-alpha
See the version list below for details.
dotnet add package WowSrp --version 0.1.0-alpha
NuGet\Install-Package WowSrp -Version 0.1.0-alpha
<PackageReference Include="WowSrp" Version="0.1.0-alpha" />
paket add WowSrp --version 0.1.0-alpha
#r "nuget: WowSrp, 0.1.0-alpha"
// Install WowSrp as a Cake Addin #addin nuget:?package=WowSrp&version=0.1.0-alpha&prerelease // Install WowSrp as a Cake Tool #tool nuget:?package=WowSrp&version=0.1.0-alpha&prerelease
WowSrp for .NET (C#)
.NET Standard 2.1 library for World of Warcraft authentication servers. Includes functionality for:
- Logging in (SRP6)
- Header encryption/decryption for Vanilla, TBC, and Wrath
- Calculation of world proof sent in
CMSG_AUTH_SESSION
- Integrity checking
- PIN codes for 1.12+
- Matrix Cards for 2.0+
Getting started
Install the library from nuget:
dotnet add package WowSrp
Usage
Authentication
For Servers
The module is split into functionality used by a server implementation and a client implementation.
Server
SrpVerifier -> SrpProof -> SrpServer
You will only want to save the username, salt, and password verifier for an account. Do not save the raw passwords on the server.
Construct an SrpVerifier
through
var verifier = new SrpVerifier(username, password);
Save the Username
, Salt
, and PasswordVerifier
in your database.
When a client connects, retrieve the Username
, Salt
, and PasswordVerifier
from your database and create
an SrpVerifier
through the constructor and convert it to an SrpProof
:
var proof = new SrpVerifier(username, passwordVerifier, salt).IntoProof();
The Salt
, ServerPublicKey
, Generator
, and LargeSafePrime
can then be sent to the client:
The internal calculations use the generator and large safe prime from the functions, and these MUST
be the ones sent to the client.
After receiving the clientPublicKey
and clientProof
, the proof can be attempted converted to an SrpServer
.
var success = server.into_server(client_public_key, client_proof)
if (!success.HasValue) {
// Password was incorrect
}
var (server, serverProof) = success!.Value;
The client is now logged in and can be sent the realm list.
If the client loses connection it will attempt to reconnect.
This requires a valid SrpServer
to exist.
In my opinion the reconnect method is insecure since it uses the session key that can easily be deduced
by any third party and it should not be implemented in a production auth server.
var success = server.VerifyReconnect(clientData, clientProof);
For Clients
SrpClientUser -> SrpClientChallenge -> SrpClient | -> SrpClientReconnection
The SrpClientReconnection
is just a data struct that contains reconnection values.
The client does not have to save any values except for the username and password.
var challenge = new SrpClientChallenge(username, password, generator, largeSafePrime, serverPublicKey, salt)
The client can then verify that the server also has the correct password through the serverProof
:
This creates an SrpClient
.
var success = challenge.VerifyServerProof(serverProof)
if (!success.HasValue) {
// Server didn't get the same hash as you did
}
var client = success!.Value;
The SrpClient
can attempt to reconnect using the serverReconnectData
:
var reconnect_data = client.CalculateReconnectValues(serverReconnectData)
And then access the reconnect values from reconnectData
:
var challenge_data = reconnectData.ChallengeData;
var client_proof = reconnectData.ClientProof;
Header Encryption
Server
First, create a random seed from WorldProof.RandomSeed()
and send it to the client in SMSG_AUTH_CHALLENGE.
After receiving CMSG_AUTH_SESSION from the client, instantiate the encrypter and decrypter for your version.
var encrypter = new VanillaEncrypter();
encrypter.WriteServerHeader(stream, size, opcode);
var decrypter = new VanillaDecrypter();
var header = decrypter.ReadServerHeader(stream);
Integrity Checking
Use the relevant function for either Windows, Mac, or the general purpose version:
var hash = Integrity.GenericCheck(allFiles, checksumSalt, clientPublicKey)
PIN Code
For both server and client, create a PinCode
object and call CalculateHash
.
Other arguments are random values sent to both client and server.
var pinGridSeed = Pin.RandomPinGridSeed();
var server/clientSalt = Pin.RandomPinSalt();
// Send these to client/server
// Each byte in the array is a digit of the pin
// Must be at least 4 and no longer than 10, values can not be greater than 9
var pin = [1, 2, 3, 4];
var hash = Pin.CalculateHash(pinGridSeed, serverSalt, clientSalt);
If the server hash matches the client hash, the client has the correct PIN.
Matrix Card
The MatrixCard
class represents the physical card and the data on it.
The VerifyHash
function takes in all the necessary parameters and should be preferred.
MatrixCardVerifier
is used for verification whenever the full MatrixCard
data is not available, such as when a physical card has been issued.
// Completely random data
new card = MatrixCard();
// Save to database
// Send to client
var success = card.VerifyHash(challengeCount, seed, sessionKey, clientProof);
Additional documentation
The WoWDev wiki has an article on the big picture of authentication. My blog has articles that detail the implementation of this library.
License
Licensed under either of
- Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0)
- MIT license http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on WowSrp:
Package | Downloads |
---|---|
WowWorldMessages
Library for World of Warcraft 1.0 through to 3.3.5 world (game) messages. |
GitHub repositories
This package is not used by any popular GitHub repositories.
# 0.1.0 - RELEASEDATE
## Added
* Initial release.