“Key file”-based authentication

These are typically more secure than basic typed passphrases due to a substantially longer “secret”. They can also be automated, so once implemented, can even be easier to use than simple username/passphrase schemes.

Related topic: devices may communicate keys by including a key as part of the details of a certificate that gets transferred. See certificate communications for details of SSL certificates.

Security Requirements Overview

In general, this process involves the client machine(s) having a private key file which is under the user's control. It is assumed that the end user can sufficiently prevent anyone else from accessing the private key. (This may not be a fully valid assumption: For instance if the system uses a network security model that allows a system administrator to access the key file, then that is a vulnerability to the whole security model. The network system administrator can read the key file, which is analogous to the network system administrator knowing the all the passwords that the user has in that key file. Keys may also be read from the system's memory.) However, in some cases, this security model can work: it simply requires tight control over every client machine that stores the private key. If a client machine is not fully trustworthy, then the private key should not be stored on, or even used by, that machine. (For untrusted situations, see one-time passwords as an alternative.)

[#dplsshky]: Deploying an SSH key so a server will accept/use it

Some of this section of this guide is (at least for now) meant to create keys that will be used with Unix-type operating systems, usage of the OpenSSH server, and maybe for OpenBSD in particular.

[#gensshky]: Generating the key files

generating the SSH key files.

There used to be some more information at this location, which has been moved.

[#badsslky]: Generating SSH keys: Generators of bad SSL keys

Information has been moved to: Generating SSH keys: Generators of bad SSL keys.

[#pbkycmnt]: Generating SSH keys: Recommended further modification: public key file's comment

Information has been moved to: Generating SSH keys: Recommended further modification: public key file's comment.

[#iosshmky]: Generating SSH keys from within Cisco IOS

Information has been moved to: Generating SSH keys from within Cisco IOS

[#oshkydmo]: OpenSSH Key

Information has been moved to: OpenSSH public key file.

[#osshfngo]: OpenSSH Fingerprint Output sample

Information has been moved to: OpenSSH Fingerprint Output sample.

There are different types of key files, so the first step is going to be to determine what kind of key file to make. The key things here to decide are the key encryption method and the format of the key file. There are different kinds of keys, and there are some key conversion options, but ultimately each piece of SSH software will only support keys if they are in a recognized format. Knowing what software will be used may help to determine an appropriate format.

[#cnvsshky]: Converting keys

There may be no need to do any sort of key conversion. However, in case such functionality would be nice, here are some details about how to create one key type from another key type.

Converting private keys to public keys

A public key file may be generated from a private key file.

Using OpenSSH
OpenSSH can read a private key with ssh-keygen -y -f privateKey and output the results to standard output. (The official ssh-keygen man page (at OpenBSD.org) lists the -f privateKey as an optional part of the command line. It is not clear why this is the case.)
Using PuTTYGen

When PuTTYGen loads a private key in PuTTY format, or imports a key (which needs to be a private key), then PuTTYGen will show the “Public key for pasting into OpenSSH authorized_keys file”.

A third party patch for Puttygen may allow a passphrase to be entered on the command line. (Note, however, that including a passphrase on a command line may widely be considered to be a security vulnerability. Therefore, this approach is not widely encouraged.)

Converting key formats
Public Key Format

(This documentation is currently untested.) OpenSSH ssh-keygen program supports conversion with some formats. The actual parameter to import is -i and the actual parameter to export is -e.

Supported formats are documented by OpenBSD's man page for ssh-keygen, specifically in the description of the -m parameter. If importing or exporting is done without specifying a value for -m, then -m RFC4716 is assumed. That SSH2 key format handles public and private keys and is described by RFC 4716: The Secure Shell (SSH) Public Key File Format. Other formats include PEM PKCS8 public keys, specifiable with -m PKCS8, and PEM public keys, specifiable with -m PEM.

Using PuTTYGen
PuTTYGen, a program for the Microsoft Windows platform, uses “PuTTY Private Key” (*.ppk) files and can import keys and export private keys to the OpenSSH key format and the ssh.com key format. (The menu options may just refer to converting keys, but attempting to use a key will reveal that only private keys may be loaded/opened/imported. Attempts to use other files, including public keys, will result in error messages instead of successfully being able to use the key.)
Deploying the existing key files
Required locations for private keys

When an SSH client is using a key to authenticate to an SSH server, both machines involved in that SSH connection need to have a private key. These keys definitely should be different keys. Also, ideally each private key will have never been used by a computer that hasn't had a need to use that key. The private key needs to be used by the computer that is uniquely identifying itself, and the reason that both systems should have a private key is that both systems should be able to authenticate (the computer and/or the user) to the remote system. This is described further with the following examples.

To keep track of what key needs to go where, it is useful to consider what the purpose of each key is. The following text describes the purpose of each key pair in a typical SSH connection where the client is authenticating with a key.

[#svrqpvky]: Key pair to authenticate the SSH server for the SSH client(s)

The SSH server will have one private key that it uses to uniquely identify itself. This is simply a service that the SSH server provides to any client that tries to connect to the server. This helps prevent clients from accidentally submitting confidential information to an incorrect (and possibly rogue, malicious) server. Such a private key is generally called ssh_host_*key and may be stored in /etc/ssh/. These private keys should have restricted rights that do not allow unauthorized users to copy them. There may also be some public keys with similar names (ssh_host_*key.pub) in the same directory. Those are public keys which are provided to any SSH client that connects (even before successful authentication) and so they may be shared.

Key pair for an SSH client to authenticate the client or its end user

SSH clients will generally need to authenticate themselves to an SSH server. One method of performing this authentication is doing this is by using a key pair. When doing so, the SSH client uses a private key to uniquely identify that it is authorized. (For a manually-initiated connection, the reason that the SSH client should be authorized is because it is being used by a trusted user.) The server will grant access to an SSH client that proves that it has possession of an authorized private key. The way that the server does this is by using a copy of the corresponding public key. Therefore, the server needs to be set up in advance so that it has a copy of the public key (and has a way to determine that the specific public key is authorized).

The location of the private key file may vary, possibly being a file that is referred to by a command line or possibly being embedded into some software called an SSH agent. Details will be in the section about testing the keys.

Deploying the public key files

For a key pair to be effectively usable, one computer needs to have the private key and the other computer needs to have a public key.

Using public keys along with an SSH server's private key
In the case of the SSH server having a private key, the SSH client will need to have a copy of the public key, and that copy should be able to be trusted that it is authentic. That can be done by using a trustworthy connection, such as a trusted connection with a reliable source. (It is generally accepted that such a trusted connection can be achieved with suitable encryption.) Another way, commonly accepted and probably easier to implement, is a three part process. The SSH client initiates the SSH connection to the server. The SSH server automatically transmits the public key to the client. Then the end user verifies the key fingerprint.
[#pbkytosv]: Deploying public keys that work with an SSH client's private key
NEWER RE-MADE TEXT

When the SSH server needs a public key that matches the SSH client's private key, placing of the public keys isn't generally quite so automated by the SSH software. Rather, the public keys are often placed onto each server a bit more manually. There may be a few steps to using a private key file on a client so that an SSH server will accept the corresponding public key as authorized.

Having the user('s area) created

First, determine the username that is going to log in. (SSH software may be able to use keys so that standard passwords are not needed, but usernames are still needed.)

If the server doesn't recognize that user, fix that problem: this may require making a user account.

Part of the reason to have the user exist now is so that the user's home directory will exist. That probably is taken care of if the user account exists on the server. However, if the server is somehow using a remotely-defined account, make sure the server can access an existing local home directory for the user.

Allow SSH access

This will be needed before the key is tested, and now may be as convenient of a time as any other.

Make sure the user is allowed to use the remote access software. (This may be easier to test if the user should be able to log in with a standard password.) For example, if the OpenSSH configuration file is using the AllowGroups directive in OpenSSH to restrict which operating system groups may log into the OpenSSH server (a condition which may be checked with “ grep -i AllowGroups /etc/ssh/sshd_config ”), be sure to put a user into a group so the specified user is in a group that the SSH server will allow.

Creating the file

A user who is going to use the key should have the key's information stored in a ~/.ssh/authorized_keys file or perhaps an ~/.ssh/authorized_keys2 file. (The OpenBSD manual page for sshd_config states, “The default is ``.ssh/authorized_keys .ssh/authorized_keys2''. This means that both filenames are equally supported.) That file might be created automatically, with some nice permissions, when a user is created by the operating system. However, perhaps depending on what operating system version is being used, there may not be a pre-existing ~/.ssh/authorized_keys* file might not pre-exist. If such a file does not pre-exist, then feel free to make the ~/.ssh/authorized_keys file, and plan to adjust permissions before the file gets used.

[#autkysrq]: Required contents for an ~/.ssh/authorized_keys* file

Note: before trying to place these contents into a file, read the following section about placing the needed contents into the authorized_keys* file. First, here, is an overview about what those contents will end up looking like.

Warning about old keys

Before performing this step, ensure that the key is known to come from a trustworthy source. Ensure that the key was not created by a compromised system (namely referring to making sure it was not generated using an old compromised Debian(/Ubuntu) OpenSSL release, as detailed by the section about generating keys (specifically the section about bad SSH keys made with older SSL libraries). (Note that although there is a program called ssh-vulnkey that may help identify keys related to the old Debian OpenSSL vulnerability, Ubuntu security advistory says that such “weak user keys” “cannot be detected in all cases”. The cases referred to in that statement might just be referring to keys that are protected by a passphrase.)

If the key is problematic (or if it is unknown whether a key has this known issue), then don't use it! Instead, start to solve the problem by generating key files using some better software.

Initial overview of the file format

The ~/.ssh/authorized_keys file may store multiple public keys. Those wanting official documentation about this file may see the OpenBSD manual for sshd, and specifically the section called “AUTHORIZED_KEYS FILE FORMAT”. (This section is below the OpenBSD manual for sshd: section about ~/.ssh/rc file.)

Basically, each line is either blank, containing a comment that starts with the # hash mark character, or contains information about a key.

Optional: options

A line that has information about a key can start with a reference to some specific “options”. These options may affect how the key gets used. For instance, an option may exist to specify that only certain commands may be used when a specific SSH key is used, or may affect what sort of tunneling options are permitted. In many simple cases where keys may be used, the line with information about a key may not include any of these options. These sort of options are often not required. However, they can exist at the beginning of a line. (If just testing a key out, and if the key is being used in a highly controlled environment where the system's security is still trusted, it may often be easiest to not use any options.) However, if options are being used, then the options will be the first thing on the line. Only if options exist, there is a space character that appears after the options and before the information about the key.

The options may not have unescaped space character. Options are comma-separated. So, the options end when the space character is encountered.

Information about the key

Place the details about the key onto the text file line that should have information about the key.

If options are not included (on the line with information about the key), then the line starts with details about the key. If the file does have options, then the details about the key come right after (the space character that comes right after) the options about how the key gets used.

The information about the key may vary a bit, based on the key type.

OpenSSH SSHv2 key

In the authorized_keys* file, the only details needed about the key are the key type, and the encoded key.

The end result is that the structure of an SSHv2 public key file is very close to the structure of the line of text in an authorized_keys* file. The only difference may be that the authorized_keys* file might have both some options, and a space character, before the contents of the public key file. If those options (and the subsequent space character) do not exist, then the line in the authorized_keys* file ends up exactly matching the contents of the public key file.

Comment

After the information about the key, there may be a space and a comment. This is optional: the line may also just end after providing the information about the key.

Now, here are details on what the information, about the key, must look like.

[#ptinauky]: placing the needed contents into the authorized_keys* file

After making sure that key files are backed up, the information about the public key will need to go to an authorized_keys file on the SSH server. As for getting the key onto the system, the “AUTHORIZED_KEYS FILE FORMAT” section of the OpenSSH sshd man page (which is text located under the OpenBSD man page for sshd: section about OpenSSH's rc file) states “Note that lines in this file are usually several hundred bytes long (because of the size of the public key encoding) up to a limit of 8 kilobytes, which permits DSA keys up to 8 kilobits and RSA keys up to 16 kilobits. You don't want to type them in; instead, copy the” needed data and paste it. The encoded key text may be hundreds or thousands of characters.

Ideally this is going to be pasted into a program designed to be editing a text file. Word-wrap is best to turn off, as each line may need to have some very long strings that lack spaces. Copy and paste operations are NOT likely to result in things being nicely seperated into multiple lines that are short enough to be easy to be able to see at a glance. (Therefore, the reality may vary from some documentation that, for the purposes of making documentation easier, might show keys split up onto multiple lines.)

If copying and pasting into a text editor is not (conveniently) available, concatinating standard output to a file could probably, technically work. However, there are some precautions to consider about how concatenation may be used:

It is generally advised to NOT be placing any sort of credentials onto any command line because sometimes command lines may be seen by users who have a way to view command lines. (One method is by using the w Unix command, although there may also be other ways to see what tasks are running. Although the security risk may be brief, it is widely considered to be a bad habit to allow this risk. Also, some command line shells may, by default or by configuration, record a list of commands that are run (storing the history file). The key could be easily re-creatable, and possibly even directly readable, later by anybody who views that history. This is true regardless of whether the key is located by viewing the active user's command line history file, or whether they obtain this information by running something like w or ps as an other user.) Therefore, using an echo command is not advisable. Running an echo command from within a script file is NOT widely considered to be a safe alternative, so do NOT do that either.

A safe method, without using any specialized text editing software, may be appending standard input by using cat. Just be sure to append to, and not overwrite, any pre-existing contents that are desirable.

If copy and paste is not available, the best option may be to transfer the public key by transfering a file that contains the key. Once done, this transferred key may be appended to the end of the authorized_keys file. If the transferred key is in a file called mykey.pub, here is an example of the file appending:

cat mykey.pub >> ~myusrnam/.ssh/authorized_keys

Note that the myusrnam text continues to be non-literal text referring to the username that the text belongs to.

In the ~myusrnam/.ssh/authorized_keys text file, the end of the line is an optional comment after the key. It may be nice to put a reference there for what key is used. The point would simply be to help someone know which key to use. (This would arguably help an attacker, and so the impact would lower security. However, it may help with ease of use. It should not matter if an untrusted person were to figure out which key file to use, because an untrusted person should not have access to the key file.)

[#autkyprm]: Permissions required for the authorized_keys* file

With OpenSSH, the sshd_config file (which is in /etc/ssh/ for OpenSSH, although the location may vary for Portable OpenSSH) may have a “StrictModes=no” line or, even less commonly, the software may have been started with a command line parameter like “ -o StrictModes=no ”. This may be able to help if using a filesystem that doesn't support Unix permissions, but this is rather unusual. Unless OpenSSH has been specifically told to ignore permissions, it may be fussy about permissions.

Details are in the OpenSSH manual page for sshd: section called “FILES” and documentation about handling file attributes. If the user's name is myusrnam then a command line like the following may address this issue:

chown myusrnam ~myusrnam/.ssh/authorized_keys*
chmod go-w ~myusrnam/ ~myusrnam/.ssh/ ~myusrnam/.ssh/authorized_keys*
[#sshkycmd]: Using an (OpenSSH) SSH key to use (only certain) commands
Overview: Determining whether to restrict a key to only run authorized commands

A key may be used to specify what command will be run whenever that key is used during the creation of an SSH connection. Specifying a specific command in the key file does not have to be done (unless it is desired and needed for some specific purpose). So, if the goal is just to get a key file to allow a log in, then this optional step may be harmlessly skipped. If this step is not taken, then the end user is generally prompted with a standard interface (a command line prompt).

One reason to restrict a key to certain commands is so that a user may be authorized to perform some activities, but not other activities. Another purpose for this is enabling an easy method to run a certain command, perhaps rather automatically, while requiring nothing more from an end user than to make a properly authenticated SSH connection. (After the SSH connection has been firmly established (including any interaction, related to key verification, that occurs between the client and the end user), the program can be started, and may continue to run without requiring that the SSH connection remain established.)

Since restricting a key to run only authorized commands is a step that is entirely optional, the recommended course of action is to skip this process unless there is a reason to perform the process. If the goal is simply to set up a key to allow authentication, skip this process. These instructions are not provided because they are always recommended: in fact they are not always recommended. However, if they are required in order to achieve the desired goal (such as if the goal is to use the SSH protocol to run an authorized command) then, by all means, follow these steps. However, the instructions are mentioned here because this is a logical time to read and follow the instructions if this step is being used.

Recommended order of operations

Creating a key that uses a restricted command may initially complicate things a bit. Therefore, when testing the functionality of using a key file (including when deploying such a key file for the first time), it may be best to delay the complexity of restricting a key to certain commands. If a controlled and trusted environment is available, where attack attempts are not going to be occurring, then consider simply testing the key without restrictions before adding restrictions back in. Then, after things are tested, come back to this section to modify the files. (Then repeat later steps to deploy any files that get changed.) However, naturally, if a user is only authorized to perform a certain action, it would be safer to make sure these restrictions are fully implemented before deploying a key. (Otherwise a less restricted method may be made available, and possibly be used, before things are fully/sufficiently restricted.)

There are multiple ways to specify which command is used. At the time of this writing, this guide is designed for implementing this functionality with OpenSSH. Of the available methods supported by OpenSSH, simply using the authorized_keys file may be easiest (especially if the key file has already been deployed). Choose one of the following three methods:

Using the authorized_keys file

This method may be the simplest (especially after basic usage of the authorized_keys file is working). Note that the “AUTHORIZED_KEYS FILE FORMAT” section of the OpenSSH sshd man page (located under the OpenBSD man page for sshd: section about OpenSSH's rc file) points out “this command may be superseded by either” a “ForceCommand directive or a command embedded in a certificate.” The ForceCommand directive being referred to is an option that may be used in the sshd_config file.

Specify a “command” option in the key file. For example, if using a Protocol 2 key, the authorized_keys file will contain a reference to the key type. Key types may include ssh-dss or ssh-rsa or something starting with ecdsa-sha2-nistp. Using this example, place the following text in the authorized_keys file. (If the authorized_keys has the key, this text needs to go before the text “ssh-dss” or “ssh-rsa”. If the authorized_keys file hasn't had that key data yet, just place the following text at the start of a line, and plan to add the “ssh-dss” or “ssh-rsa” text after the following text which is placed at the beginning of the line.)

command="echo Say \\"Hello\\" cheerfully daily.",no-agent-forwarding,no-port-forwarding,no-X11-forwarding

This example will be allowing a user named myusrnam to use the key file.

mkdir -p ~myusrnam/.ssh
echo -n command=\"echo Say \\\\\\\\\"Hello\\\\\\\\\" cheerfully daily.\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding" " >> ~myusrnam/.ssh/authorized_keys

(Yup, that's right: because of factors such as the echo command outputting one backslash when four are specified, it takes a whoppin' eighteen backslashes (divided into two groups of nine backslashes each) to properly escape the quotation marks that will eventually show up in the output!)

Note that this only covers creating the first part of the line. This first part of the line will affect what happens when the key works, but additional content will need to be added to the same line of text in order for the key to work at all. (Keep reading, particularly the upcoming requirements for files of authorized keys, to get additional details about what else to put into the file. The steps described by this example so far are not a complete set of steps that are sufficient to fulfill all the steps required to have a key be ready to be used.)

Having a command be specified in the certificate
One method to specify what command will be run is to use the certificate. The ssh-keygen command allows for a “ -O force-command=/bin/ls ” command to be specified. (At the time of this writing, this method has not been thoroughly tested by the creator of this tutorial. It is simply being mentioned as an existing option.) (This seems to be related to signing certificates, and may be discussed further in the OpenBSD manual page for ssh-keygen. If ssh-keygen is simply creating keys and not a certificate, using that command line option may have no effect, and does not seem to cause the restrictions that one may be trying to have implemented. .)
Using a directive in the OpenSSH server's configuration file
One method to specify what command will be run is to specify such details in the SSH server's configuration file, or on the command line. Details would be in the documentation on the /etc/ssh/sshd_config file for OpenSSH, specifically related to the ForceCommand option. This may(/must?) affect all users who connect to the specific SSH server instance. (At the time of this writing, this method has not been thoroughly tested by the creator of this tutorial. It is simply being mentioned as an existing option.)

Details on combining this with privilege escalation (using sudo) are discussed in the (later) section about privilege escalation with SSH keys.



OLDER TEXT
Note: this text may refer to /etc/ssh/authorized_keys thinking that was supported; maybe it isn't though?

If the desired username does not yet exist, make the user.

Backing up files on the server that are likely to be changed

An example, will be allowing a user named myusrnam to use the key file. On the system that is going to accept the matching keys in order to allow a login, make the changes performed by the following command lines. (One needs to be able to write to the specified directory: Become a superuser if that is the most convenient way to do so.)

Quick backup guide for files that are about to be changed
ls -td1 /origbak/ver* | head -n 1

(If the output of this command is “ls: /origbak/ver*: No such file or directory” then /origbak/ver1 may be used. If the output had said “/origbak/ver36” then we would be using the next higher number: “/origbak/ver37.”)

This example code is a bit sloppy: If ~myusrnam is /home/myusrnam then the chmod gets /origbak/home/root but not /origbak/home. (Getting all the directories may increase complexity and it was deemed unnecessary overkill for this example.)

This example code will be using /origbak/etc/ver4/.

mkdir -p /origbak/ver4/$( echo ~myusrnam )/.ssh /origbak/ver4/etc
chmod go-rwx /origbak/ver4/$( echo ~myusrnam )/.ssh /origbak/ver4/$( echo ~myusrnam ) /origbak/ver4/etc
/origbak/ver4
/origbak
cp -p ~myusrnam/.ssh/* /origbak/ver4/$( echo ~myusrnam )/.ssh
[#oldauthkyrq]: Getting the needed contents into the necessary file of keys
What goes into the key file

The basic goal is to get the information about the key to be in a file where this information will be used. The information about the key contains an optional set of options, a key type, hash information, and an optional comment. The following is an approximation of what may be going into the text file:

(contents of key file have been moved to the section of generating a key.)

The general syntax of the line, after any options (which are optional and which don't always need to exist), is to start with a key type, and then to include a key, and then to optionally include a command (which is often a reference to who might be anticipated to use the key). Here is an example, split into multiple lines, of what a key would look like. However, unlike this example, the key in the authorized_keys file must not be split into multiple lines for easy reading.

How to get the information where it needs to go
(Some information has been moved from this section.)

The contents of the public key file will need to go into a file called authorized_keys (which goes in a different location depending on who is supposed to be able to use the file). If the public key is meant to be used by all users on the system (which may seem unlikely), then the authorized_keys should go into the same directory as the SSH configuration file (which may be /etc/ssh for OpenSSH, and perhaps a different location for Portable OpenSSH). If the public key file is just meant for authorized users, then the file needs to exist inside the .ssh subdirectory underneath the home directory of each user that will be authorized to use that key. So, if the key is meant to be used by netadmin and sysop then the key would go into ~netadmin/.ssh/authorized_keys and also the ~sysop/.ssh/authorized_keys file. (Note that those files might not be identical; they certainly should not be if one of those files has a key that the other user is not supposed to have access to.)

(Some information has been moved from this section.)

mkdir -p ~myusrnam/.ssh

For protocol 2 keys, the keytype, specified just before the actual key, is going to be either “ssh-dss ” or “ssh-rsa ”. For more documentation about this file, see the “AUTHORIZED_KEYS FILE FORMAT” section of the OpenSSH sshd man page (located under the OpenBSD man page for sshd: section about OpenSSH's rc file).

Follow up work to do on the authorized_keys file
  • Make sure that the file's contents are correct. As examples, check for these things:
    • Is everything related to one key on one line? There are multiple possible problems that could cause part of the line key to go onto a separate line in the text file. Examples include word wrapping in pre-copied text, or word wrapping applied while the text was being pasted, or something like multiple echo commands. If the information related to a single key is on multiple lines, then edit the text file as needed to get everything on one line.
    • Do the “ssh-dss” or “ssh-rsa” terms come immediately after either the start of the file or white space? If the key type is not the first item on the line, such as if there is a command option, then there needs to be a space before the key type. This is needed for any line that doesn't start with a key type. For example, if there is one option and that option is a command option that uses quotation marks, make sure there is a space between the final question mark and the key type.
  • Make sure the ownerships are what is needed/desired. The section about file attributes should cover details on how this may be done. For example, if the file being used is ~myusrnam/.ssh/authorized_keys, an appropriate line for some (Unix) operating systems may be:
    chown myusrnam:myusrnam ~myusrnam/.ssh/authorized_keys ~myusrnam/.ssh
    However, some operating systems may need a different GID specified after the colon in that example. (Yet other operating systems, likely older ones, may require a period instead of the colon shown in the prior example. More details may be available in/near the section about file attributes/permissions/ownerships.)
  • Make sure the permissions are something that the SSH server will accept. Details may be in the section about file attributes. This example will be allowing a user named myusrnam to use the key file.

    chmod og-w ~myusrnam/.ssh/authorized_keys ~myusrnam/.ssh

    If the permissions for any one of these locations must allow group writing, note that the “AUTHORIZED_KEYS FILE FORMAT” section of the OpenSSH sshd man page (located under the OpenBSD man page for sshd: section about OpenSSH's rc file) points out that the .ssh/authorized_keys file may “be modified or replaced by” the user with such write permissions. Then, if it is still desirable to allow this, overriding this requirement may be done by setting a StrictModes option in the OpenSSH server's configuration file. This will affect all users who may use that SSH server.

[#tstsshky]: Testing the deployed keys
[#tsshkprp]: Preparing to test the deployed keys: overview, considerations, and simplification

Consider testing the deployed key. Naturally, the effect should be considered before running a test. For example, if logging in with the key will cause the server to run some other specific command, such as rebooting the system, then the impact of that command should be considered before performing the test. (Perhaps there will be some sort of benefit in performing the test at a later time, or temporarily changing what happens when the key is used (and remembering to change the key's effect back after the test is performed).) If the key will simply provide a command prompt to a trusted user, then running the test is probably not an issue, so plan to perform a test that verifies that the key is accepted.

Testing a private key that is used by an SSH server is generally as simple as just making an SSH connection.

Therefore, the rest of this section is more focused on testing a private key that is on an SSH client.

To verify that the key is successfully usable, make sure the desired system (with the SSH client) has the private key. (This should be the case if the key was generated on the system with the OpenSSH client. If the key was generated on another computer, whether that be a server with OpenSSH server installed or another client that ran PuTTYGen, the private key may not yet be on the system. In such a case, transfer the key.)

It may be easier to first create a manual connection to the SSH server, logging in with standard password credentials. (In some cases, like where standard password credentials are prohibited, that might not be easier.) This way some things can be verified, such as the IP address being correct, the SSH server successfully running, and that the client has the public key that corresponds to the SSH server's private key. That latter step, especially, may be likely to need some attention, and if there are messages related to keys then testing just one key pair first may limit the complexity because it will be clear which key pair is being referred to. If the public key that corresponds to the server's private key is not known to have been saved to the client, display the signature of the server's key in anticipation of the next step. The next step, then, is to proceed to perform the remaining steps of manually verifying key fingerprints/signatures before any SSH connections are accepted. After the fingerprint is verified, the remote system should indeed actually be the system that the client is attempting to connect to (assuming that the private key and the method of keying have both not been compromised). Otherwise, see the section on dealing with a(n unauthorized) key change may be appropriate.

Using the private key on the client

For this to be expected to work, it is assumed that the relevant public keys being deployed to the SSH server has already been done, and that preparations have been completed. (Especially the important preparations are making sure that the SSH connections can be made, so either the client has a saved public key that corresponds to the SSH server's private key, or there are plans to manually make sure than an SSH key/signature/fingerprint validates.)

Attempt to create an SSH connection. Hopefully the section about implementation-specific details will quickly lead to a successful test. Keep in mind that if something doesn't work (like the key not being expected or a desired resulting command not running), one may check details offered by the section on troubleshooting the use of private keys on SSH cleints.

Details specific to certain software implementations

Software-specific details follow.

OpenSSH

In a key pair, the private key file generally has no extension as part of its filename.

OpenSSH will ignore any key file (and, therefore, any keys in that file) if the key file's permissions are not accepted by the OpenSSH software. With Unix permissions, such a file must not be accessible (including being readable) by others. In the case where the key is stored on something like a FAT partition which might be mounted in a way that all files appear to be readable, OpenSSH will not allow the file to be used. (The solution may need to be something that seems even less secure: copying the file to another partition where OpenSSH itself can verify that the permissions seem suitable enough for OpenSSH.) Painfully, the client software may not report any errors that describe why a file filled with credentials may be getting ignored.

If the keys are stored in the correct relevant ~/.ssh/id* file, then OpenSSH may find the keys rather automatically. Another option, which may especially be simpler for a quick, fast test, is to use the “ -i name-of-private-key-file ” parameters.

The OpenBSD man page for OpenSSH client's description of -i notes some default filenames, and also notes that the software “will also try to load certificate information from the filename obtained by appending -cert.pub to identity filenames.”

PuTTY
Desired results

If a username is not provided, PuTTY may need to ask for the username (after the SSH connection is at least partially created). Once the username has been provided in some fashion, then PuTTY should try to use a key to authenticate. When things work well, it is expected that PuTTY will show text such as:

Authenticating with public key "nameOfKeyFromKeyFile"

(The next line will be output from the remote system.)

If PuTTY asks for a password, then the key was not successfully used (either because PuTTY failed to use it, or, more likely, because the server failed to accept it).

If PuTTY works, and if the results are that a command is run on the remote system, then the command will run and the SSH session may be closed. Seeing a window close may not be the most satisfying experience when one wants to see that everything is working well. There are two ways to deal with that when testing. One is to change the command that gets run to something that will prompt the user. (For example, have it run man man.) Another option is to perform the following steps:

  • Do not provide PuTTY with the username (via the command line, nor the GUI) before the SSH connection is made.
  • Adjust the “Session” configuration. If the SSH connection will be created with the GUI, this can be done from the “Putty Configuration” screen before the connection is made. If PuTTY is created with the command line, this may need to happen after the SSH connection is made. Either way, this can be done before the username is entered.
  • If an SSH is already started, and if the setting still needs to be changed, access the program's “System Menu”. (Pressing Alt-Space, a standard for Microsoft Windows applications, will work if PuTTY's setting for this, on the Window\Behavior screen, was previously customized to allow this standard behavior. Another option that may work is just pressing “Alt” alone, although that also requires previous customization of the setting on the Window\Behavior screen. Otherwise, use a pointing device (such as a mouse) to click on the icon in the lower-left corner.) Then choose “Chang Settings...” to bring up the “Putty Reconfiguration” screen. (Alternatively, one of the options related to a session may be used.)
  • From the “PuTTY Configuration” (or “PuTTY Reconfiguration”) screen, choose the “Session” screen full of options. Then, in the “Close window on exit:” section, move the radio button from “Only on clean exit” to “Never”. (Note that if this term “Never” will usually only apply to this specific SSH connection. The exception to this is if the change is both made from the “PuTTY Configuration” screen (not the “PuTTY Reconfiguration” screen), and also the change is saved to a saved “session” before opening the connection.
Using the key

The private key file being used should be in Putty's *.PPK file format. (See converting key types for details.)

One option that may be preferable is to use the “PuTTY Agent” software. However, performing a manual connection first may be easier to deal with in case troubles do occur. (Then troubleshooting won't need to deal with the added complexity of interactions with the Agent software.)

Using the command line

Those who prefer to use the command line may use:

PuTTY -ssh -i ppkFileName.PPK -P 22 username@nameOrIPofRemoteSystem

Some of those command line options for PuTTY may be optional parameters which are not required: the one related to keys are -i and the following parameter: the name of the PuTTY Private Key file. The name/address of the remote system will be needed. The username@ may be left off, in which case PuTTY will prompt the end user for a username.

If a saved “session” (of connection settings) was previously created from the GUI, a command line may be used to load the session. (Details about how to create the saved “session” are in the section about using the GUI.) The command line to use for such a connection is:

PuTTY -load "SessionName"

(The SessionName may (and should) be customized.)

Using the GUI

For those who are using the graphical user interface, under Connection\SSH\Auth is an “Authentication parameters” section with a dialog box to specify a “Private key file for authentication:” (and a “Browse...” button that affects that dialog box). If this is a system that will be connected to regularly, then after filling out that dialog box, the most desirable course of action might NOT be to choose the button on the bottom of the screen that says “Open”. Instead, if it is certain that no unauthorized person will ever be using this PuTTY configuration, consider saving the full login settings for easier use later. If so, proceed with the following steps to create a “session”.

To use a session, first go to the spot under the “Connection” category to the options screen called “Data”. Fill in the desired “Auto-login username” (which may be the only option within the “Login details” section.) Then, head back up to the “Session” screen, make sure that the top part of the screen has all the right settings (for the “Host Name (or IP address)”, “Connection type”, and TCP “Port”), type in a name that the “Saved Session” is about to have, and choose to “Save” that session. Then, at any time including future times when PuTTY is run, the connection may be made by choosing the listed “Saved Session” and choosing “Load” and “Open”. Even faster is could be to use the command line to specify a saved session to use.

[#fxsshpvk]: Troubleshooting/fixing the use of private keys on SSH cleints

There are several potential troubles which may cause things to not work. Here are some things to check:

  • Is it possible that the key encrypted with a passphrase? (Ramifications of keys which require passphrases is a concept that isn't fully covered by this documentation.)
  • Can the user log in with any other method of verifying credentials, such as using a password when using an SSH connection, or even logging into the machine locally? (Note that if the answer is “no”, meaning that the user cannot log in successfully with the other method, that may not completely answer the question as to why the SSH key isn't working. For example, there might be a restriction that prevents local logins by specific groups of users to specific machines. If that exists, then the user won't be able to log in locally but the cause will have nothing to do with why SSH keys aren't working.)
  • Are the access rights (file ownership, filesystem permissions) of the .ssh/authorized_keys file something that is acceptable for the SSH server?
  • Are the contents of the authorized_keys file valid, and including the key which is supposed to be used?
  • Are the permissions of the private key file being accepted by the SSH client, and is the right key file being used?
  • What does the authorization log on the server have to say about the login attempt? (In Unix, this is probably using the “AUTH” logging facility, in which case /var/log/authlog may be the relevant filename to check out. However, the actual log can be modified by using the SyslogFacility variable in the sshd_config file being used, which might be located at “/etc/ssh/”.)
    • As an example of how this could help, the log file may have a tell-tale description such as “User myusrnam from 192.0.2.1 not allowed because none of the user's groups are listed in AllowGroups”. (In that case, add the user to a group that is listed in a AllowGroups directive in the OpenSSH server's sshd_config file, which may be located in the /etc/ssh/ directory.)
  • If a specific command is specified, and that doesn't seem to be working:
    • Does the command work when logged in locally as the end user?
    • Can a different command, such as sh, work better?
      • If so, consider adjusting the command that gets run, by prepending echo to the command that is run when the key is used. Then, when that happens, does this result in outputing the expected command line?
    • Keep security in mind, so if there is any chance that somebody else may take advantage of temporary removal of restrictions, then do not run a test that involves removing restrictions about what commands are run. However, if it is safe and secure to do so, consider finding out fi the same command runs successfully when using a command shell as the logged in user, and then (as the end user) manually running the command from the command line.
[#sshkysdo]: Using privilege escalation (sudo access) with SSH keys

This is often used while using an SSH key to run a command on a remote system.

Naturally, the first recommended step to changing a file is to back up a file that is about to be changed.

Quick backup guide for files that are about to be changed
ls -td1 /origbak/ver* | head -n 1

(If the output of this command is “ls: /origbak/ver*: No such file or directory” then /origbak/ver1 may be used. If the output had said “/origbak/ver36” then we would be using the next higher number: “/origbak/ver37.”)

This example code uses /origbak/etc/ver5/.

mkdir -p /origbak/ver5/etc
cp -p /etc/sudoers /origbak/ver5/etc/.

This text assumes knowledge of how to get the SSH key files to allow a specified command to run, an ability which is described by the previous section about using an OpenSSH key to use (only certain) commands. This text assumes knowledge of how to get the SSH key files to allow a specified command to run. (If further details are needed, see the previous section.)

Use “ visudo ”. Look for a few lines that look something like the following:

# Same thing without a password
# %wheel  ALL=(ALL) NOPASSWD SETENV: ALL
%wheel  ALL=(ALL) NOPASSWD SETENV: ALL

Finding the above lines is not necessarily important, so do not worry if they can't be located. It simply makes sense to put the next line after those lines.

The next step will be to add a line to the text file which shows what should be allowed. For anyone interested in the precise technical details curious, the precise syntax of the line to be added is documented by Manual for the sudoers file: “User Specification” section. However, for those simply interested in seeing an example that is relatively easy to be able to follow, an example follows. For this example, we will be allowing a user named myusrnam to use the key file.

myusrnam  ALL = (ALL) NOPASSWD:/bin/ls *, echo *

The first part of that line is a list of users/groups that may be allowed to run this command. In this example, the specified list consists just of a single user that has a username of myusrnam.

The part between the list of users (at the start of the line) and the equal sign later represents a lists of hosts. (For what purpose? More details needed...)

After the equal sign is a comma-separated list of command specifications. (If there is just one command specification then there is no comma needed.) Really, there's no huge difference between including multiple possible command specifications in a comma-separated list, or to just use one command specification per line and to have multiple nearly-identical lines of text (as needed to describe all of the desired command specifications). However, it is important to know this is comma separated, because any actual commas needed as part of the command will need to be escaped in this text file.

The * is actually not part of the command line, but specifies that sudo will accept any text (so any parameters are allowed). (The space after the name of the command does not have to be used when the desired command is given to sudo. If the end user just tries to run “ls” without a space, that will work even though the text file might look like that it dictates a space, and even though the text file specifies what path the expected executable is in.)

A command specification has a command line. However, it may also have some information before the command line, and that is where the (ALL) NOPASSWD: comes into play. If the first (non-whitespace) character of a command list is a left parenthesis (“(”) character, then the command specification starts with something that the documentation calls a “Runas_Spec”. Within a single command specification, there are some things (other than a Runas_Spec) that may occur before the command line that will be run. (If there is a Runas_Spec, these other things will come after the Runas_Spec, and before the start of the command line.) These additional terms that may come before the command line will either include an equal sign, or they will end with a colon. These instructions are being a bit vague about what is included within the parentheses of a Runas_Spec of what terms (with an equal sign or ending with a colon) are recognized: The full list is shown by the Manual for the sudoers file: “User Specification” section.

(The possible terms with an equal sign listed in the Manual for the sudoers file: “User Specification” section are related to SELinux. Such terms do not occur in the “User specification” section of the OpenBSD Manual Page for /etc/sudoers file. Presumably that is because the variation included with OpenBSD may not have the same level of support for SELinux, or that such functionality is not expected to work because how SELinux is not supported by some other part of a base OpenBSD installation.)