Make an Ed25519 key, then write it with SshPrivateKey.Create in the openssh-key-v1 format that ssh-keygen writes, encrypted with a passphrase, and the public key as an authorized_keys line. OpenSSH reads both. No ssh-keygen process is needed.
dotnet new console -o SshKeyDemo && cd SshKeyDemo dotnet add package RecursiveAI.OneCrypto --version 0.1.0-preview.1
OneCrypto is a preview, so dotnet add package needs --version or --prerelease. Put this in Program.cs and run dotnet run:
using RecursiveAI.OneCrypto.Pkcs; using RecursiveAI.OneCrypto.Primitives; using RecursiveAI.OneCrypto.Wire.Ssh; using Ed25519PrivateKey ed = Ed25519PrivateKey.Generate(); using PrivateKeyInfo key = PrivateKeyInfo.FromEd25519(ed); // aes256-ctr with 16 bcrypt rounds, the ssh-keygen defaults SshPrivateKey sshKey = SshPrivateKey.Create(key, "deploy@build-01", "a long passphrase"); File.WriteAllText("id_ed25519", sshKey.ToPem()); if (!OperatingSystem.IsWindows()) // ssh refuses keys others can read File.SetUnixFileMode("id_ed25519", UnixFileMode.UserRead | UnixFileMode.UserWrite); string pub = sshKey.PublicKey.ToAuthorizedKey("deploy@build-01"); File.WriteAllText("id_ed25519.pub", pub + "\n"); Console.WriteLine($"Private key: {sshKey.CipherName}, {sshKey.KdfName}, " + $"encrypted: {sshKey.IsEncrypted}"); Console.WriteLine($"Fingerprint: {sshKey.PublicKey.Fingerprint}");
Private key: aes256-ctr, bcrypt, encrypted: True Fingerprint: SHA256:gn7ABggzAYXIw2oNXML8oHgQDVnDT4tR2Fbg4Xlboww
Put the .pub line in a server’s ~/.ssh/authorized_keys, and the private key file where ssh looks for keys. ToPem() writes the -----BEGIN OPENSSH PRIVATE KEY----- form; pass an empty passphrase for an unencrypted key. RSA and ECDSA keys work the same way: build the PrivateKeyInfo from .NET’s RSA or ECDsa with PrivateKeyInfo.FromAsymmetricAlgorithm.
Check it with ssh-keygen
ssh-keygen -y decrypts the private key and prints its public key, which must equal the .pub file; -l prints the fingerprint:
ssh-keygen -y -P "a long passphrase" -f id_ed25519 | cut -d' ' -f1-2 > from-private.pub cut -d' ' -f1-2 id_ed25519.pub | cmp - from-private.pub \ && echo "ssh-keygen reads the key" ssh-keygen -l -f id_ed25519.pub | cut -d' ' -f2
ssh-keygen reads the key SHA256:gn7ABggzAYXIw2oNXML8oHgQDVnDT4tR2Fbg4Xlboww
Reading keys
SshPrivateKey.Parse (or FromPem) reads a key file and Open(passphrase) decrypts it; SshPublicKey.ParseAuthorizedKey reads a .pub or authorized_keys line. Crypto.Load reads all of these without being told the format and returns keys ready to sign: see Load a PEM or PKCS#8 private key.
Limits
- Not audited. This library has not been independently audited. It is a preview: 0.1.0-preview.1, and the API can change.
- Key files only. OneCrypto reads and writes keys and certificates; it is not an SSH client, and it doesn’t talk to
ssh-agentyet. Signing files with SSH keys (SSHSIG) comes in a later package. - Ciphers.
[email protected]key files are not read.bcrypt-pbkdf, which protects the passphrase, looks up tables by data; the project says why it accepts that in Password-based key derivation.
How OpenSSH keys and certificates are read and written: PKCS.