It is not weird you just assumed that the public key is stored in the registry as it is stored on your server, which is not the case. I did some more research and found out that putty stores the public keys in his own format [1] and not in the openssh format which is the format of your host key on the server. You need to convert the registry entry from the putty key format to the openssh key format to be able to compare the fingerprints.
I have slightly modified a script of Mark Grandi [2] which you can use to make the conversion:
Code: Select all
#!/usr/bin/env python3
#
# script that converts between
# openSSH 'known hosts' to what putty
# stores in the registry for its known hosts
#
#
# written by Mark Grandi, March 27, 2014
# ruined by cronoik :(
import binascii
import struct
import base64
import io
import sys
import argparse
import os, os.path
import collections
import re
import socket
import math
# represents the data that would go inside the registry key for the putty known hosts
# add your registry values here:
keyName = 'rsa2@2.....'
exponent = '0x10001'
modulus = '0x.......'
PuttyKnownhostEntry = collections.namedtuple("PuttyKnownhostEntry", ["keyName", "exponent", "modulus"])
yourkey = (PuttyKnownhostEntry(keyName, exponent,modulus))
def main():
''' figures out what function to call
@param args - the argument parser Namespace object we got from parse_args()
'''
puttyToOpenSSH()
def puttyToOpenSSH():
''' converts putty known hosts entries to openSSH ones
@param args - the argument parser Namespace object we got from parse_args()
'''
puttyEntries = []
puttyEntries.append(yourkey)
# now go through each entry and convert it to a openssh line
openSshLines = []
for iterEntry in puttyEntries:
# parse the key name, which has the hostname or ip, port, and algorithm
# it looks like: 'rsa2@60101:mgrandi.no-ip.org'
alg = iterEntry.keyName.split("@")[0]
opensshAlg = ""
if alg == "rsa2":
opensshAlg = "ssh-rsa"
elif alg == "dsa":
opensshAlg = "ssh-dss"
secondPart = iterEntry.keyName.split("@")[1]
port = secondPart.split(":")[0] # putty always stores the port
hostOrIp = secondPart.split(":")[1]
hostName = hostOrIp
try:
addrList = socket.getaddrinfo(hostOrIp, port)
hostName = addrList[0][4][0]
except OSError as e:
print("#WARNING: error when trying to resolve '{}:{}', error: '{}'\n\n".format(hostOrIp, port, e))
hostName = hostOrIp
# now calculate the data that it stores
resultBytes = io.BytesIO()
resultBytes.write(struct.pack(">i", 7)) # write that there is a 7 byte algorithm identifier
resultBytes.write(opensshAlg.encode("utf-8")) # write algorithm identifier
expInt = int(iterEntry.exponent[2:], 16)
# how many bytes does it take to store this exponent?
numBytes = math.ceil(int(expInt).bit_length() / 8)
# write length of exponent
resultBytes.write(struct.pack(">i", numBytes))
# write exponent
resultBytes.write(struct.pack(">{}s".format(numBytes), int(expInt).to_bytes(numBytes, "big")))
modulusData = binascii.unhexlify(iterEntry.modulus[2:])
# here we have to 'add' a b'\x00' byte to the start of this, because i guess we are padding the modulus
# to match the RSA key modulus, see my comment later on in this file)
modulusData = b'\x00' + modulusData
# write length of modulus
resultBytes.write(struct.pack(">i", len(modulusData)))
# write modulus
resultBytes.write(modulusData)
# base64 it
result = base64.b64encode(resultBytes.getvalue())
# now we have the openssh line
# put it in our list
# (like [68.98.45.184]:23 ssh-rsa AAAAB3.....)
openSshLines.append("[{}]:{} {} {}".format(hostName, port, opensshAlg, result.decode("utf-8")))
for iterEntry in openSshLines:
print(iterEntry + "\n")
if __name__ == "__main__":
main()
I haven't tested it with ed25519 keys because I don't have registry entries of servers with such a key. In case it doesn't work try to set opensshAlg = "ed25519" or look for a script which does the conversion between the putty key format and the openssh key format.
[1]
https://unix.stackexchange.com/question ... -putty-key
[2]
https://github.com/mgrandi/openssh-putt ... -converter