paramiko / paramiko

The leading native Python SSHv2 protocol library.
http://paramiko.org
GNU Lesser General Public License v2.1
9.14k stars 2k forks source link

[FEAT] - Support for ecdsa-sk and ed25519-sk #2299

Open crabhi opened 1 year ago

crabhi commented 1 year ago

Is this feature for paramiko acting as a client or a server?

Client

What functionality does this feature request relate to?

Keys/auth

For client-side features, does this relate to a specific type of SSH server?

OpenSSH

If you're using paramiko as part of another tool, which tool/version?

Fabric, Ansible

Desired behavior

Openssh v.8.2 added support for FIDO/U2F tokens introducing sk-ssh-ed25519@openssh.com and sk-ssh-ecdsa@openssh.com. See: https://www.openssh.com/txt/release-8.2

When such a key is present in the SSH agent, the client connection fails with (traceback from Ansible, but Fabric fails similarly)

Traceback (most recent call last):
  File "/home/krab/.virtualenvs/ansible/lib/python3.10/site-packages/paramiko/transport.py", line 2185, in run
    handler(m)
  File "/home/krab/.virtualenvs/ansible/lib/python3.10/site-packages/paramiko/auth_handler.py", line 394, in _parse_service_accept
    key_type, bits = self._get_key_type_and_bits(self.private_key)
  File "/home/krab/.virtualenvs/ansible/lib/python3.10/site-packages/paramiko/auth_handler.py", line 218, in _get_key_type_and_bits
    if key.public_blob:
  File "/home/krab/.virtualenvs/ansible/lib/python3.10/site-packages/paramiko/agent.py", line 476, in __getattr__
    raise AttributeError(name)
AttributeError: public_blob

It would be nice if this type of keys would be supported and Paramiko could be used instead of the OpenSSH client.

Anything else?

No response

jakubman1 commented 11 months ago

Hi, is there any progress on this issue? Thanks.

strokovok commented 3 months ago

Found some dirty workaround

You will have to load your key from agent like this:

mykey = paramiko.Agent().get_keys()[0]

And then do this:

if not hasattr(mykey, "public_blob"):
    mykey.public_blob = None

Then connect using this key:

client.connect("a.b.c.d", 22, username="user", pkey=mykey, allow_agent=False, look_for_keys=False)

CC @crabhi @jakubman1 @kofrezo

jakubman1 commented 3 months ago

Found some dirty workaround

You will have to load your key from agent like this:

mykey = paramiko.Agent().get_keys()[0]

And then do this:

if not hasattr(mykey, "public_blob"):
    mykey.public_blob = None

Then connect using this key:

client.connect("a.b.c.d", 22, username="user", pkey=mykey, allow_agent=False, look_for_keys=False)

CC @crabhi @jakubman1 @kofrezo

Thanks for the workaround, but I actually needed key verification, as I am using paramiko just to verify signatures.

I managed to solve my issue by implementing ed25519-sk key verification myself, as that is the only type of -sk key I need to verify.

If anyone is interested in the ed25519-sk key verification, here is my implementation: https://gist.github.com/jakubman1/ea54327166e43bafdbbd4d15a514f848