From 1fd0f4f69b21cbd20c0eb0e2f8f4506061f4a211 Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Sat, 13 Feb 2016 21:22:54 -0500 Subject: [PATCH] Tolerate installation of pycryptodome Newer versions of pysaml2 uses pycryptodome, so if by accident if this library gets installed, Nova breaks. paramiko folks are working on this: https://github.com/paramiko/paramiko/issues/637 In the meanwhile, we should tolerate if either pycrypto or pycryptodome is installed. Closes-Bug: #1545370 Change-Id: If88beeb3983705621fe736995939ac20b2daf1f3 --- nova/crypto.py | 22 +++++++++++++++++++++- nova/tests/unit/test_crypto.py | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/nova/crypto.py b/nova/crypto.py index db7816233ebc..7e07fb4763d1 100644 --- a/nova/crypto.py +++ b/nova/crypto.py @@ -26,6 +26,7 @@ import base64 import binascii import os +from Crypto.PublicKey import RSA from cryptography import exceptions from cryptography.hazmat import backends from cryptography.hazmat.primitives.asymmetric import padding @@ -161,8 +162,27 @@ def generate_x509_fingerprint(pem_key): 'Error message: %s') % ex) +def generate_key(bits): + """Generate a paramiko RSAKey""" + # NOTE(dims): pycryptodome has changed the signature of the RSA.generate + # call. specifically progress_func has been dropped. paramiko still uses + # pycrypto. However some projects like latest pysaml2 have switched from + # pycrypto to pycryptodome as pycrypto seems to have been abandoned. + # paramiko project has started transition to pycryptodome as well but + # there is no release yet with that support. So at the moment depending on + # which version of pysaml2 is installed, Nova is likely to break. So we + # call "RSA.generate(bits)" which works on both pycrypto and pycryptodome + # and then wrap it into a paramiko.RSAKey + rsa = RSA.generate(bits) + key = paramiko.RSAKey(vals=(rsa.e, rsa.n)) + key.d = rsa.d + key.p = rsa.p + key.q = rsa.q + return key + + def generate_key_pair(bits=2048): - key = paramiko.RSAKey.generate(bits) + key = generate_key(bits) keyout = six.StringIO() key.write_private_key(keyout) private_key = keyout.getvalue() diff --git a/nova/tests/unit/test_crypto.py b/nova/tests/unit/test_crypto.py index 1a96dfa8907a..a32e9678f9be 100644 --- a/nova/tests/unit/test_crypto.py +++ b/nova/tests/unit/test_crypto.py @@ -361,7 +361,7 @@ class KeyPairTest(test.NoDBTestCase): keyin.seek(0) key = paramiko.RSAKey.from_private_key(keyin) - with mock.patch.object(paramiko.RSAKey, 'generate') as mock_generate: + with mock.patch.object(crypto, 'generate_key') as mock_generate: mock_generate.return_value = key (private_key, public_key, fingerprint) = crypto.generate_key_pair() self.assertEqual(self.rsa_pub, public_key)