Add integrity hash support and SRP tuning options

This commit is contained in:
Kelsi 2026-02-13 01:32:15 -08:00
parent b3001a4b5b
commit 5435796a98
10 changed files with 591 additions and 22 deletions

View file

@ -111,6 +111,7 @@ private:
uint8_t securityFlags_ = 0;
uint32_t pinGridSeed_ = 0;
std::array<uint8_t, 16> pinServerSalt_{}; // from LOGON_CHALLENGE response
std::array<uint8_t, 16> checksumSalt_{}; // from LOGON_CHALLENGE response (integrity salt)
std::string pendingSecurityCode_;
};

View file

@ -37,6 +37,7 @@ struct LogonChallengeResponse {
std::vector<uint8_t> g; // Generator (variable, usually 1 byte)
std::vector<uint8_t> N; // Prime modulus (variable, usually 256 bytes)
std::vector<uint8_t> salt; // Salt (32 bytes)
std::array<uint8_t, 16> checksumSalt{}; // aka "crc_salt"/integrity salt
uint8_t securityFlags;
// PIN extension (securityFlags & 0x01)
@ -66,6 +67,7 @@ public:
static network::Packet build(const std::vector<uint8_t>& A,
const std::vector<uint8_t>& M1,
uint8_t securityFlags,
const std::array<uint8_t, 20>* crcHash,
const std::array<uint8_t, 16>* pinClientSalt,
const std::array<uint8_t, 20>* pinHash);
};

View file

@ -0,0 +1,35 @@
#pragma once
#include <array>
#include <cstdint>
#include <string>
#include <vector>
namespace wowee {
namespace auth {
// Computes the LOGON_PROOF "CRC hash" / integrity hash for the legacy WoW login protocol.
//
// Algorithm (per WoWDev/gtker docs):
// checksum = HMAC_SHA1(checksumSalt, concatenated_file_bytes)
// crc_hash = SHA1(clientPublicKey || checksum)
//
// clientPublicKey is the 32-byte A as sent on the wire.
//
// Returns false if any file is missing/unreadable.
bool computeIntegrityHashWin32(const std::array<uint8_t, 16>& checksumSalt,
const std::vector<uint8_t>& clientPublicKeyA,
const std::string& miscDir,
std::array<uint8_t, 20>& outHash,
std::string& outError);
// Same as computeIntegrityHashWin32, but allows selecting the EXE filename used in the file set.
bool computeIntegrityHashWin32WithExe(const std::array<uint8_t, 16>& checksumSalt,
const std::vector<uint8_t>& clientPublicKeyA,
const std::string& miscDir,
const std::string& exeName,
std::array<uint8_t, 20>& outHash,
std::string& outError);
} // namespace auth
} // namespace wowee

View file

@ -27,6 +27,15 @@ public:
const std::vector<uint8_t>& N,
const std::vector<uint8_t>& salt);
// Some SRP implementations use k = H(N|g) instead of the WoW-specific k=3.
// Default is false (k=3).
void setUseHashedK(bool enabled) { useHashedK_ = enabled; }
// Controls how SHA1 outputs are interpreted when converted to big integers (x, u, optionally k).
// Many SRP implementations treat hash outputs as big-endian integers.
// Default is false (treat hash outputs as little-endian integers).
void setHashBigEndian(bool enabled) { hashBigEndian_ = enabled; }
// Get client public ephemeral (A) - send to server
std::vector<uint8_t> getA() const;
@ -73,6 +82,8 @@ private:
std::vector<uint8_t> stored_auth_hash; // Pre-computed SHA1(UPPER(user):UPPER(pass))
bool initialized = false;
bool useHashedK_ = false;
bool hashBigEndian_ = false;
};
} // namespace auth