---
name: "ssh_file"
section: "3erl"
platform: "linux"
package: "erlang-manpages"
version: "1:25.2.3+dfsg-1+deb12u4"
release: "Debian 12 (Bookworm)"
platforms: ["linux"]
url: "https://new.carta.tech/ssh_file"
---

# ssh\_file(3erl)

Default callback module for the client's and server's database operations in the ssh application

## NAME

ssh\_file - Default callback module for the client's and 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. 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 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.

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!

## FILES, DIRECTORIES AND WHO USES THEM

### Daemons

Daemons uses 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 uses 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.

  To change the SYSDIR, see the system\_dir option.

- **USERDIR:**

  This is the directory holding the files:

  - \*

    *authorized\_keys* and, as second alternative *authorized\_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 the *user2dir* function.

```
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 thoose options.

Note that EdDSA passhrases (Curves 25519 and 448) are not implemented.

```
optimize_key_lookup() = {optimize, time | space}
```

Make the handling of large files fast by setting *time*, but this will use more memory. The *space* variant 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 implementaition of the *openssh\_key\_v1* format.

## EXPORTS

```
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

**Files**

- \*

  *SYSDIR/ssh\_host\_rsa\_key*

- \*

  *SYSDIR/ssh\_host\_dsa\_key*

- \*

  *SYSDIR/ssh\_host\_ecdsa\_key*

- \*

  *SYSDIR/ssh\_host\_ed25519\_key*

- \*

  *SYSDIR/ssh\_host\_ed448\_key*c\>

```
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\_fun

- \*

  user\_dir

**Files**

- \*

  *USERDIR/authorized\_keys*

- \*

  *USERDIR/authorized\_keys2*

This functions discards all options in the beginning of the lines of thoose files when reading them.

```
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 that the alternative, the old Module:add\_host\_key/3 is no longer supported by *ssh\_file*.

**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 that the alternative, the old Module:is\_host\_key/4 is no longer supported by *ssh\_file*.

**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\_dir

- \*

  dsa\_pass\_phrase

- \*

  rsa\_pass\_phrase

- \*

  ecdsa\_pass\_phrase

Note that EdDSA passhrases (Curves 25519 and 448) are not implemented.

**Files**

- \*

  *USERDIR/id\_dsa*

- \*

  *USERDIR/id\_rsa*

- \*

  *USERDIR/id\_ecdsa*

- \*

  *USERDIR/id\_ed25519*

- \*

  *USERDIR/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.

**Note:**

The following key types have been renamed from the deprecated *public\_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.

```
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 (public keys and attributes) to a binary.

**Note:**

The following key types have been renamed from the removed *public\_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.

```
extract_public_key(PrivKey) -> PubKey
```

Types:

PrivKey = public\_key:private\_key()\
 PubKey = public\_key:public\_key()\

Fetches the public key from a private key.
