How to Verify RSA Key Pair Matches Using OpenSSH id_rsa and id_rsa.pub Files


2 views

When working with SSH authentication, it's crucial to ensure your private key (id_rsa) and public key (id_rsa.pub) form a valid cryptographic pair. Here are reliable methods to verify their relationship:

The most straightforward way to check key pair matching is by comparing their fingerprints:


# Generate fingerprint from private key
ssh-keygen -y -f id_rsa | ssh-keygen -lf -

# Get fingerprint from public key directly 
ssh-keygen -lf id_rsa.pub

If both commands output identical fingerprints, the keys match. The -y option tells ssh-keygen to extract the public key from the private key file.

For absolute certainty, perform a cryptographic verification:


# Create test file
echo "verification test" > testfile

# Sign with private key
openssl dgst -sha256 -sign id_rsa -out testfile.sig testfile

# Verify with public key
openssl dgst -sha256 -verify <(ssh-keygen -e -f id_rsa.pub -m PKCS8) -signature testfile.sig testfile

Successful verification outputs "Verified OK", confirming the key pair relationship.

RSA keys share the same modulus value. Compare them using:


# Get modulus from private key
openssl rsa -in id_rsa -noout -modulus | openssl md5

# Get modulus from public key
openssl rsa -in id_rsa.pub -pubin -noout -modulus | openssl md5

Identical MD5 hashes indicate matching keys.

For scripting purposes, here's a bash function to automate the check:


function verify_keypair() {
    local private_key=$1
    local public_key=$2
    
    if [[ ! -f "$private_key" || ! -f "$public_key" ]]; then
        echo "Error: Key files not found"
        return 1
    fi
    
    private_fingerprint=$(ssh-keygen -y -f "$private_key" | ssh-keygen -lf - | awk '{print $2}')
    public_fingerprint=$(ssh-keygen -lf "$public_key" | awk '{print $2}')
    
    if [[ "$private_fingerprint" == "$public_fingerprint" ]]; then
        echo "SUCCESS: Key pair matches"
        return 0
    else
        echo "ERROR: Key pair mismatch"
        return 1
    fi
}

  • Ensure key files have correct permissions (600 for private key)
  • Verify the key format (PEM for private, OpenSSH for public)
  • Check for passphrase protection that might prevent access
  • Confirm you're examining the correct key files (common in multi-key environments)

For Python developers, here's how to verify using cryptography library:


from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

def verify_key_pair(private_path, public_path):
    with open(private_path, "rb") as f:
        private_key = serialization.load_pem_private_key(
            f.read(),
            password=None,
        )
    
    with open(public_path, "rb") as f:
        public_key = serialization.load_ssh_public_key(f.read())
    
    # Compare public numbers
    if (private_key.public_key().public_numbers() == public_key.public_numbers()):
        return True
    return False


When working with SSH or cryptographic systems, you'll often need to verify whether a given RSA private key (id_rsa) matches its corresponding public key (id_rsa.pub). This is crucial for security and troubleshooting purposes.

The most reliable way is to compare the modulus (the 'n' parameter in RSA) of both keys, which should be identical for a valid pair.

# Extract modulus from private key
openssl rsa -in id_rsa -noout -modulus | openssl md5

# Extract modulus from public key
openssl rsa -in id_rsa.pub -pubin -noout -modulus | openssl md5

If both commands output the same MD5 hash, your keys match.

For SSH keys specifically, you can use:

ssh-keygen -y -f id_rsa > generated_pub.key
diff generated_pub.key id_rsa.pub

No output means the keys match.

Here's a bash script that automates the verification:

#!/bin/bash

PRIVATE_KEY="id_rsa"
PUBLIC_KEY="id_rsa.pub"

if [ ! -f "$PRIVATE_KEY" ] || [ ! -f "$PUBLIC_KEY" ]; then
    echo "Error: Key files not found"
    exit 1
fi

PRIV_MOD=$(openssl rsa -in "$PRIVATE_KEY" -noout -modulus | openssl md5)
PUB_MOD=$(openssl rsa -in "$PUBLIC_KEY" -pubin -noout -modulus | openssl md5)

if [ "$PRIV_MOD" = "$PUB_MOD" ]; then
    echo "SUCCESS: Key pair matches"
else
    echo "ERROR: Key pair doesn't match"
    exit 1
fi

Permission issues: Ensure your private key has proper permissions (600).

Key format problems: Convert between formats using:

ssh-keygen -p -f id_rsa -m pem

Passphrase-protected keys: You'll need to provide the passphrase during verification.

For integration into Python applications:

from Crypto.PublicKey import RSA

def verify_key_pair(private_key_path, public_key_path):
    with open(private_key_path, 'r') as f:
        priv_key = RSA.importKey(f.read())
    
    with open(public_key_path, 'r') as f:
        pub_key = RSA.importKey(f.read())
    
    return priv_key.n == pub_key.n and priv_key.e == pub_key.e

# Usage
print(verify_key_pair('id_rsa', 'id_rsa.pub'))