How to Programmatically Validate SSH RSA Public Key File Format (id_rsa.pub)


2 views

A standard SSH RSA public key file (id_rsa.pub) contains three space-separated components:

ssh-rsa AAAAB3NzaC1yc2EAAA... comment@example.com

The ssh-rsa prefix is mandatory. The middle part is Base64-encoded data containing the actual public key, and the final part is an optional comment.

Here are three reliable ways to validate the format:

Method 1: Using ssh-keygen

ssh-keygen -l -f id_rsa.pub

This will either output the key fingerprint (valid) or an error message (invalid). Example output for valid key:

2048 SHA256:jX3jD... comment@example.com (RSA)

Method 2: Python Validation Script

Here's a Python 3 script that performs thorough validation:

import base64
import re

def validate_ssh_rsa_pubkey(filename):
    try:
        with open(filename) as f:
            line = f.readline().strip()
        
        parts = line.split()
        if len(parts) < 2:
            return False, "Not enough components"
            
        if parts[0] != "ssh-rsa":
            return False, "Missing ssh-rsa prefix"
            
        try:
            decoded = base64.b64decode(parts[1])
            if not decoded.startswith(b'\x00\x00\x00\x07ssh-rsa'):
                return False, "Invalid key encoding"
            return True, "Valid SSH RSA public key"
        except:
            return False, "Invalid Base64 encoding"
    except Exception as e:
        return False, f"File read error: {str(e)}"

Method 3: Using OpenSSH's Internal Checks

ssh-keygen -e -f id_rsa.pub > /dev/null 2>&1

Silent operation - check the return code ($? in bash). Exit code 0 means valid format.

  • Line breaks: The file should contain exactly one line
  • Whitespace: No leading/trailing whitespace except the single newline
  • Encoding: Must be ASCII or UTF-8 without BOM
  • Key prefix: Must begin with "ssh-rsa"

For pipeline validation, you could use this Bash snippet:

validate_ssh_pubkey() {
    if [ ! -f "$1" ]; then
        echo "Error: File not found" >&2
        return 1
    fi
    if ! ssh-keygen -l -f "$1" &>/dev/null; then
        echo "Error: Invalid SSH public key format" >&2
        return 1
    fi
    return 0
}

A standard RSA SSH public key file (id_rsa.pub) contains three space-separated components:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ... comment@example.com

The format consists of:

  • Key type prefix (always "ssh-rsa" for RSA keys)
  • Base64-encoded key (the actual public key data)
  • Optional comment (typically user@hostname)

Method 1: Using ssh-keygen

The most reliable way to validate an SSH public key is using OpenSSH's built-in tool:

ssh-keygen -l -f id_rsa.pub

This command will:

  • Return the fingerprint if the key is valid
  • Display an error if the format is incorrect

Example output for valid key:

2048 SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 comment@example.com (RSA)

Method 2: Manual Format Checking

For quick checks, you can verify the basic structure:

grep -E '^ssh-rsa AAAA[0-9A-Za-z+/]+[=]{0,3}( .*)?$' id_rsa.pub

This regex validates:

  1. Starts with "ssh-rsa"
  2. Followed by Base64-encoded data starting with AAAA
  3. Optional comment at the end

Checking for Newline Issues

To ensure no extra newlines:

if [ $(wc -l < id_rsa.pub) -gt 1 ]; then
  echo "Warning: Multiple lines detected in public key file"
fi

Validating Multiple Keys

For batch processing multiple keys:

for key in *.pub; do
  if ! ssh-keygen -l -f "$key" &>/dev/null; then
    echo "Invalid key: $key"
  fi
done

For programmatic validation in Python:

import base64
import re

def validate_ssh_pubkey(key_path):
    try:
        with open(key_path, 'r') as f:
            line = f.readline().strip()
        
        parts = line.split()
        if len(parts) < 2 or parts[0] != 'ssh-rsa':
            return False
        
        # Decode Base64 portion to verify structure
        key_data = base64.b64decode(parts[1])
        return True
    except:
        return False

For GitLab CI pipeline validation:

validate_ssh_keys:
  stage: test
  script:
    - for key in $(find . -name "*.pub"); do
        ssh-keygen -l -f "$key" || exit 1
      done