2521N/AIn-house removal of PyCrypto dependency in Glance. This patch is
2521N/ASolaris-specific and not suitable for upstream.
2521N/A
2521N/AConvert urlsafe_encrypt() and urlsafe_decrypt() to use M2Crypto instead
2521N/Aof PyCrypto.
2521N/A
6850N/A--- glance-12.0.0.0rc1/glance/common/crypt.py.~1~ 2016-03-16 06:18:49.000000000 -0700
6850N/A+++ glance-12.0.0.0rc1/glance/common/crypt.py 2016-03-30 02:26:55.580507508 -0700
6850N/A@@ -18,14 +18,28 @@ Routines for URL-safe encrypting/decrypt
2521N/A """
2521N/A
2521N/A import base64
2521N/A+import os
2521N/A
2521N/A-from Crypto.Cipher import AES
2521N/A-from Crypto import Random
2521N/A-from Crypto.Random import random
6850N/A from oslo_utils import encodeutils
6850N/A import six
6850N/A-# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
6850N/A-from six.moves import range
5403N/A+
5403N/A+from M2Crypto.EVP import Cipher
6850N/A+
6850N/A+from glance.common import exception
6850N/A+
2521N/A+def _key_to_alg(key):
2521N/A+ """Return a M2Crypto-compatible AES-CBC algorithm name given a key."""
2521N/A+ aes_algs = {
2521N/A+ 128: 'aes_128_cbc',
2521N/A+ 192: 'aes_192_cbc',
2521N/A+ 256: 'aes_256_cbc'
2521N/A+ }
2521N/A+
2521N/A+ keylen = 8 * len(key)
2521N/A+ if keylen not in aes_algs:
2521N/A+ msg = ('Invalid AES key length, %d bits') % keylen
2521N/A+ raise exception.Invalid(msg)
2521N/A+ return aes_algs[keylen]
6850N/A
6850N/A
2521N/A def urlsafe_encrypt(key, plaintext, blocksize=16):
6850N/A@@ -39,23 +53,14 @@ def urlsafe_encrypt(key, plaintext, bloc
2521N/A
6850N/A :returns: Resulting ciphertext
2521N/A """
2521N/A- def pad(text):
2521N/A- """
2521N/A- Pads text to be encrypted
2521N/A- """
2521N/A- pad_length = (blocksize - len(text) % blocksize)
2521N/A- sr = random.StrongRandom()
6850N/A- pad = b''.join(six.int2byte(sr.randint(1, 0xFF))
6850N/A- for i in range(pad_length - 1))
2521N/A- # We use chr(0) as a delimiter between text and padding
6850N/A- return text + b'\0' + pad
2521N/A
6850N/A plaintext = encodeutils.to_utf8(plaintext)
6850N/A key = encodeutils.to_utf8(key)
2521N/A # random initial 16 bytes for CBC
2521N/A- init_vector = Random.get_random_bytes(16)
2521N/A- cypher = AES.new(key, AES.MODE_CBC, init_vector)
6850N/A- padded = cypher.encrypt(pad(six.binary_type(plaintext)))
2521N/A+ init_vector = os.urandom(16)
2521N/A+ cipher = Cipher(alg=_key_to_alg(key), key=key, iv=init_vector, op=1)
2521N/A+ padded = cipher.update(str(plaintext))
2521N/A+ padded = padded + cipher.final()
6850N/A encoded = base64.urlsafe_b64encode(init_vector + padded)
6850N/A if six.PY3:
6850N/A encoded = encoded.decode('ascii')
6850N/A@@ -76,9 +81,9 @@ def urlsafe_decrypt(key, ciphertext):
6850N/A ciphertext = encodeutils.to_utf8(ciphertext)
6850N/A key = encodeutils.to_utf8(key)
6850N/A ciphertext = base64.urlsafe_b64decode(ciphertext)
2521N/A- cypher = AES.new(key, AES.MODE_CBC, ciphertext[:16])
2521N/A- padded = cypher.decrypt(ciphertext[16:])
6850N/A- text = padded[:padded.rfind(b'\0')]
2521N/A+ cipher = Cipher(alg=_key_to_alg(key), key=key, iv=ciphertext[:16], op=0)
2521N/A+ padded = cipher.update(ciphertext[16:])
6850N/A+ text = padded + cipher.final()
6850N/A if six.PY3:
6850N/A text = text.decode('utf-8')
6850N/A return text