using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Esiur.Security.Authority;
using Esiur.Security.Authority.Providers;
namespace Esiur.Tests.Unit;
///
/// Drives a pair of instances (initiator and
/// responder) through the SHA3 challenge/response handshake and asserts both the happy
/// path (matching session keys) and the security hardening (constant-time challenge
/// checks, nonce validation, fail-closed behaviour on malformed peer input).
///
public class AuthHandshakeTests
{
// ---- test credential store -------------------------------------------------------
class TestAccount
{
public string Identity;
public byte[] RawPassword;
public byte[] Salt;
public byte[] Hash; // SHA3-256(RawPassword || Salt), exactly what the verifier stores
}
static readonly byte[] FixedSalt = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6 };
static TestAccount MakeAccount(string identity, string password)
{
var raw = Encoding.UTF8.GetBytes(password);
var hash = PasswordAuthenticationHandler.ComputeSha3(raw.Concat(FixedSalt).ToArray());
return new TestAccount { Identity = identity, RawPassword = raw, Salt = FixedSalt, Hash = hash };
}
class StubProvider : PasswordAuthenticationProvider
{
readonly Dictionary _accounts;
readonly string _self;
public StubProvider(string self, params TestAccount[] accounts)
{
_self = self;
_accounts = accounts.ToDictionary(a => a.Identity, a => a);
}
public override IdentityPassword GetSelfIdentityAndCredential(string domain, string hostname)
=> new IdentityPassword(_self, _accounts[_self].RawPassword);
public override byte[] GetSelfCredential(string identity, string domain, string hostname)
=> _accounts.TryGetValue(identity, out var a) ? a.RawPassword : null;
public override PasswordHash GetHostedAccountCredential(string identity, string domain)
=> _accounts.TryGetValue(identity, out var a)
? new PasswordHash(a.Hash, a.Salt)
: new PasswordHash(null, null);
}
// ---- helpers ---------------------------------------------------------------------
static object[] DataOf(AuthenticationResult result)
=> ((List