Repository: ktbyers/netmiko

Issue:
cryptography 3.1 library breaks tplink drivers
I've just updated to netmiko 3.3.2 from 3.3.0, and paramiko 2.7.2 before and after the netmiko upgrade.  My custom ssh driver worked fine with netmiko 3.3.0. The stack trace is interesting for a couple reasons:

The actual error "AttributeError: module 'cryptography.utils' has no attribute 'bit_length'".  Looking back through the stack trace, there's a "raise e" from paramiko/transport.py line 660 in start_client().  The reported error is the actual exception raised at that point.

I don't get how the code goes from raising that exception and ends up in the new tplink driver.

I think I've installed all the latest module versions using pip to recreate the environment.

Debugging ideas are much appreciated!

```
Traceback (most recent call last):
(...deleted portion of stack trace...)
 File "/usr/local/lib/python3.6/site-packages/netmiko/ssh_dispatcher.py, line 324, in ConnectHandler
   return ConnectionClass(*args, **kwargs)
 File "/usr/local/lib/python3.6/site-packages/netmiko/<vendor>/<driverfile>, line 189, in __init__
   self.client.connect(self.host, port=22, username=self.username, password=self.password, look_for_keys=False, timeout=self.timeout)
 File "/usr/local/lib/python3.6/site-packages/paramiko/client.py, line 406, in connect
   t.start_client(timeout=timeout)
 File "/usr/local/lib/python3.6/site-packages/paramiko/transport.py, line 660, in start_client
   raise e
 File "/usr/local/lib/python3.6/site-packages/paramiko/transport.py, line 2075, in run
   self.kex_engine.parse_next(ptype, m)
 File "/usr/local/lib/python3.6/site-packages/paramiko/kex_group1.py line 75, in parse_next
   return self._parse_kexdh_reply(m)
 File "/usr/local/lib/python3.6/site-packages/paramiko/kex_group1.py line 120, in _parse_kexdh_reply
   self.transport._verify_key(host_key, sig)
 File "/usr/local/lib/python3.6/site-packages/paramiko/transport.py, line 1886, in _verify_key
   if not key.verify_ssh_sig(self.H, Message(sig)):
 File "/usr/local/lib/python3.6/site-packages/paramiko/dsskey.py, line 153, in verify_ssh_sig
   ).public_key(backend=default_backend())
 File "/usr/local/lib64/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py, line 212, in public_key
   return backend.load_dsa_public_numbers(self)
 File "/usr/local/lib64/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py, line 873, in load_dsa_public_numbers
   dsa._check_dsa_parameters(numbers.parameter_numbers)
 File "/usr/local/lib/python3.6/site-packages/netmiko/tplink/tplink_jetstream.py, line 145, in _override_check_dsa_parameters
   if crypto_utils.bit_length(parameters.q) not in [160, 256]:
AttributeError: module 'cryptography.utils' has no attribute 'bit_length'
```


Discussion:
cryptography 3.1 library broke this (released Sept 22). It exists in cryptography 3.0.

```
In [2]: from cryptography import utils as crypto_utils

In [3]: crypto_utils.bit_length
Out[3]: <function cryptography.utils.bit_length(x)>
```
You will need to `pip install cryptography==3.0.0` until we fix/work around this.

Resolving patch:
diff --git a/netmiko/tplink/tplink_jetstream.py b/netmiko/tplink/tplink_jetstream.py
--- a/netmiko/tplink/tplink_jetstream.py
+++ b/netmiko/tplink/tplink_jetstream.py
@@ -1,7 +1,6 @@
 import re
 import time
 
-from cryptography import utils as crypto_utils
 from cryptography.hazmat.primitives.asymmetric import dsa
 
 from netmiko import log
@@ -142,7 +141,7 @@ def _override_check_dsa_parameters(parameters):
 
         It's still not possible to remove this hack.
         """
-        if crypto_utils.bit_length(parameters.q) not in [160, 256]:
+        if parameters.q.bit_length() not in [160, 256]:
             raise ValueError("q must be exactly 160 or 256 bits long")
 
         if not (1 < parameters.g < parameters.p):


Test patch: