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
This commit is contained in:
Davanum Srinivas 2016-02-13 21:22:54 -05:00
parent 9d615b7eec
commit 1fd0f4f69b
2 changed files with 22 additions and 2 deletions

View File

@ -26,6 +26,7 @@ import base64
import binascii import binascii
import os import os
from Crypto.PublicKey import RSA
from cryptography import exceptions from cryptography import exceptions
from cryptography.hazmat import backends from cryptography.hazmat import backends
from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.asymmetric import padding
@ -161,8 +162,27 @@ def generate_x509_fingerprint(pem_key):
'Error message: %s') % ex) '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): def generate_key_pair(bits=2048):
key = paramiko.RSAKey.generate(bits) key = generate_key(bits)
keyout = six.StringIO() keyout = six.StringIO()
key.write_private_key(keyout) key.write_private_key(keyout)
private_key = keyout.getvalue() private_key = keyout.getvalue()

View File

@ -361,7 +361,7 @@ class KeyPairTest(test.NoDBTestCase):
keyin.seek(0) keyin.seek(0)
key = paramiko.RSAKey.from_private_key(keyin) 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 mock_generate.return_value = key
(private_key, public_key, fingerprint) = crypto.generate_key_pair() (private_key, public_key, fingerprint) = crypto.generate_key_pair()
self.assertEqual(self.rsa_pub, public_key) self.assertEqual(self.rsa_pub, public_key)