Table of Contents

Class SrpService

Namespace
FishMMO.Auth.Implementation
Assembly
FishMMO-AuthShared.dll

Transport-agnostic SRP-6a authentication service. Provides server-side and client-side SRP field decryption/encryption, fake SRP salt derivation for anti-enumeration, and SRP session helpers.

public static class SrpService
Inheritance
SrpService
Inherited Members

Remarks

Methods that operate on encrypted fields use ConnectionEncryptionData for AES-GCM transport encryption. Methods without encryption data parameters operate on plaintext (suitable for TLS-protected transports like HTTPS).

Methods

ClientDecryptAuthToken(byte[], byte[], GcmNonceContext, ushort)

Decrypts an auth token from a SRP success message.

public static byte[] ClientDecryptAuthToken(byte[] encryptedToken, byte[] serverToClientKey, CryptoHelper.GcmNonceContext receiveNonceCtx, ushort agreedVersion)

Parameters

encryptedToken byte[]

AES-GCM encrypted token bytes.

serverToClientKey byte[]

AES-256 key for server→client direction.

receiveNonceCtx CryptoHelper.GcmNonceContext

Client's receive nonce context.

agreedVersion ushort

Negotiated protocol version.

Returns

byte[]

Raw token bytes.

ClientDecryptServerProof(byte[], byte[], GcmNonceContext, ushort)

Decrypts the server's SRP success proof.

public static string ClientDecryptServerProof(byte[] encryptedProof, byte[] serverToClientKey, CryptoHelper.GcmNonceContext receiveNonceCtx, ushort agreedVersion)

Parameters

encryptedProof byte[]

AES-GCM encrypted server proof bytes.

serverToClientKey byte[]

AES-256 key for server→client direction.

receiveNonceCtx CryptoHelper.GcmNonceContext

Client's receive nonce context.

agreedVersion ushort

Negotiated protocol version.

Returns

string

Decrypted server proof string.

Remarks

Throws CryptographicException on decryption/authentication failure.

ClientDecryptTwoFactorSetup(byte[], byte[], byte[], GcmNonceContext, ushort, out string, out string[])

Decrypts two-factor setup data (otpauth URI and recovery codes) from the server.

public static void ClientDecryptTwoFactorSetup(byte[] encryptedOtpauthUri, byte[] encryptedRecoveryCodes, byte[] serverToClientKey, CryptoHelper.GcmNonceContext receiveNonceCtx, ushort agreedVersion, out string otpauthUri, out string[] recoveryCodes)

Parameters

encryptedOtpauthUri byte[]

AES-GCM encrypted otpauth URI.

encryptedRecoveryCodes byte[]

AES-GCM encrypted newline-delimited recovery codes.

serverToClientKey byte[]

AES-256 key for server→client direction.

receiveNonceCtx CryptoHelper.GcmNonceContext

Client's receive nonce context.

agreedVersion ushort

Negotiated protocol version.

otpauthUri string

Decrypted otpauth URI.

recoveryCodes string[]

Decrypted recovery codes array.

ClientDecryptVerifyResponse(byte[], byte[], byte[], GcmNonceContext, ushort, out string, out string)

Decrypts the SRP verify response from the server (salt + server ephemeral).

public static void ClientDecryptVerifyResponse(byte[] encryptedSalt, byte[] encryptedPublicEphemeral, byte[] serverToClientKey, CryptoHelper.GcmNonceContext receiveNonceCtx, ushort agreedVersion, out string salt, out string publicServerEphemeral)

Parameters

encryptedSalt byte[]

AES-GCM encrypted salt from server.

encryptedPublicEphemeral byte[]

AES-GCM encrypted server ephemeral from server.

serverToClientKey byte[]

AES-256 key for server→client direction.

receiveNonceCtx CryptoHelper.GcmNonceContext

Client's receive nonce context.

agreedVersion ushort

Negotiated protocol version.

salt string

Decrypted salt string.

publicServerEphemeral string

Decrypted server public ephemeral string.

Remarks

Throws CryptographicException on decryption/authentication failure.

ClientEncryptAccountVerify(string, string, byte[], GcmNonceContext, ushort, out byte[], out byte[], out uint)

Encrypts account verification fields (username + code) for transmission.

public static void ClientEncryptAccountVerify(string username, string verifyCode, byte[] clientToServerKey, CryptoHelper.GcmNonceContext sendNonceCtx, ushort agreedVersion, out byte[] encryptedUsername, out byte[] encryptedCode, out uint codeSeq)

Parameters

username string

Username to verify.

verifyCode string

Verification code.

clientToServerKey byte[]

AES-256 key for client→server direction.

sendNonceCtx CryptoHelper.GcmNonceContext

Client's send nonce context.

agreedVersion ushort

Negotiated protocol version.

encryptedUsername byte[]

Encrypted username output.

encryptedCode byte[]

Encrypted verification code output.

codeSeq uint

Sequence number of the code (used as broadcast Seq).

ClientEncryptEphemeral(string, byte[], GcmNonceContext, ushort, out byte[], out uint)

Encrypts the client's SRP public ephemeral for transmission to the server.

public static void ClientEncryptEphemeral(string publicEphemeral, byte[] clientToServerKey, CryptoHelper.GcmNonceContext sendNonceCtx, ushort agreedVersion, out byte[] encryptedEphemeral, out uint seq)

Parameters

publicEphemeral string

Client's SRP public ephemeral string.

clientToServerKey byte[]

AES-256 key for client→server direction.

sendNonceCtx CryptoHelper.GcmNonceContext

Client's send nonce context.

agreedVersion ushort

Negotiated protocol version.

encryptedEphemeral byte[]

Encrypted ephemeral output.

seq uint

Sequence number used (for broadcast).

ClientEncryptProof(string, byte[], GcmNonceContext, ushort, out byte[], out uint)

Encrypts the client's SRP proof for transmission to the server.

public static void ClientEncryptProof(string proof, byte[] clientToServerKey, CryptoHelper.GcmNonceContext sendNonceCtx, ushort agreedVersion, out byte[] encryptedProof, out uint seq)

Parameters

proof string

Client SRP proof string.

clientToServerKey byte[]

AES-256 key for client→server direction.

sendNonceCtx CryptoHelper.GcmNonceContext

Client's send nonce context.

agreedVersion ushort

Negotiated protocol version.

encryptedProof byte[]

Encrypted proof output.

seq uint

Sequence number used (for broadcast).

ClientEncryptRegistrationFields(string, int, string, string, byte[], GcmNonceContext, ushort, out byte[], out byte[], out byte[], out byte[], out uint)

Encrypts registration fields (email, age, salt, verifier) for transmission. Uses the CreateAccount AAD type for all fields.

public static void ClientEncryptRegistrationFields(string email, int age, string salt, string verifier, byte[] clientToServerKey, CryptoHelper.GcmNonceContext sendNonceCtx, ushort agreedVersion, out byte[] encryptedEmail, out byte[] encryptedAge, out byte[] encryptedSalt, out byte[] encryptedVerifier, out uint verifierSeq)

Parameters

email string

Email address string.

age int

Age value.

salt string

SRP salt string.

verifier string

SRP verifier string.

clientToServerKey byte[]

AES-256 key for client→server direction.

sendNonceCtx CryptoHelper.GcmNonceContext

Client's send nonce context.

agreedVersion ushort

Negotiated protocol version.

encryptedEmail byte[]

Encrypted email output.

encryptedAge byte[]

Encrypted age output.

encryptedSalt byte[]

Encrypted salt output.

encryptedVerifier byte[]

Encrypted verifier output.

verifierSeq uint

Sequence number of the verifier (used as broadcast Seq).

ClientEncryptTotpCode(string, byte[], GcmNonceContext, ushort, out byte[], out uint)

Encrypts a TOTP code for transmission to the server.

public static void ClientEncryptTotpCode(string code, byte[] clientToServerKey, CryptoHelper.GcmNonceContext sendNonceCtx, ushort agreedVersion, out byte[] encryptedCode, out uint seq)

Parameters

code string

TOTP code string.

clientToServerKey byte[]

AES-256 key for client→server direction.

sendNonceCtx CryptoHelper.GcmNonceContext

Client's send nonce context.

agreedVersion ushort

Negotiated protocol version.

encryptedCode byte[]

Encrypted code output.

seq uint

Sequence number used (for broadcast).

ClientEncryptUsername(string, byte[], GcmNonceContext, ushort, bool, out byte[], out uint)

Encrypts a username for SRP verify transmission from client to server.

public static void ClientEncryptUsername(string username, byte[] clientToServerKey, CryptoHelper.GcmNonceContext sendNonceCtx, ushort agreedVersion, bool isRegistration, out byte[] encryptedUsername, out uint seq)

Parameters

username string

Plaintext username string.

clientToServerKey byte[]

AES-256 key for client→server direction.

sendNonceCtx CryptoHelper.GcmNonceContext

Client's send nonce context.

agreedVersion ushort

Negotiated protocol version.

isRegistration bool

If true, uses CreateAccount AAD; otherwise SrpVerify AAD.

encryptedUsername byte[]

Encrypted username output.

seq uint

Sequence number used (for broadcast).

DecryptProof(byte[], ConnectionEncryptionData, uint)

Decrypts the SRP proof from an AES-GCM encrypted payload.

public static string DecryptProof(byte[] encryptedProof, ConnectionEncryptionData encryptionData, uint seq)

Parameters

encryptedProof byte[]

AES-GCM encrypted proof bytes.

encryptionData ConnectionEncryptionData

Connection encryption state.

seq uint

Broadcast sequence number.

Returns

string

Decrypted proof string.

Remarks

Throws CryptographicException on decryption/authentication failure.

DerivePerUsernameFakeSalt(string, byte[])

Derives a deterministic per-username fake SRP salt via HMAC-SHA512 so that each non-existent username receives a unique but repeatable salt. Prevents attackers from detecting salt reuse across different fake accounts.

public static string DerivePerUsernameFakeSalt(string username, byte[] fakeSaltKey)

Parameters

username string

The username to derive a fake salt for.

fakeSaltKey byte[]

HMAC-SHA512 key. Must not be null or zeroed.

Returns

string

Hex-encoded fake salt string, or the static fake salt if the key is unavailable.

Remarks

Output is a 128-character lowercase hex string derived from HMAC-SHA512, matching the length of real SRP salts produced by the SRP library with SHA-512 parameters. This prevents ciphertext-size oracles from leaking account existence.

EncryptServerProof(string, ConnectionEncryptionData)

Encrypts the server proof for transmission using AES-GCM with SrpSuccess AAD type.

public static byte[] EncryptServerProof(string serverProof, ConnectionEncryptionData encryptionData)

Parameters

serverProof string

SRP server proof string.

encryptionData ConnectionEncryptionData

Connection encryption state.

Returns

byte[]

Encrypted server proof bytes.

EncryptVerifyResponse(string, string, ConnectionEncryptionData, out byte[], out byte[])

Encrypts the SRP verify response fields (salt + server ephemeral) for transmission using AES-GCM with SrpVerifyResponse AAD type.

public static void EncryptVerifyResponse(string srpSalt, string srpPublicServerEphemeral, ConnectionEncryptionData encryptionData, out byte[] encryptedSalt, out byte[] encryptedPublicServerEphemeral)

Parameters

srpSalt string

SRP salt string to encrypt.

srpPublicServerEphemeral string

SRP server public ephemeral string to encrypt.

encryptionData ConnectionEncryptionData

Connection encryption state.

encryptedSalt byte[]

Encrypted salt output.

encryptedPublicServerEphemeral byte[]

Encrypted server ephemeral output.

GetStaticFakeData()

Returns the pre-computed static fake SRP salt and verifier. Force-access this at startup to prevent first-use timing side-channels.

public static (string Salt, string Verifier) GetStaticFakeData()

Returns

(string Salt, string Verifier)

Tuple of (Salt, Verifier) strings.

ServerDecryptTotpCode(byte[], ConnectionEncryptionData, uint)

Decrypts a TOTP code from an AES-GCM encrypted payload sent by the client.

public static string ServerDecryptTotpCode(byte[] encryptedCode, ConnectionEncryptionData encryptionData, uint seq)

Parameters

encryptedCode byte[]

AES-GCM encrypted TOTP code bytes.

encryptionData ConnectionEncryptionData

Connection encryption state.

seq uint

Broadcast sequence number.

Returns

string

Decrypted TOTP code string.

TryDecryptVerifyFields(byte[], byte[], ConnectionEncryptionData, uint, out string?, out string?)

Decrypts the SRP verify fields (username/email and public ephemeral) from AES-GCM encrypted payloads using the two-sequence encoding: seq-1 = username, seq = public ephemeral.

public static bool TryDecryptVerifyFields(byte[] encryptedUsername, byte[] encryptedPublicEphemeral, ConnectionEncryptionData encryptionData, uint seq, out string? username, out string? publicEphemeral)

Parameters

encryptedUsername byte[]

AES-GCM encrypted username/email bytes.

encryptedPublicEphemeral byte[]

AES-GCM encrypted SRP public ephemeral bytes.

encryptionData ConnectionEncryptionData

Connection encryption state (keys, nonces, version).

seq uint

The broadcast sequence number (ephemeral's sequence; username = seq-1).

username string

Decrypted username/email string.

publicEphemeral string

Decrypted SRP public ephemeral string.

Returns

bool

true if decryption and sequence validation succeeded.

Remarks

Throws CryptographicException on decryption/authentication failure. The caller should treat any CryptographicException as connection-fatal.

Sequence atomicity: This method consumes two consecutive sequence numbers (seq−1, seq). If the first consume succeeds but the second fails (e.g., due to a concurrent call or counter exhaustion), seq−1 is burned and the receive counter is left in an inconsistent state. Callers MUST tear down the connection on any false return — a partially-consumed sequence cannot be recovered.