File fix-python3-crypto-call.patch of Package pgadmin4
From: Antonio Larrosa <alarrosa@suse.com>
Subject: Fix a python exception in crypto functions
Fix an exception being raised because C code in crypto functions can't be passed a <class 'str'> object
as key (see https://github.com/pybind/pybind11/issues/1335 for a similar error)
2018-10-03 16:44:20,411: ERROR flask.app: Object type <class 'str'> cannot be passed to C code
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/pgadmin4-web/pgadmin/utils/driver/psycopg2/connection.py", line 258, in connect
password = decrypt(encpass, user.password)
File "/usr/lib/python3.6/site-packages/pgadmin4-web/pgadmin/utils/crypto.py", line 66, in decrypt
cipher = AES.new(pad(key), AES.MODE_CFB, iv)
File "/usr/lib64/python3.6/site-packages/Crypto/Cipher/AES.py", line 206, in new
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
File "/usr/lib64/python3.6/site-packages/Crypto/Cipher/__init__.py", line 79, in _create_cipher
return modes[mode](factory, **kwargs)
File "/usr/lib64/python3.6/site-packages/Crypto/Cipher/_mode_cfb.py", line 230, in _create_cfb_cipher
cipher_state = factory._create_base_cipher(kwargs)
File "/usr/lib64/python3.6/site-packages/Crypto/Cipher/AES.py", line 102, in _create_base_cipher
result = start_operation(c_uint8_ptr(key),
File "/usr/lib64/python3.6/site-packages/Crypto/Util/_raw_api.py", line 109, in c_uint8_ptr
raise TypeError("Object type %s cannot be passed to C code" % type(data))
TypeError: Object type <class 'str'> cannot be passed to C code
Index: pgadmin4-3.3/web/pgadmin/utils/crypto.py
===================================================================
--- pgadmin4-3.3.orig/web/pgadmin/utils/crypto.py
+++ pgadmin4-3.3/web/pgadmin/utils/crypto.py
@@ -18,6 +18,12 @@ from Crypto.Cipher import AES
padding_string = b'}'
+def to_CStringCompatible(string):
+ if isinstance(string, str):
+ return string.encode('utf-8')
+ return string
+
+
def encrypt(plaintext, key):
"""
Encrypt the plaintext with AES method.
@@ -27,11 +33,14 @@ def encrypt(plaintext, key):
key -- Key for encryption.
"""
+ plaintext = to_CStringCompatible(plaintext)
+ key = to_CStringCompatible(key)
+
iv = Random.new().read(AES.block_size)
cipher = AES.new(pad(key), AES.MODE_CFB, iv)
# If user has entered non ascii password (Python2)
# we have to encode it first
- if hasattr(str, 'decode'):
+ if hasattr(plaintext, 'encode'):
plaintext = plaintext.encode('utf-8')
encrypted = base64.b64encode(iv + cipher.encrypt(plaintext))
@@ -49,6 +58,9 @@ def decrypt(ciphertext, key):
global padding_string
+ ciphertext = to_CStringCompatible(ciphertext)
+ key = to_CStringCompatible(key)
+
ciphertext = base64.b64decode(ciphertext)
iv = ciphertext[:AES.block_size]
cipher = AES.new(pad(key), AES.MODE_CFB, iv)
@@ -72,7 +84,7 @@ def pad(key):
return key
# Convert bytes to string (python3)
- if not hasattr(str, 'decode'):
+ if hasattr(padding_string, 'decode'):
padding_string = padding_string.decode()
# Add padding to make key 32 bytes long