When working with AWS EC2 instances, you might encounter a puzzling situation where the fingerprint displayed in the AWS console for your imported SSH key doesn't match the fingerprint generated by OpenSSH's ssh-keygen
tool. This occurs even when you're certain you've uploaded the correct public key.
The root cause lies in the different fingerprint calculation methods:
# OpenSSH default fingerprint (SHA256):
$ ssh-keygen -l -f ~/.ssh/my_key.pub
2048 SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789+ user@host (RSA)
# AWS EC2 console shows MD5 fingerprint:
34:5e:12:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01
AWS EC2 uses an MD5 hash of the public key's DER-encoded ASN.1 modulus and exponent for RSA keys. This differs from OpenSSH's default SHA256 fingerprint generation.
To verify your key matches AWS's calculation:
# For RSA keys:
$ openssl pkey -in my_key -pubout -outform DER | openssl md5 -c
# For EC2 keys:
$ openssl ec -in my_key -pubout -outform DER | openssl md5 -c
Here's the complete workflow from key generation to verification:
# Generate a new RSA key
$ ssh-keygen -t rsa -b 2048 -f aws_key -N ''
# Check OpenSSH fingerprint (SHA256)
$ ssh-keygen -l -f aws_key.pub
# Get AWS-compatible fingerprint (MD5)
$ openssl rsa -in aws_key -pubout -outform DER | openssl md5 -c
AWS maintains backward compatibility with older EC2 console versions that originally implemented MD5 fingerprints. While not ideal from a cryptographic perspective, this ensures existing systems continue to work.
While MD5 is considered cryptographically broken for many purposes, in this context it's only used as a visual verification tool. The actual SSH connection still uses modern cryptographic protocols.
For additional assurance, you can:
- Compare the entire public key content
- Use AWS CLI to verify key pairs
- Check the key's creation timestamp in AWS
When working with EC2 instances, many developers encounter a puzzling situation: the fingerprint shown in AWS console differs from what ssh-keygen -l
displays, even when using the exact same public key. Let's dissect why this happens and how to verify keys properly.
AWS EC2 uses the MD5 hash of the public key in RFC 4716 format, while OpenSSH's default shows SHA256 of the key in PEM format. Here's how to see both formats:
# Show OpenSSH default (SHA256/PEM)
ssh-keygen -l -f ~/.ssh/my_key.pub
# Show MD5/RFC4716 format that AWS uses
ssh-keygen -l -E md5 -f ~/.ssh/my_key.pub
To manually verify the AWS fingerprint matches your key:
# 1. Get public key body (between second and third space)
awk '{print $2}' ~/.ssh/my_key.pub | base64 -d | md5sum
# 2. For OpenSSH new format:
ssh-keygen -lf my_key.pub -E md5
# 3. Alternative method:
openssl pkey -in my_key -pubout |
openssl md5 -c
Sometimes converting between formats helps troubleshooting:
# Convert OpenSSH to RFC 4716
ssh-keygen -e -f openssh_key.pub -m RFC4716 > rfc_key.pub
# Convert RFC 4716 to OpenSSH
ssh-keygen -i -f rfc_key.pub -m RFC4716 > openssh_key.pub
- Using wrong key file (private vs public)
- Extra whitespace in pasted key
- Different line endings (CRLF vs LF)
- Key comment field modifications
For CI/CD pipelines, here's a Python script to match AWS fingerprints:
import hashlib
import base64
def aws_fingerprint(pubkey):
key_body = pubkey.split()[1]
decoded = base64.b64decode(key_body)
md5 = hashlib.md5(decoded).hexdigest()
return ':'.join(md5[i:i+2] for i in range(0, len(md5), 2))
print(aws_fingerprint(open('my_key.pub').read()))
The only scenario where fingerprints should match exactly is when using AWS's own generated keypairs (not imported ones) with:
ssh-keygen -lf <(aws ec2 get-key-pair --key-name my-key \
--query 'KeyMaterial' --output text)