This document is intended to provide regular expressions that can be used to confirm if an SSH public key starts with a valid expected value. To help contribute to this information, please open a pull request.
Most of the information collected and presented here was originally discussed in the comments of a gist posted by @paranoiq. Specifically, information provided by @MaPePeR was critical in composing the information here.
The OpenSSH Manual Pages link to ssh-keygen(1) which lists the valid options for the -t flag as:
dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa
Using ssh-keygen -t ...
for each of the above types as follows:
ssh-keygen -t dsa
ssh-keygen -t ecdsa
ssh-keygen -t ecdsa-sk
ssh-keygen -t ed25519
ssh-keygen -t ed25519-sk
ssh-keygen -t rsa
Results in generation of *.pub
files for each key type.
Within each *.pub
file, the string of characters at the beginning is expected to be (in order)
- The key type (this does not always match the value given to the
-t
option when runningssh-keygen
) - A space
- The base64 value of:
\0\0\0
(hex characters)- The hex representation of the length of the key type
- The key type
- The rest of the key
- (optional) A space
- (optional) A comment describing the key
\0\0\0\x0bssh-ed25519
^----------------- \0\0\0 hex characters, always expected
^----------- \x0b the hex representation of the length of ssh-ed25519 (11)
^------- ssh-ed25519 the key type
\0\0\0\x07ssh-rsa
^----------------- \0\0\0 hex characters, always expected
^----------- \x07 the hex representation of the length of ssh-rsa (7)
^------- ssh-rsa the key type
$ echo -ne "\0\0\0\x07ssh-dss" | base64
AAAAB3NzaC1kc3M=
$ echo -ne "\0\0\0\x13ecdsa-sha2-nistp256" | base64
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY=
$ echo -ne "\0\0\0\[email protected]" | base64
AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20=
$ echo -ne "\0\0\0\x0bssh-ed25519" | base64
AAAAC3NzaC1lZDI1NTE5
$ echo -ne "\0\0\0\[email protected]" | base64
AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t
$ echo -ne "\0\0\0\x07ssh-rsa" | base64
AAAAB3NzaC1yc2E=
In some of the shell output the final character is =
, which base64 uses for padding. When the rest of the key is present after the key type in the encoded string it can change the preceding character output in the encoded string.
Using ssh-rsa
for example:
$ echo -ne "\0\0\0\x07ssh-rsa" | base64
AAAAB3NzaC1yc2E=
$ echo -ne "\0\0\0\x07ssh-rsa\x00" | base64
AAAAB3NzaC1yc2EA
$ echo -ne "\0\0\0\x07ssh-rsa\xff" | base64
AAAAB3NzaC1yc2H/
Because of this, if the base64 output final character is =
the last 2 characters cannot be reliably used in regular expression matching.
^ssh-dss AAAAB3NzaC1kc3[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$
^ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$
^sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb2[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$
^ssh-ed25519 AAAAC3NzaC1lZDI1NTE5[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$
^sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$
^ssh-rsa AAAAB3NzaC1yc2[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$
^(ssh-dss AAAAB3NzaC1kc3|ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT|sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb2|ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$
dsa
(dss
) and ecdsa
/sk-ecdsa
may not be considered secure.
^(ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$