ssh_file(3erl)
okay bestie, welcome to ssh_file(3erl) π
β Erlang Module Definition β aka the page where the default file-based callback module spills all its directory tea. It's giving very "your keys are literally in files" energy, and honestly? iconic.
π NAME π
ssh_file β the default callback module for the client's and the server's database operations in the ssh application π«Ά
β¨ DESCRIPTION β¨
This module is the default callback handler for the client's and the server's user and host "database" operations, no cap. All data β for instance key pairs β are stored in files in the normal file system. This page documents the files, where they are stored, and the configuration options for this callback module. π
The intention is to be compatible with the OpenSSH storage in files. Therefore it mimics directories and filenames of OpenSSH. like, it's literally copying OpenSSH's fit, and it ate. π
Ssh_file implements the ssh_server_key_api and the ssh_client_key_api. This enables the user to make an own interface using for example a database handler. πΎ
Such another callback module could be used by setting the option key_cb when starting a client or a server (with for example ssh:connect, ssh:daemon of ssh:shell). π
β οΈ Note: The functions are Callbacks for the SSH app. They are not intended to be called from the user's code! bestie, do not call these directly, i'm begging π
π FILES, DIRECTORIES AND WHO USES THEM π
π Daemons π
Daemons use all files stored in the SYSDIR directory. ποΈ
Optionally, in case of publickey authorization, one or more of the remote user's public keys in the USERDIR directory are used. See the files USERDIR/authorized_keys and USERDIR/authorized_keys2. π
π¦ Clients π¦
Clients use all files stored in the USERDIR directory. π
πΈ Directory contents πΈ
π«Ά LOCALUSER π«Ά
The user name of the OS process running the Erlang virtual machine (emulator). π§
ποΈ SYSDIR ποΈ
This is the directory holding the server's files:
ssh_host_dsa_keyβ private dss host key (optional)ssh_host_rsa_keyβ private rsa host key (optional)ssh_host_ecdsa_keyβ private ecdsa host key (optional)ssh_host_ed25519_keyβ private eddsa host key for curve 25519 (optional)ssh_host_ed448_keyβ private eddsa host key for curve 448 (optional)
The key files could be generated with OpenSSH's ssh-keygen command. π οΈ
At least one host key must be defined. The default value of SYSDIR is /etc/ssh. π
π For security reasons, this directory is normally accessible only to the root user. periodt.
To change the SYSDIR, see the system_dir option. π§
ποΈ USERDIR ποΈ
This is the directory holding the files:
authorized_keysand, as second alternativeauthorized_keys2β the user's public keys are stored concatenated in one of those files. π«Ά
It is composed of lines as for OpenSSH:
(options)? keytype base64-encoded-key comment
where
options :: option(,option)*
option :: % All options are skipped
keytype :: 'ssh-dsa'
| 'ssh-rsa'
| 'ssh-ecdsa-nistp256'
| 'ssh-ecdsa-nistp384'
| 'ssh-ecdsa-nistp521'
| 'ssh-ed25519'
| 'ssh-ed448'
base64-encoded-key :: % The user's public key
comment :: % Comments are skipped
known_hostsβ host keys from hosts visited concatenated. The file is created and used by the client. π
It is composed of lines as for OpenSSH:
(option)? pattern(,pattern)* keytype key (comment)?
where
option :: '@revoked'
pattern :: host | '[' host ']:' port
host :: ip-address | hostname | '*'
port :: portnumber | '*'
keytype :: 'ssh-dsa'
| 'ssh-rsa'
| 'ssh-ecdsa-nistp256'
| 'ssh-ecdsa-nistp384'
| 'ssh-ecdsa-nistp521'
| 'ssh-ed25519'
| 'ssh-ed448'
key :: % encoded key from eg ssh_host_*.pub
id_dsaβ private dss user key (optional)id_rsaβ private rsa user key (optional)id_ecdsaβ private ecdsa user key (optional)id_ed25519β private eddsa user key for curve 25519 (optional)id_ed448β private eddsa user key for curve 448 (optional)
The key files could be generated with OpenSSH's ssh-keygen command. π οΈ
The default value of USERDIR is /home/LOCALUSER/.ssh. π
To change the USERDIR, see the user_dir option. π§
π¦ DATA TYPES π¦
π Options for the default ssh_file callback module π
user_dir_common_option() = {user_dir, string()}β Sets the user directory. πuser_dir_fun_common_option() = {user_dir_fun, user2dir()}user2dir() = fun((RemoteUserName :: string()) -> UserDir :: string())β Sets the user directory dynamically by evaluating theuser2dirfunction. β¨system_dir_daemon_option() = {system_dir, string()}β Sets the system directory. ποΈpubkey_passphrase_client_options() = {dsa_pass_phrase, string()} | {rsa_pass_phrase, string()} | {ecdsa_pass_phrase, string()}β If the user's DSA, RSA or ECDSA key is protected by a passphrase, it can be supplied with those options. π
Note that EdDSA passphrases (Curves 25519 and 448) are not implemented. π«
optimize_key_lookup() = {optimize, time | space}β Make the handling of large files fast by settingtime, but this will use more memory. Thespacevariant shrinks the memory requirements, but with a higher time consumption. β‘
To set it, set the option
{key_cb, {ssh_file, [{optimize,TimeOrSpace}]}
in the call of "ssh:connect/3, ssh:daemon/2 or similar function call that initiates an ssh connection." π
key() = public_key:public_key() | public_key:private_key()β The key representation. πexperimental_openssh_key_v1() = [{key(), openssh_key_v1_attributes()}]openssh_key_v1_attributes() = [{atom(), term()}]β Types for the experimental implementation of theopenssh_key_v1format. π§ͺ
β¨ EXPORTS β¨
okay bestie, this is where the actual callbacks and helper functions live π every signature is exactly what it looks like, no cap.
π¦ host_key(Algorithm, Options) -> Result
π Types
Algorithm = ssh:pubkey_alg()
Result = {ok, public_key:private_key()} | {error, term()}
Options = ssh_server_key_api:daemon_key_cb_options(none())
β¨ Types and description
See the api description in ssh_server_key_api, Module:host_key/2.
π Options
system_dirβ the one option listed here, periodt.
πΈ Files
SYSDIR/ssh_host_rsa_keySYSDIR/ssh_host_dsa_keySYSDIR/ssh_host_ecdsa_keySYSDIR/ssh_host_ed25519_keySYSDIR/ssh_host_ed448_key
π«Ά is_auth_key(Key, User, Options) -> boolean()
π Types
Key = public_key:public_key()
User = string()
Options =
ssh_server_key_api:daemon_key_cb_options(optimize_key_lookup())
β¨ Types and description
See the api description in ssh_server_key_api: Module:is_auth_key/3.
π Options
user_dir_funuser_dir
πΈ Files
USERDIR/authorized_keysUSERDIR/authorized_keys2
This function discards all options at the beginning of the lines in those files when reading them. yes bestie, it just tosses those leading options aside π
π¦ add_host_key(Host, Port, Key, Options) -> Result
π Types
Host =
inet:ip_address() |
inet:hostname() |
[inet:ip_address() | inet:hostname()]
Port = inet:port_number()
Key = public_key:public_key()
Options = ssh_client_key_api:client_key_cb_options(none())
Result = ok | {error, term()}
β¨ Types and description
See the api description in ssh_client_key_api, Module:add_host_key/4.
Note: the alternative, the oldModule:add_host_key/3, is no longer supported byssh_file. so don't try to make it happen, okay? π
π Option
user_dir
πΈ File
USERDIR/known_hosts
π«Ά is_host_key(Key, Host, Port, Algorithm, Options) -> Result
π Types
Key = public_key:public_key()
Host =
inet:ip_address() |
inet:hostname() |
[inet:ip_address() | inet:hostname()]
Port = inet:port_number()
Algorithm = ssh:pubkey_alg()
Options =
ssh_client_key_api:client_key_cb_options(optimize_key_lookup())
Result = boolean() | {error, term()}
β¨ Types and description
See the api description in ssh_client_key_api, Module:is_host_key/5.
Note: the alternative, the oldModule:is_host_key/4, is no longer supported byssh_file. lowkey important, bestie π
π Option
user_dir
πΈ File
USERDIR/known_hosts
π¦ user_key(Algorithm, Options) -> Result
π Types
Algorithm = ssh:pubkey_alg()
Result = {ok, public_key:private_key()} | {error, string()}
Options = ssh_client_key_api:client_key_cb_options(none())
β¨ Types and description
See the api description in ssh_client_key_api, Module:user_key/2.
π Options
user_dirdsa_pass_phrasersa_pass_phraseecdsa_pass_phrase
Note: EdDSA passphrases (Curves 25519 and 448) are not implemented. not me expecting those to work π they do not, okay?
πΈ Files
USERDIR/id_dsaUSERDIR/id_rsaUSERDIR/id_ecdsaUSERDIR/id_ed25519USERDIR/id_ed448
π«Ά decode(SshBin, Type) -> Decoded | {error, term()}
π Types
SshBin = binary()
Type =
ssh2_pubkey | public_key | openssh_key | rfc4716_key |
openssh_key_v1 | known_hosts | auth_keys
Decoded =
Decoded_ssh2_pubkey | Decoded_public | Decoded_openssh |
Decoded_rfc4716 | Decoded_openssh_key_v1 |
Decoded_known_hosts | Decoded_auth_keys
Decoded_ssh2_pubkey = public_key:public_key()
Decoded_public =
Decoded_rfc4716 | Decoded_openssh_key_v1 | Decoded_openssh
Decoded_openssh =
[{public_key:public_key(), [{comment, string()}]}]
Decoded_rfc4716 = [{key(), [{headers, Attrs}]}]
Decoded_openssh_key_v1 = experimental_openssh_key_v1()
Decoded_known_hosts =
[{public_key:public_key(),
[{comment, string()} | {hostnames, [string()]}]}]
Decoded_auth_keys =
[{public_key:public_key(),
[{comment, string()} | {options, [string()]}]}]
Attrs = {Key :: string(), Value :: string()}
β¨ Decodes an SSH file-binary
If Type is public_key the binary can be either an RFC4716 public key or an OpenSSH public key. cute and flexible, we love that for us π
Note: The following key types have been renamed from the deprecatedpublic_key:ssh_decode/2: -rfc4716_public_key->rfc4716_key-openssh_public_key->openssh_key
Note: The implementation of the openssh_key_v1 format is still experimental. so treat it like a first draft, bestie π«Ά
π encode(InData, Type) -> binary() | {error, term()}
π Types
Type =
ssh2_pubkey | openssh_key | rfc4716_key | openssh_key_v1 |
known_hosts | auth_keys
InData =
InData_ssh2_pubkey | InData_openssh | InData_rfc4716 |
InData_openssh_key_v1 | InData_known_hosts |
InData_auth_keys
InData_ssh2_pubkey = public_key:public_key()
InData_openssh =
[{public_key:public_key(), [{comment, string()}]}]
InData_rfc4716 = [{key(), [{headers, Attrs}]}]
InData_openssh_key_v1 = experimental_openssh_key_v1()
InData_known_hosts =
[{public_key:public_key(),
[{comment, string()} | {hostnames, [string()]}]}]
InData_auth_keys =
[{public_key:public_key(),
[{comment, string()} | {options, [string()]}]}]
Attrs = {Key :: string(), Value :: string()}
β¨ Encodes a list of SSH file entries
It encodes a list of SSH file entries (public keys and attributes) to a binary. literally turning the group chat into one neat message π
Note: The following key types have been renamed from the removedpublic_key:ssh_encode/2: -rfc4716_public_key->rfc4716_key-openssh_public_key->openssh_key
Note: The implementation of the openssh_key_v1 format is still experimental. again, experimental means experimental, no cap π
π¦ extract_public_key(PrivKey) -> PubKey
π Types
PrivKey = public_key:private_key()
PubKey = public_key:public_key()
Fetches the public key from a private key. it's giving "give me the public version of this private situation" β¨
okay that's the whole page bestie π big shoutout to Ericsson AB, this is ssh version 4.15.3.1, and the man page is ssh_file(3erl). slay and goodbye ππ
π¦ where this page comes from
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4 Β· Apache-2.0
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4.8 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms