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
encryptedTokenbyte[]AES-GCM encrypted token bytes.
serverToClientKeybyte[]AES-256 key for server→client direction.
receiveNonceCtxCryptoHelper.GcmNonceContextClient's receive nonce context.
agreedVersionushortNegotiated 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
encryptedProofbyte[]AES-GCM encrypted server proof bytes.
serverToClientKeybyte[]AES-256 key for server→client direction.
receiveNonceCtxCryptoHelper.GcmNonceContextClient's receive nonce context.
agreedVersionushortNegotiated 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
encryptedOtpauthUribyte[]AES-GCM encrypted otpauth URI.
encryptedRecoveryCodesbyte[]AES-GCM encrypted newline-delimited recovery codes.
serverToClientKeybyte[]AES-256 key for server→client direction.
receiveNonceCtxCryptoHelper.GcmNonceContextClient's receive nonce context.
agreedVersionushortNegotiated protocol version.
otpauthUristringDecrypted otpauth URI.
recoveryCodesstring[]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
encryptedSaltbyte[]AES-GCM encrypted salt from server.
encryptedPublicEphemeralbyte[]AES-GCM encrypted server ephemeral from server.
serverToClientKeybyte[]AES-256 key for server→client direction.
receiveNonceCtxCryptoHelper.GcmNonceContextClient's receive nonce context.
agreedVersionushortNegotiated protocol version.
saltstringDecrypted salt string.
publicServerEphemeralstringDecrypted 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
usernamestringUsername to verify.
verifyCodestringVerification code.
clientToServerKeybyte[]AES-256 key for client→server direction.
sendNonceCtxCryptoHelper.GcmNonceContextClient's send nonce context.
agreedVersionushortNegotiated protocol version.
encryptedUsernamebyte[]Encrypted username output.
encryptedCodebyte[]Encrypted verification code output.
codeSequintSequence 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
publicEphemeralstringClient's SRP public ephemeral string.
clientToServerKeybyte[]AES-256 key for client→server direction.
sendNonceCtxCryptoHelper.GcmNonceContextClient's send nonce context.
agreedVersionushortNegotiated protocol version.
encryptedEphemeralbyte[]Encrypted ephemeral output.
sequintSequence 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
proofstringClient SRP proof string.
clientToServerKeybyte[]AES-256 key for client→server direction.
sendNonceCtxCryptoHelper.GcmNonceContextClient's send nonce context.
agreedVersionushortNegotiated protocol version.
encryptedProofbyte[]Encrypted proof output.
sequintSequence 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
emailstringEmail address string.
ageintAge value.
saltstringSRP salt string.
verifierstringSRP verifier string.
clientToServerKeybyte[]AES-256 key for client→server direction.
sendNonceCtxCryptoHelper.GcmNonceContextClient's send nonce context.
agreedVersionushortNegotiated protocol version.
encryptedEmailbyte[]Encrypted email output.
encryptedAgebyte[]Encrypted age output.
encryptedSaltbyte[]Encrypted salt output.
encryptedVerifierbyte[]Encrypted verifier output.
verifierSequintSequence 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
codestringTOTP code string.
clientToServerKeybyte[]AES-256 key for client→server direction.
sendNonceCtxCryptoHelper.GcmNonceContextClient's send nonce context.
agreedVersionushortNegotiated protocol version.
encryptedCodebyte[]Encrypted code output.
sequintSequence 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
usernamestringPlaintext username string.
clientToServerKeybyte[]AES-256 key for client→server direction.
sendNonceCtxCryptoHelper.GcmNonceContextClient's send nonce context.
agreedVersionushortNegotiated protocol version.
isRegistrationboolIf true, uses CreateAccount AAD; otherwise SrpVerify AAD.
encryptedUsernamebyte[]Encrypted username output.
sequintSequence 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
encryptedProofbyte[]AES-GCM encrypted proof bytes.
encryptionDataConnectionEncryptionDataConnection encryption state.
sequintBroadcast 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
usernamestringThe username to derive a fake salt for.
fakeSaltKeybyte[]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
serverProofstringSRP server proof string.
encryptionDataConnectionEncryptionDataConnection 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
srpSaltstringSRP salt string to encrypt.
srpPublicServerEphemeralstringSRP server public ephemeral string to encrypt.
encryptionDataConnectionEncryptionDataConnection encryption state.
encryptedSaltbyte[]Encrypted salt output.
encryptedPublicServerEphemeralbyte[]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
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
encryptedCodebyte[]AES-GCM encrypted TOTP code bytes.
encryptionDataConnectionEncryptionDataConnection encryption state.
sequintBroadcast 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
encryptedUsernamebyte[]AES-GCM encrypted username/email bytes.
encryptedPublicEphemeralbyte[]AES-GCM encrypted SRP public ephemeral bytes.
encryptionDataConnectionEncryptionDataConnection encryption state (keys, nonces, version).
sequintThe broadcast sequence number (ephemeral's sequence; username = seq-1).
usernamestringDecrypted username/email string.
publicEphemeralstringDecrypted SRP public ephemeral string.
Returns
- bool
trueif 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.