Files
DodoSSH/tests/DodoSSH.Client.Session.Tests/FakeDeviceKeyStore.cs
T

59 lines
2.1 KiB
C#

namespace DodoSSH.Client.Session.Tests;
/// A device key store that keeps its key in a field.
/// </summary>
/// <remarks>
/// Stands in for whatever guards the key on a real machine. The gesture is the entire security value of the
/// real thing, so what this fake models is the two ways the gesture ends: it hands the key over, or it does
/// not. <see cref="Decline"/> is a cancelled prompt and an invalidated key at once, which is exactly how much
/// the caller is allowed to know.
/// </remarks>
internal sealed class FakeDeviceKeyStore : IDeviceKeyStore
{
private byte[]? key;
/// <summary>When set, the next load refuses, as a cancelled gesture does.</summary>
internal bool Decline { get; set; }
/// <summary>Whether this machine can keep a key at all.</summary>
internal bool IsAvailable { get; set; } = true;
/// <summary>Reads the stored key without a gesture, for assertions only.</summary>
internal byte[]? Peek() => key;
/// <summary>Replaces the stored key, standing in for a rotated or corrupted keystore entry.</summary>
internal void Overwrite(byte[] replacement) => key = replacement;
/// <inheritdoc />
public async ValueTask<bool> IsAvailableAsync(CancellationToken cancellationToken)
{
if (HoldAvailability is { } hold)
{
await hold.WaitAsync(cancellationToken).ConfigureAwait(false);
}
return IsAvailable;
}
/// <summary>When set, availability is not answered until it completes: an unlock held part-way.</summary>
internal Task? HoldAvailability { get; set; }
/// <inheritdoc />
public ValueTask SaveAsync(ReadOnlyMemory<byte> devicePrivateKey, CancellationToken cancellationToken)
{
key = devicePrivateKey.ToArray();
return ValueTask.CompletedTask;
}
/// <inheritdoc />
public ValueTask<byte[]?> TryLoadAsync(CancellationToken cancellationToken) =>
ValueTask.FromResult(Decline ? null : key?.ToArray());
/// <inheritdoc />
public ValueTask ForgetAsync(CancellationToken cancellationToken)
{
key = null;
return ValueTask.CompletedTask;
}
}