paramiko / paramiko/paramiko

RSAKey fingerprint doesn't match imported EC2 key pair fingerprint

Open
#1,228 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
9.9k
Forks
2.1k
PR merge metrics
No merged PRs in 30d

Description

Edit: I believe this has to do with getting the DER of the public key. How can I achieve this?

I'm trying to verify a .pem private key file as having the same public key fingerprint as imported EC2 key pairs on AWS. As mentioned in boto3's documentation, AWS returns a MD5 public key fingerprint for imported EC2 key pairs. Paramiko's documentation mentions that that the get_fingerprint method also returns a MD5 fingerprint of the public key. However, when I compare the imported EC2 key pair's fingerprint with the fingerprint computed with the public_key_fingerprint method below, they differ.

(This serverfault question answer mentions that AWS EC2 gives the SSH2 fingerprint, if that's relevant.)

My code to generate a key pair, convert a private key to a public key, and get the public key fingerprint are the following:

def generate_rsa_key_pair(self):
    """generate and return RSA private/public key pair strings

    Returns:
        tuple:
            str: Private key string
            str: Public key string
    """
    private_key = paramiko.RSAKey.generate(2048)
    with StringIO() as pem_stringio:
        private_key.write_private_key(pem_stringio)
        pem_str = pem_stringio.getvalue()
    pub_key_str = self.pem_to_public_key(pem_str)
    return (pem_str, pub_key_str)

# This is what gets uploaded to AWS via import_key_pair
def pem_to_public_key(self, pem_str):
    """converts pem RSA private key string to public key string"""
    with StringIO(pem_str) as pem_stringio:
        private_key = paramiko.RSAKey.from_private_key(pem_stringio)
    return " ".join([private_key.get_name(), private_key.get_base64()])


def public_key_fingerprint(self, pem_str):
    """convert private key to public key's fingerprint"""
    with StringIO(pem_str) as pem_stringio:
        private_key = paramiko.RSAKey.from_private_key(pem_stringio)
    digest_hex = private_key.get_fingerprint().hex()
    return ":".join(a+b for a,b in zip(digest_hex[::2], digest_hex[1::2]))

The serverfault answer gave the following command:

openssl pkey -in theprivatekeyfile.pem -pubout -outform DER | openssl md5 -c

which successfully spat out the correct fingerprint, so this question could be rephrased as "How do I get paramiko to do what that command does?"

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Paramiko's RSAKey.get_fingerprint, from_private_key, get_base64, and the pem_to_public_key and public_key_fingerprint functions shown in the issue. Compare their input to the OpenSSL pkey -pubout -outform DER | openssl md5 -c command and AWS import_key_pair behavior. Done means determining whether Paramiko can produce the AWS-compatible fingerprint and documenting or tracking the required change.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cryptography
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.