The issue is likely that you are changing the host key in such a way as to make it unparsable. If you try using ssh -v [host]
you'll probably see something like this:
debug1: /home/[user]/.ssh/known_hosts:1: parse error in hostkeys file
If you want to cause a verification error rather than a parse error that gets ignored, you'll have to change the key in a way that ssh
still thinks it's valid. The way to do this depends on what type of key it is. You can force host key types with HostKeyAlgorithms
(eg -o HostKeyAlgorithms=ssh-rsa
). The most common host keys you'll run across with OpenSSH are RSA and ECDSA.
RSA
If you have an RSA host key, Thomas Pornin describes the public key format here:
00 00 00 07 The length in bytes of the next field
73 73 68 2d 72 73 61 The key type (ASCII encoding of "ssh-rsa")
00 00 00 03 The length in bytes of the public exponent
01 00 01 The public exponent (usually 65537, as here)
00 00 01 01 The length in bytes of the modulus (here, 257)
00 c3 a3... The modulus
To avoid an invalid format error, you'll have to keep the string lengths and key type valid. OpenSSH also checks that the public exponent and modulus are not equal to 0, that the modulus is greater than 0, and that the modulus is at least 1024 bits. Here is an example key with a public exponent of 1 and a modulus of 21023 (note that this is not a valid RSA key, it just passes the checks OpenSSH uses for keys in known_hosts
):
AAAAB3NzaC1yc2EAAAABAQAAAIEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
In general, you can change pretty much anything after the 33rd or so base64 character, as long as you keep it the same length and valid base64. All that's required is that the modulus is > 0 and at least 1024 bits.
ECDSA
You can find the key format in the RFC and SEC 1:
Let's break down this example key I just generated:
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLpVyqsu97ajvCDAcc8/W50xhG/Rt2qOxdiy05hAJJtwRTPZRJxrCLayFDWWkNY5ZICRQoYB6Fn7z42JPZNUaI=
00000013 Length of string (19 bytes)
65636473612d736861322d6e69737470323536 ASCII encoding of "ecdsa-sha2-nistp256" ("ecdsa-sha2-[identifier]")
00000008 Length of string (8 bytes)
6e69737470323536 ASCII encoding of "nistp256" ("[identifier]")
00000041 Length of string (65 bytes)
04d2e9572aacbbdeda8ef08301c73cfd... Q
Decoding Q according to SEC 1 section 2.3.4:
04 W
d2e9572aacbbdeda8ef08301c73cfd6e74c611bf46ddaa3b1762cb4e6100926d X
c114cf651271ac22dac850d65a4358e59202450a1807a167ef3e3624f64d51a2 Y
The OpenSSL functions OpenSSH calls for ECDSA keys actually verify that the point is on the curve, so you'd have to do some math to change it to another valid public key. At that point you might as well just generate a new one using:
ssh-keygen -t ecdsa -f /tmp/key -N ''
cat /tmp/key.pub
rm /tmp/key{,.pub}
You can of course do this for RSA and other keys as well.