What you see
Load key "/home/user/.ssh/id_ed25519": invalid format
user@server: Permission denied (publickey).
On many Linux systems the same damaged file gives:
Load key "/home/user/.ssh/id_ed25519": error in libcrypto
In our tests the same file gave invalid format on macOS and error in libcrypto on Debian. So treat them as one problem. A wrong passphrase looks different: incorrect passphrase supplied to decrypt private key.
SSH does not stop here. It continues with other keys and passwords, so the login may fail later or even succeed with something else.
Test the file without connecting
ssh-keygen -y -f ~/.ssh/id_ed25519
A good key prints its public key, or asks for a passphrase and then prints it. A bad one prints the same Load key error. file is not a reliable test here: it still reports OpenSSH private key for a damaged file.
Check what is wrong with it
In a healthy file these print only the header and footer lines. A damaged file with everything on one line would show the whole key, so do not run them in a CI log or on a shared screen:
head -1 ~/.ssh/id_ed25519
tail -1 ~/.ssh/id_ed25519
tail -c 1 ~/.ssh/id_ed25519 | xxd
grep -c $'\r' ~/.ssh/id_ed25519
| You see | Cause | Fix |
|---|---|---|
grep -c prints more than 0 | Windows line endings, from a Windows editor or a copy through Windows | tr -d '\r' < key > key.fixed |
xxd shows 2d, not 0a | No newline after the END line | echo >> key |
Starts with ssh-ed25519 AAAA or ssh-rsa AAAA | This is the public key | Use the file without .pub |
Starts with PuTTY-User-Key-File | PPK format | Convert it, see below |
First line is not -----BEGIN ..., or last line is not -----END ... | Part of the file is missing | Copy it again from the source |
| Everything on one line, with spaces | Line breaks were lost | See CI below |
| Empty file | The copy failed | Copy it again from the source |
file key reports UTF-16 | Saved by PowerShell 5 > or an editor set to Unicode | iconv -f UTF-16 -t UTF-8 key > key.fixed |
The strict checks on line endings and the final newline apply to the newer format, the one starting with -----BEGIN OPENSSH PRIVATE KEY-----. An older -----BEGIN RSA PRIVATE KEY----- file with the same damage still loaded in our test.
After writing a fixed copy, set its permissions and test it. Without this, SSH can refuse it for a different reason, see unprotected private key file:
chmod 600 key.fixed
ssh-keygen -y -f key.fixed
Keys in CI variables
This is a very common source of the error. Without quotes, the shell turns the line breaks into spaces. And printf '%s' adds no newline, so a variable that has no final newline produces a bad file. Both of these failed:
echo $SSH_KEY > key
printf '%s' "$SSH_KEY" > key
This works, as long as the variable holds the complete key with its line breaks:
printf '%s\n' "$SSH_KEY" > key
chmod 600 key
ssh-keygen -y -f key > /dev/null
Run the last line as an early step in the job, and it fails with a clear error. Mind what your CI system does with multi-line values. Some keep them only when stored as files, and some store base64 instead.
PPK keys
OpenSSH does not read .ppk files. Convert them with the PPK key generator, or on Linux and macOS:
puttygen key.ppk -O private-openssh -o key
chmod 600 key
Details in Convert a PPK key to OpenSSH.
Wrong file in your config
If you never meant to use this key, see where it comes from:
ssh -G server | grep '^identityfile '
-i key.pub and IdentityFile key.pub are a common mistake. SSH offers the public key, the server accepts it, and then loading it as the private key fails, often with bad permissions because .pub files are readable by everyone. Point them at the private file.
If the key really is truncated and you have no other copy, it cannot be repaired. Generate a new key, install it, and remove the old public key from your servers.
To get the public key back from a working private key, see how to get the public key from a private key.
Questions
What is the difference between invalid format and error in libcrypto?
Usually none. The same damaged file gives invalid format with LibreSSL builds, as on macOS, and error in libcrypto with OpenSSL builds on Linux.
Can a key with invalid format be repaired?
Often, when only the line endings or the final newline are wrong. A truncated key cannot be repaired: generate a new one and replace the public key on your servers.
Why does my key work locally but fail in CI?
The CI variable usually lost its line breaks or its final newline. Write it to the file with quotes and a final newline, then test it with ssh-keygen -y -f.