using System.Text;
using DodoSSH.Client.Ssh;
namespace DodoSSH.Client.Session;
///
/// The throwaway key one connection signs in to a Spelunk server with.
///
///
///
/// For a host set to sign in through Spelunk — see SpelunkRoute.SignInThroughSpelunk — each connection
/// makes one of these, sends with its ticket request, and authenticates with
/// once the tunnel is up. Spelunk's agent runs a one-connection SSH server whose only
/// authorised key is this one, so the key is worth nothing after the connection it was made for.
///
///
/// Made in memory and never kept. Nothing writes it to a disk or to the vault, and nothing logs it:
/// says what it is and nothing of what it holds. Ed25519, which is what
/// makes instantly and what every OpenSSH the agent could start accepts.
///
///
public sealed class SpelunkSignIn
{
/// The account Spelunk signs in as when its answer does not name one.
public const string DefaultUser = "root";
/// The comment the public key carries, which is what Spelunk and the server's logs see.
internal const string KeyComment = "dodossh-spelunk-sign-in";
private SpelunkSignIn(string publicKeyLine, SshPrivateKeyCredential credential)
{
PublicKeyLine = publicKeyLine;
Credential = credential;
}
/// The public half, as one OpenSSH authorized_keys line: ssh-ed25519 AAAA… comment.
public string PublicKeyLine { get; }
/// The private half, in the form a connection authenticates with.
public SshPrivateKeyCredential Credential { get; }
/// Makes a fresh key pair for one connection.
public static SpelunkSignIn Create()
{
var key = SshKeyGenerator.Generate(SshKeyAlgorithm.Ed25519, KeyComment);
return new SpelunkSignIn(
key.PublicKeyLine.Trim(),
new SshPrivateKeyCredential(Encoding.UTF8.GetBytes(key.PrivateKeyArmour), Passphrase: null));
}
///
/// Says nothing of the key, so one that reaches a log by accident takes nothing with it.
public override string ToString() => "Spelunk sign-in key";
}
///
/// The credential of a connection that will sign in through Spelunk, before the tunnel has made its key.
///
///
///
/// A host that signs in through Spelunk is resolved to a login before anything is opened — the same
/// resolution every host goes through — but its key does not exist until the tunnel is opened, and the
/// account is whatever Spelunk then says. This stands in for the key until the route replaces it, together
/// with the username, as the connection is made through it.
///
///
/// It authenticates nothing. The SSH layer knows only passwords and private keys, and refuses any other
/// credential before it dials — so a path that forgot to take the route's key fails closed rather than
/// sending something else in its place.
///
///
public sealed record SpelunkSignInPending : SshCredential
{
/// The one value; there is nothing in it to tell two apart.
public static SpelunkSignInPending Instance { get; } = new();
private SpelunkSignInPending()
{
}
}