pyinfra icon indicating copy to clipboard operation
pyinfra copied to clipboard

ValueError: q must be exactly 160, 224, or 256 bits long

Open luroc opened this issue 7 months ago • 4 comments

Describe the bug

Just starting with pyinfra. I'm trying to do an initial install. When trying to run pyinfra with below inventory.py or below cli command I get a 'ValueError: q must be exactly 160, 224, or 256 bits long' error.

To Reproduce

Steps to reproduce the behavior, please include where possible:

  • Operation code & usage inventory.py
import getpass
import os

HOSTNAME = "olivar"
SSH_USER = "root"  # e.g., 'ubuntu', 'admin', 'root'

hosts = [
    (HOSTNAME, {
        "ssh_user": SSH_USER,
        "ssh_password": getpass.getpass(prompt=f"Password for {SSH_USER}@{HOSTNAME}: ")
    }),
]

cli command

pyinfra --ssh-user="root" --ssh-password="mypw" myhost deploy.py
  • Target system information current EndeavourOS (archlinux) on Lenovo T480
  • Example using the @docker connector (helps isolate the problem) don't want to install docker on this system if not absolutely necessary

Expected behavior

Have the command run without error and create inital users and install inital packages.

Meta

  • Include output of pyinfra --support.
    If you are having issues with pyinfra or wish to make feature requests, please
    check out the GitHub issues at https://github.com/Fizzadar/pyinfra/issues .
    When adding an issue, be sure to include the following:

    System: Linux
      Platform: Linux-6.12.28-1-lts-x86_64-with-glibc2.41
      Release: 6.12.28-1-lts
      Machine: x86_64
    pyinfra: v3.3.1
      click: v8.1.8
      coverage: v7.8.0
      coverage: v7.8.0
      distro: v1.9.0
      gevent: v24.11.1
      jinja2: v3.1.5
      packaging: v25.0
      paramiko: v3.5.0
      pytest: v8.3.5
      pytest: v8.3.5
      python-dateutil: v2.9.0
      pyyaml: v6.0.2
      pyyaml: v6.0.2
      setuptools: v80.3.1
      typeguard: v4.4.2
      typing-extensions: v4.13.2
      wheel: v0.45.1
    Executable: /usr/bin/pyinfra
    Python: 3.13.3 (CPython, GCC 14.2.1 20250207)
  • How was pyinfra installed (source/pip)? arch AUR
  • Include pyinfra-debug.log (if one was created)
  File "/usr/lib/python3.13/site-packages/pyinfra_cli/main.py", line 225, in cli
    _main(*args, **kwargs)
    ~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra_cli/main.py", line 351, in _main
    connect_all(state)
    ~~~~~~~~~~~^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/api/connect.py", line 37, in connect_all
    greenlet.get()
    ~~~~~~~~~~~~^^
  File "src/gevent/greenlet.py", line 797, in gevent._gevent_cgreenlet.Greenlet.get
  File "src/gevent/greenlet.py", line 373, in gevent._gevent_cgreenlet.Greenlet._raise_exception
  File "/usr/lib/python3.13/site-packages/gevent/_compat.py", line 50, in reraise
    raise value.with_traceback(tb)
  File "src/gevent/greenlet.py", line 900, in gevent._gevent_cgreenlet.Greenlet.run
  File "/usr/lib/python3.13/site-packages/pyinfra/api/host.py", line 380, in connect
    self.connector.connect()
    ^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/ssh.py", line 201, in connect
    return self._connect()
    ^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/ssh.py", line 231, in _connect
    self.client.connect(hostname, **kwargs)
    ^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/sshuserclient/client.py", line 182, in connect
    super().connect(hostname, **config)
    ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/client.py", line 485, in connect
    self._auth(
  File "/usr/lib/python3.13/site-packages/paramiko/client.py", line 734, in _auth
    self._transport.auth_publickey(username, key)
    
  File "/usr/lib/python3.13/site-packages/paramiko/transport.py", line 1709, in auth_publickey
    return self.auth_handler.wait_for_response(my_event)
    ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/auth_handler.py", line 248, in wait_for_response
    raise e
  File "/usr/lib/python3.13/site-packages/paramiko/transport.py", line 2262, in run
    handler(m)
    
  File "/usr/lib/python3.13/site-packages/paramiko/auth_handler.py", line 404, in _parse_service_accept
    sig = self.private_key.sign_ssh_data(blob, algorithm)
    ^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/dsskey.py", line 120, in sign_ssh_data
    ).private_key(backend=default_backend())
    ^^^^^^^^^^^^^^^
ValueError: q must be exactly 160, 224, or 256 bits long
  • Consider including output with -vv and --debug.
pyinfra --ssh-user="root" --ssh-password="thepw" thehost intial_install_deploy.py -vv --debug                                                        23:45:45 [71/603]
--> Loading config...                                                                                                
--> Loading inventory...                                                                                             
    [pyinfra_cli.inventory] Creating fake inventory...
    [pyinfra_cli.inventory] Checking possible group_data at: /home/lvl/library/repos/pyinfra/group_data              
                                                                                                                     
--> Connecting to hosts...                                                                                           
    [pyinfra.connectors.ssh] Connecting to: thehst ({'allow_agent': True, 'look_for_keys': True, '_pyinfra_ssh_forward_agent': False, '_pyinfra_ssh_config_file': None, '_pyinfra_ssh_known_hosts_file': None, '_pyinfra_ssh_strict_host_k
ey_checking': 'accept-new', '_pyinfra_ssh_paramiko_connect_kwargs': None, 'username': 'root', 'timeout': 10, 'password': 'pw'})
    [pyinfra.connectors.sshuserclient.client] Loading SSH config: None                                               
Unknown exception: q must be exactly 160, 224, or 256 bits long
Traceback (most recent call last):                                                                                                                                                                                                        
  File "/usr/lib/python3.13/site-packages/paramiko/transport.py", line 2262, in run                                  
    handler(m)                                            
    ~~~~~~~^^^                 
  File "/usr/lib/python3.13/site-packages/paramiko/auth_handler.py", line 404, in _parse_service_accept
    sig = self.private_key.sign_ssh_data(blob, algorithm)                                                            
  File "/usr/lib/python3.13/site-packages/paramiko/dsskey.py", line 120, in sign_ssh_data                            
    ).private_key(backend=default_backend())                                                                         
      ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                                                              
ValueError: q must be exactly 160, 224, or 256 bits long

Traceback (most recent call last):
  File "src/gevent/greenlet.py", line 900, in gevent._gevent_cgreenlet.Greenlet.run
  File "/usr/lib/python3.13/site-packages/pyinfra/api/host.py", line 380, in connect
    self.connector.connect()
    ~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/ssh.py", line 201, in connect
    return self._connect()
           ~~~~~~~~~~~~~^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/ssh.py", line 231, in _connect
    self.client.connect(hostname, **kwargs)
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/sshuserclient/client.py", line 182, in connect
    super().connect(hostname, **config)
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/client.py", line 485, in connect
    self._auth(
    ~~~~~~~~~~^
        username,
        ^^^^^^^^^
    ...<9 lines>...
        passphrase,
        ^^^^^^^^^^^
    )
    ^
  File "/usr/lib/python3.13/site-packages/paramiko/client.py", line 734, in _auth
    self._transport.auth_publickey(username, key)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/transport.py", line 1709, in auth_publickey
    return self.auth_handler.wait_for_response(my_event)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/auth_handler.py", line 248, in wait_for_response
 raise e
  File "/usr/lib/python3.13/site-packages/paramiko/transport.py", line 2262, in run
    handler(m)
    ~~~~~~~^^^
  File "/usr/lib/python3.13/site-packages/paramiko/auth_handler.py", line 404, in _parse_service_accept
    sig = self.private_key.sign_ssh_data(blob, algorithm)
  File "/usr/lib/python3.13/site-packages/paramiko/dsskey.py", line 120, in sign_ssh_data
    ).private_key(backend=default_backend())
      ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: q must be exactly 160, 224, or 256 bits long
2025-05-21T21:45:45Z <Greenlet at 0x75d121c77560: <bound method Host.connect of Host(olivar)>> failed with ValueError 


--> Disconnecting from hosts...
--> An internal exception occurred:

  File "/usr/lib/python3.13/site-packages/paramiko/dsskey.py", line 120, in sign_ssh_data
    ).private_key(backend=default_backend())
    ^^^^^^^^^^^^^^^
ValueError: q must be exactly 160, 224, or 256 bits long

    [pyinfra_cli.exceptions]   File "/usr/lib/python3.13/site-packages/pyinfra_cli/main.py", line 225, in cli
    _main(*args, **kwargs)
    ~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra_cli/main.py", line 351, in _main
    connect_all(state)
    ~~~~~~~~~~~^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/api/connect.py", line 37, in connect_all
    greenlet.get()
    ~~~~~~~~~~~~^^
  File "src/gevent/greenlet.py", line 797, in gevent._gevent_cgreenlet.Greenlet.get
  File "src/gevent/greenlet.py", line 373, in gevent._gevent_cgreenlet.Greenlet._raise_exception
  File "/usr/lib/python3.13/site-packages/gevent/_compat.py", line 50, in reraise
    raise value.with_traceback(tb)
  File "src/gevent/greenlet.py", line 900, in gevent._gevent_cgreenlet.Greenlet.run
  File "/usr/lib/python3.13/site-packages/pyinfra/api/host.py", line 380, in connect
    self.connector.connect()
    ^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/ssh.py", line 201, in connect
    return self._connect()
    ^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/ssh.py", line 231, in _connect
    self.client.connect(hostname, **kwargs)
    ^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/pyinfra/connectors/sshuserclient/client.py", line 182, in connect
    super().connect(hostname, **config)
    ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/client.py", line 485, in connect
    self._auth(
File "/usr/lib/python3.13/site-packages/paramiko/client.py", line 734, in _auth
    self._transport.auth_publickey(username, key)
    
  File "/usr/lib/python3.13/site-packages/paramiko/transport.py", line 1709, in auth_publickey
    return self.auth_handler.wait_for_response(my_event)
    ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/auth_handler.py", line 248, in wait_for_response
    raise e
  File "/usr/lib/python3.13/site-packages/paramiko/transport.py", line 2262, in run
    handler(m)
    
  File "/usr/lib/python3.13/site-packages/paramiko/auth_handler.py", line 404, in _parse_service_accept
    sig = self.private_key.sign_ssh_data(blob, algorithm)
    ^^^^^^^
  File "/usr/lib/python3.13/site-packages/paramiko/dsskey.py", line 120, in sign_ssh_data
    ).private_key(backend=default_backend())
    ^^^^^^^^^^^^^^^

    [pyinfra_cli.exceptions] ValueError: q must be exactly 160, 224, or 256 bits long

--> The full traceback has been written to pyinfra-debug.log
--> If this is unexpected please consider submitting a bug report on GitHub, for more information run `pyinfra --support`.

luroc avatar May 21 '25 21:05 luroc

That appears to be a paramiko bug with the handling of key files see: https://github.com/paramiko/paramiko/issues/1839

plattrap avatar Jun 04 '25 03:06 plattrap

is there any kind of workaround for this?

khimaros avatar Sep 19 '25 23:09 khimaros

ah, it looks like it is trying the first key and if that one fails it gives up. i was able to workaround the issue by reordering my keys in ~/.ssh/config

khimaros avatar Sep 19 '25 23:09 khimaros

There seem to be a few different circumstances and approaches to solve this that work for different people when you look at paramikos issue tracker: https://github.com/paramiko/paramiko/issues?q=q%20must%20be%20exactly

congrats on finding a solution so quickly though ;) I simply try to stay away from projects using paramiko for now.

luroc avatar Sep 20 '25 00:09 luroc