Public-Key Authentication
Ed25519, RSA, and ECDSA public-key authentication, including raw-key, OpenSSH key-loading, and OpenSSH key-generation paths.
Public-Key Methods
Traversio exposes Ed25519, RSA, plus ECDSA P-256, P-384, and P-521 public-key authentication:
.ed25519PrivateKey(rawRepresentation: [UInt8])
.rsaPrivateKey(pkcs1DERRepresentation: [UInt8])
.ecdsaP256PrivateKey(rawRepresentation: [UInt8])
.ecdsaP384PrivateKey(rawRepresentation: [UInt8])
.ecdsaP521PrivateKey(rawRepresentation: [UInt8])
try .ed25519PrivateKey(openSSHPrivateKey: String, passphrase: String? = nil)
try .ed25519PrivateKey(contentsOfOpenSSHPrivateKeyFile: String, passphrase: String? = nil)
try .rsaPrivateKey(openSSHPrivateKey: String, passphrase: String? = nil)
try .rsaPrivateKey(contentsOfOpenSSHPrivateKeyFile: String, passphrase: String? = nil)
try .ecdsaPrivateKey(openSSHPrivateKey: String, passphrase: String? = nil)
try .ecdsaPrivateKey(contentsOfOpenSSHPrivateKeyFile: String, passphrase: String? = nil)The Ed25519 raw-value case expects a 32-byte private-key seed. The RSA raw-value case expects PKCS#1 DER private-key bytes. The ECDSA raw-value cases expect the corresponding curve-specific raw private-key representation. The throwing helpers load OpenSSH openssh-key-v1 Ed25519, RSA, or ECDSA private keys and return the matching auth case. Pass passphrase: when the file is encrypted with the OpenSSH bcrypt KDF and a supported AES cipher.
OpenSSH Key Generation
Traversio also exposes a small OpenSSH key-generation surface:
SSHOpenSSHKeyPair.generate(
algorithm: .ed25519,
comment: String = "traversio",
encryption: SSHOpenSSHPrivateKeyEncryption? = nil
)Supported key-pair algorithms:
.ed25519.ecdsaP256.ecdsaP384.ecdsaP521.rsa(bitCount: Int)
SSHOpenSSHPrivateKeyEncryption(passphrase:cipher:rounds:) supports:
aes128-ctraes192-ctraes256-ctraes128-cbcaes192-cbcaes256-cbc
The default encrypted export matches the OpenSSH baseline: bcrypt with aes256-ctr and 24 rounds.
For a full workflow guide with file-writing examples, permission handling, and direct use of the generated authenticationMethod, see Key Generation.
Generation Example
import Foundation
import Traversio
@available(macOS 26.0, iOS 26.0, *)
func makeDeploymentKey() throws -> SSHAuthenticationMethod {
let keyPair = try SSHOpenSSHKeyPair.generate(
algorithm: .ed25519,
comment: "[email protected]",
encryption: SSHOpenSSHPrivateKeyEncryption(
passphrase: "correct horse battery staple"
)
)
let sshDirectory = FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent(".ssh", isDirectory: true)
let privateKeyURL = sshDirectory.appendingPathComponent("id_traversio")
let publicKeyURL = sshDirectory.appendingPathComponent("id_traversio.pub")
try keyPair.privateKeyPEM.write(to: privateKeyURL, atomically: true, encoding: .utf8)
try keyPair.authorizedKeyLine.write(to: publicKeyURL, atomically: true, encoding: .utf8)
try FileManager.default.setAttributes(
[.posixPermissions: 0o600],
ofItemAtPath: privateKeyURL.path
)
return keyPair.authenticationMethod
}End-to-End Example
import Traversio
@available(macOS 26.0, iOS 26.0, *)
func connectWithECDSAKeyFile() async throws {
let configuration = SSHClientConfiguration(
host: "example.com",
username: "deploy",
authentication: try .ecdsaPrivateKey(
contentsOfOpenSSHPrivateKeyFile: "/Users/me/.ssh/id_ecdsa",
passphrase: "correct horse battery staple"
),
hostKeyPolicy: .knownHostsFile("/Users/me/.ssh/known_hosts")
)
try await SSHClient.withConnection(configuration: configuration) { connection in
let result = try await connection.execute("whoami")
print(String(decoding: result.standardOutput, as: UTF8.self))
}
}If you already manage key material in memory, the raw cases remain available for Ed25519, RSA, and each supported ECDSA curve. SSHOpenSSHKeyPair.generate(...) covers the matching OpenSSH file-generation workflow.
Request Flow
For the OpenSSH-compatible path, Traversio:
- constructs the method-specific public-key request for
ssh-ed25519,rsa-sha2-512/rsa-sha2-256, optional legacyssh-rsa, orecdsa-sha2-nistp* - handles the method-specific
SSH_MSG_USERAUTH_PK_OKconfirmation step - signs the session-identifier-bound authentication payload
- retries with the signed request
For RSA keys, Traversio prefers rsa-sha2-512 and falls back to rsa-sha2-256 when the server's server-sig-algs extension only advertises that SHA-256 path.
If you enable SSHLegacyAlgorithmOptions.sshRSA on SSHClientConfiguration or one SSHProxyJumpHost, Traversio also enables the legacy RSA/SHA-1 path for that specific connection or hop. It appends ssh-rsa to the preferred host-key list, then retries RSA public-key authentication with ssh-rsa only after the server declines the SHA-2 attempt and still offers publickey.
RSA and ECDSA public-key authentication are already live-validated against OpenSSH. Ed25519, RSA, and ECDSA request and signature handling is also covered by deterministic protocol tests. Generated OpenSSH private keys are smoke-tested against the system ssh-keygen -y reader on macOS for the supported algorithms.
Deferred Areas
The public-key feature set stays focused on direct key loading and OpenSSH file compatibility:
- SSH agent integration
- keychain-backed credential loading
Good Fits
Use the public-key API when:
- you want Ed25519, RSA/SHA-2, or ECDSA authentication
- you want optional explicit legacy
ssh-rsacompatibility for an older endpoint and can enable it on that specific connection or jump-host hop - an OpenSSH private key file is acceptable, with
passphrase:supplied when it is encrypted, or you already control the key material yourself - you want the most direct production-oriented path in the current public surface
SSH agent support and keychain-backed credentials remain outside the current public surface.