components/python/keystoneclient/patches/nopycrypto.patch
branchs11-update
changeset 4072 db0cec748ec0
child 5405 66fd59fecd68
equal deleted inserted replaced
4067:4be1f488dda8 4072:db0cec748ec0
       
     1 In-house removal of PyCrypto dependency in keystoneclient. This patch
       
     2 is Solaris-specific and not suitable for upstream.
       
     3 
       
     4 --- python-keystoneclient-1.0.0/keystoneclient/middleware/memcache_crypt.py.~1~	2014-12-18 09:37:35.000000000 -0800
       
     5 +++ python-keystoneclient-1.0.0/keystoneclient/middleware/memcache_crypt.py	2015-01-31 23:38:16.649757111 -0800
       
     6 @@ -17,7 +17,7 @@
       
     7  Utilities for memcache encryption and integrity check.
       
     8  
       
     9  Data should be serialized before entering these functions. Encryption
       
    10 -has a dependency on the pycrypto. If pycrypto is not available,
       
    11 +has a dependency on M2Crypto. If M2Crypto is not available,
       
    12  CryptoUnavailableError will be raised.
       
    13  
       
    14  This module will not be called unless signing or encryption is enabled
       
    15 @@ -37,9 +37,10 @@ import sys
       
    16  
       
    17  import six
       
    18  
       
    19 -# make sure pycrypto is available
       
    20 +# make sure M2Crypto is available
       
    21  try:
       
    22 -    from Crypto.Cipher import AES
       
    23 +    from M2Crypto.EVP import Cipher
       
    24 +    AES = Cipher
       
    25  except ImportError:
       
    26      AES = None
       
    27  
       
    28 @@ -72,6 +73,13 @@ class CryptoUnavailableError(Exception):
       
    29      pass
       
    30  
       
    31  
       
    32 +class InvalidKeyLength(Exception):
       
    33 +    """raise when AES key length is an invalid value.
       
    34 +
       
    35 +    """
       
    36 +    pass
       
    37 +
       
    38 +
       
    39  def assert_crypto_availability(f):
       
    40      """Ensure Crypto module is available."""
       
    41  
       
    42 @@ -131,31 +139,44 @@ def sign_data(key, data):
       
    43      return base64.b64encode(mac)
       
    44  
       
    45  
       
    46 +def _key_to_alg(key):
       
    47 +    """Return a M2Crypto-compatible AES-CBC algorithm name given a key."""
       
    48 +    aes_algs = {
       
    49 +        128: 'aes_128_cbc',
       
    50 +        192: 'aes_192_cbc',
       
    51 +        256: 'aes_256_cbc'
       
    52 +    }
       
    53 +
       
    54 +    keylen = 8 * len(key)
       
    55 +    if keylen not in aes_algs:
       
    56 +        msg = ('Invalid AES key length, %d bits') % keylen
       
    57 +        raise InvalidKeyLength(msg)
       
    58 +    return aes_algs[keylen]
       
    59 +
       
    60 +
       
    61  @assert_crypto_availability
       
    62  def encrypt_data(key, data):
       
    63      """Encrypt the data with the given secret key.
       
    64  
       
    65 -    Padding is n bytes of the value n, where 1 <= n <= blocksize.
       
    66      """
       
    67      iv = os.urandom(16)
       
    68 -    cipher = AES.new(key, AES.MODE_CBC, iv)
       
    69 -    padding = 16 - len(data) % 16
       
    70 -    return iv + cipher.encrypt(data + six.int2byte(padding) * padding)
       
    71 +    cipher = Cipher(alg=_key_to_alg(key), key=key, iv=iv, op=1)
       
    72 +    result = cipher.update(data)
       
    73 +    return iv + result + cipher.final()
       
    74  
       
    75  
       
    76  @assert_crypto_availability
       
    77  def decrypt_data(key, data):
       
    78      """Decrypt the data with the given secret key."""
       
    79      iv = data[:16]
       
    80 -    cipher = AES.new(key, AES.MODE_CBC, iv)
       
    81 +    cipher = Cipher(alg=_key_to_alg(key), key=key, iv=iv, op=0)
       
    82      try:
       
    83 -        result = cipher.decrypt(data[16:])
       
    84 +        result = cipher.update(data[16:])
       
    85 +        result = result + cipher.final()
       
    86      except Exception:
       
    87          raise DecryptError('Encrypted data appears to be corrupted.')
       
    88  
       
    89 -    # Strip the last n padding bytes where n is the last value in
       
    90 -    # the plaintext
       
    91 -    return result[:-1 * six.byte2int([result[-1]])]
       
    92 +    return result
       
    93  
       
    94  
       
    95  def protect_data(keys, data):