> On Dec 2, 2016, at 12:37 AM, Glyph Lefkowitz <gl...@twistedmatrix.com> wrote:
>> On Dec 2, 2016, at 12:27 AM, Glyph Lefkowitz <gl...@twistedmatrix.com 
>> <mailto:gl...@twistedmatrix.com>> wrote:
>>> On Dec 2, 2016, at 12:19 AM, Glyph Lefkowitz <gl...@twistedmatrix.com 
>>> <mailto:gl...@twistedmatrix.com>> wrote:
>>>> On Dec 1, 2016, at 7:01 PM, Mark Williams <markrwilli...@gmail.com 
>>>> <mailto:markrwilli...@gmail.com>> wrote:
>>>> On Thu, Dec 01, 2016 at 05:11:37PM -0800, Craig Rodrigues wrote:
>>>>> Hi,
>>>>> I filed this bug:
>>>>> https://twistedmatrix.com/trac/ticket/8931 
>>>>> <https://twistedmatrix.com/trac/ticket/8931>
>>>>> At least for me, conch fails to parse a host key created by OpenSSH
>>>>> in ~/.ssh/known_hosts
>>>>> which is of type ecdsa-sha2-nistp256.
>>>>> Anyone have an idea as to how to fix this?
>>>> As usual you've found a fantastically interesting issue.
>>>> This is conch, the client, right?  I'm guessing so because
>>>> ~/.ssh/known_hosts contains the servers the ssh client trusts.
>>>> (Specifically, among other things it contains a hostname and that
>>>> host's sshd server's public key fingerprint).
>>>> If it is conch, the-client, then deleting the offending entry from
>>>> ~/.ssh/known_hosts and getting a new one makes sense.  That's because
>>>> sshd usually generates a couple of different keys in case clients
>>>> don't support the latest and greatest technology.
>>>> I think deleting the entry in ~/.ssh/known_hosts allows conch to ask
>>>> the server for a different key that it *can* understand.  You should
>>>> be able to find out which server key conch negotiated by doing thing
>>>> following after deleting the offending ~/.ssh/known_hosts entry:
>>>> (<hostname is the problematic OS X server>)
>>>> $ ssh-keygen -H -F <hostname> | awk '{ print $NF }'
>>>> dGhpcyBpcyB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgbG9uZyBob3N0IGtleQ==
>>>> Then on the OS X server, grep for that in /etc/ssh/*.pub
>>>> I bet the key negotiated by conch is not an ECDSA key but rather an
>>>> RSA key.  If this is all the case, then I think you've found a key
>>>> that LibreSSL supports but your client's libssl (which conch calls
>>>> into via cryptography) does not.  What version of libssl do you have?
>>>> If any of this is helpful or relevant I'll ask more questions in the
>>>> ticket.
>>> I think there might be a regression in 16.6.0.
>>> For every version up to 16.6.0, I can do 'conch twistedmatrix.com 
>>> <http://twistedmatrix.com/>' in a shell and it works fine.
>>> On 16.6.0, I get:
>>> Connection to twistedmatrix.com <http://twistedmatrix.com/> closed.
>>> conch: exiting with error [Failure instance: Traceback (failure with no 
>>> frames): <class 'twisted.conch.error.ConchError'>: ('bad host key', 9)
>>> ]
>>> instead.
>>> Worth noting: the keys I have for twistedmatrix.com 
>>> <http://twistedmatrix.com/> are RSA keys.
>>> What did we add recently that changes key parsing?
>> The offending commit is 8164d89104a453947215b9296e8b406f15e63252.  Clearly 
>> something went wrong when introducing ECDSA parsing.
> The problem is not quite as bad as breaking RSA parsing, at least; the issue 
> is that my known_hosts file includes an ecdsa-sha2-nistp256 entry that 
> _precedes_ my ssh-rsa entry.  So the problem is that parsing one of those 
> entries raises an exception which propagates.  From a superficial 
> investigation, it would appear that _all_ ecdsa keys cause this failure, 
> though.

Investigating further, I think I've figured it out.  Here's a patch that fixes 
the problem:

diff --git a/src/twisted/conch/ssh/keys.py b/src/twisted/conch/ssh/keys.py
index d47db7f..570f524 100644
--- a/src/twisted/conch/ssh/keys.py
+++ b/src/twisted/conch/ssh/keys.py
@@ -247,8 +247,10 @@ class Key(object):
         elif keyType in [b'ecdsa-sha2-' + curve for curve in 
-            x, y, rest = common.getMP(rest, 2)
-            return cls._fromECComponents(x=x, y=y, curve=keyType)
+            return cls(load_ssh_public_key(
+                keyType + b' ' + base64.encodestring(blob),
+                default_backend())
+            )
             raise BadKeyError('unknown blob type: %s' % (keyType,))
I suspect, but do not fully understand, that the problem here is point 
compression.  Key._fromString_BLOB naively just does getMP(blob, 2) and expects 
that the x,y will be the EC point.  However, to quote 
https://tools.ietf.org/html/rfc5656#section-3.1, "point compression MAY be 
used".  I don't know exactly how point compression works, but I do understand 
that it means you do funky stuff with the Y value.  I do not believe that 
EllipticCurvePrivateNumbers understands said funky stuff.

A specific ECC integration test with ssh-keygen from OpenSSH and 
twisted.conch.client.knownhosts.KnownHostsFile would have spotted this specific 
manifestation of the issue.  However, another underlying bug is that 
KnownHostsFile _should_ ignore lines that it can't parse.  And, there's another 
potential manifestation of the issue where loading from an actual key blob 
might not work; arguably the problem here is that KnownHostsFile made the 
questionable decision to do its own base64-decoding and pass the blob straight 
to the key rather than just pass the portion of the line after the hostname and 
load it as an openssh-format key directly.


Twisted-Python mailing list

Reply via email to