Introduction
OpenSSH uses HashKnownHosts yes by default in many distributions, which stores hostnames and IP addresses as HMAC-SHA1 hashes in the known_hosts file. This prevents an attacker who gains read access to the file from discovering which servers you connect to. However, hashing makes it impossible to manually audit which hosts are tracked, complicates host key rotation, and makes it difficult to verify compliance with key pinning policies.
Symptoms
cat ~/.ssh/known_hostsshows entries like|1|randomhash|randomhash ssh-ed25519 AAAA...- Cannot determine which servers are in your known_hosts file
- Cannot grep for a specific hostname to check its key
- Automated scripts that parse known_hosts fail on hashed entries
- Compliance audit requires a plaintext inventory of connected hosts and their keys
Common Causes
HashKnownHosts yesset in system-wide ssh_config (/etc/ssh/ssh_config)- SSH client compiled with hashing enabled by default
- User manually hashed existing entries with
ssh-keygen -H - Configuration management tool enforcing hashed known_hosts
- Security policy requiring host identity protection
Step-by-Step Fix
- 1.Check if hashing is enabled:
- 2.```bash
- 3.grep -i HashKnownHosts /etc/ssh/ssh_config ~/.ssh/config 2>/dev/null
- 4.# Check the file for hashed entries
- 5.head -5 ~/.ssh/known_hosts
- 6.# Hashed entries start with |1|
- 7.
` - 8.Check if a specific host is in known_hosts (hashed):
- 9.```bash
- 10.# ssh-keygen can check hashed entries
- 11.ssh-keygen -F server.example.com
- 12.# Returns the matching hashed entry if found
- 13.
` - 14.Unhash known_hosts entries for auditing:
- 15.```bash
- 16.# Create a backup first
- 17.cp ~/.ssh/known_hosts ~/.ssh/known_hosts.backup
- 18.# Disable hashing
- 19.sed -i 's/HashKnownHosts yes/HashKnownHosts no/' ~/.ssh/config
- 20.# Recreate known_hosts by connecting to each host again
- 21.# Or manually unhash if you know the hostnames
- 22.
` - 23.Hash an existing plaintext known_hosts:
- 24.```bash
- 25.ssh-keygen -H -f ~/.ssh/known_hosts
- 26.# This hashes all plaintext entries in-place
- 27.rm ~/.ssh/known_hosts.old # The backup created by -H
- 28.
` - 29.Export a human-readable inventory for compliance:
- 30.```bash
- 31.# For each entry, get the hostname and fingerprint
- 32.while IFS= read -r line; do
- 33.if [[ "$line" == "|1|"* ]]; then
- 34.echo "HASHED: $line"
- 35.else
- 36.host=$(echo "$line" | awk '{print $1}')
- 37.fingerprint=$(echo "$line" | ssh-keygen -lf /dev/stdin 2>/dev/null)
- 38.echo "$host -> $fingerprint"
- 39.fi
- 40.done < ~/.ssh/known_hosts
- 41.
` - 42.Disable hashing for specific hosts only:
- 43.```bash
- 44.# In ~/.ssh/config:
- 45.Host audited-servers
- 46.HostName server1.example.com server2.example.com
- 47.HashKnownHosts no
Host * HashKnownHosts yes ```
Prevention
- Balance security (hashing) with operability (plaintext) based on your environment
- For compliance-heavy environments, use SSH certificates with a CA instead of known_hosts
- Maintain a separate plaintext inventory of all server host keys for auditing
- Use configuration management to deploy known_hosts entries in a controlled manner
- Document the hashing policy and provide procedures for key verification during audits