Replace the PyCrypto module with the cryptography module. Fixes #3272

This commit is contained in:
Cyril Jouve 2019-01-31 15:57:27 +01:00 committed by Dave Page
parent cbfa614cf9
commit b786c4c140
4 changed files with 29 additions and 37 deletions

View File

@ -181,11 +181,6 @@ REM Main build sequence Ends
ECHO Creating virtual environment... ECHO Creating virtual environment...
IF NOT EXIST "%PGBUILDPATH%" MKDIR "%PGBUILDPATH%" IF NOT EXIST "%PGBUILDPATH%" MKDIR "%PGBUILDPATH%"
REM If we're using VC++, and this is Python 3.6+, we need a hack for PyCrypto
IF "%MAKE%" == "nmake" (
IF %PYTHON_VERSION% GEQ 36 SET CL=-FI"%VCINSTALLDIR%\INCLUDE\stdint.h"
)
CD "%PGBUILDPATH%" CD "%PGBUILDPATH%"
"%PYTHON_HOME%\Scripts\virtualenv.exe" "%VIRTUALENV%" "%PYTHON_HOME%\Scripts\virtualenv.exe" "%VIRTUALENV%"
@ -255,12 +250,6 @@ REM Main build sequence Ends
ECHO Removing Sphinx ECHO Removing Sphinx
CALL pip uninstall -y sphinx Pygments alabaster colorama docutils imagesize requests snowballstemmer CALL pip uninstall -y sphinx Pygments alabaster colorama docutils imagesize requests snowballstemmer
IF %PYTHON_MAJOR% == 3 (
ECHO Fixing PyCrypto module for Python 3...
CALL "%PYTHON_HOME%\python" "%WD%\pkg\win32\replace.py" "-i" "%PGBUILDPATH%\%VIRTUALENV%\Lib\site-packages\Crypto\Random\OSRNG\nt.py" "-o" "%PGBUILDPATH%\%VIRTUALENV%\Lib\site-packages\Crypto\Random\OSRNG\nt.py.new" "-s" "import winrandom" -r "from . import winrandom"
MOVE /Y "%PGBUILDPATH%\%VIRTUALENV%\Lib\site-packages\Crypto\Random\OSRNG\nt.py.new" "%PGBUILDPATH%\%VIRTUALENV%\Lib\site-packages\Crypto\Random\OSRNG\nt.py"
)
ECHO Assembling runtime environment... ECHO Assembling runtime environment...
CD "%WD%\runtime" CD "%WD%\runtime"

View File

@ -14,6 +14,7 @@ Features
Bug fixes Bug fixes
********* *********
| `Bug #3272 <https://redmine.postgresql.org/issues/3272>`_ - Replace the PyCrypto module with the cryptography module.
| `Bug #3453 <https://redmine.postgresql.org/issues/3453>`_ - Fixed SQL for foreign table options. | `Bug #3453 <https://redmine.postgresql.org/issues/3453>`_ - Fixed SQL for foreign table options.
| `Bug #3475 <https://redmine.postgresql.org/issues/3475>`_ - Fixed execution time to show Hours part for long running queries in Query Tool. | `Bug #3475 <https://redmine.postgresql.org/issues/3475>`_ - Fixed execution time to show Hours part for long running queries in Query Tool.
| `Bug #3608 <https://redmine.postgresql.org/issues/3608>`_ - Messages tab of query tool should be clear on subsequent execution of table/view using View/Edit Data. | `Bug #3608 <https://redmine.postgresql.org/issues/3608>`_ - Messages tab of query tool should be clear on subsequent execution of table/view using View/Edit Data.

View File

@ -18,7 +18,6 @@ html5lib==1.0.1
linecache2==1.0.0 linecache2==1.0.0
passlib==1.7.1 passlib==1.7.1
pbr==3.1.1 pbr==3.1.1
pycrypto>=2.6.1
pyrsistent==0.14.2 pyrsistent==0.14.2
python-mimeparse==1.6.0 python-mimeparse==1.6.0
pytz==2018.3 pytz==2018.3

View File

@ -9,13 +9,21 @@
"""This File Provides Cryptography.""" """This File Provides Cryptography."""
from __future__ import division
import base64 import base64
import hashlib import hashlib
import os
from Crypto import Random import six
from Crypto.Cipher import AES
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import CFB8
padding_string = b'}' padding_string = b'}'
iv_size = AES.block_size // 8
def encrypt(plaintext, key): def encrypt(plaintext, key):
@ -27,15 +35,17 @@ def encrypt(plaintext, key):
key -- Key for encryption. key -- Key for encryption.
""" """
iv = Random.new().read(AES.block_size) iv = os.urandom(iv_size)
cipher = AES.new(pad(key), AES.MODE_CFB, iv) cipher = Cipher(AES(pad(key)), CFB8(iv), default_backend())
encryptor = cipher.encryptor()
# If user has entered non ascii password (Python2) # If user has entered non ascii password (Python2)
# we have to encode it first # we have to encode it first
if hasattr(str, 'decode'): if isinstance(plaintext, six.text_type):
plaintext = plaintext.encode('utf-8') plaintext = plaintext.encode()
encrypted = base64.b64encode(iv + cipher.encrypt(plaintext))
return encrypted return base64.b64encode(iv + encryptor.update(plaintext) +
encryptor.finalize())
def decrypt(ciphertext, key): def decrypt(ciphertext, key):
@ -47,36 +57,29 @@ def decrypt(ciphertext, key):
key -- key to decrypt the encrypted string. key -- key to decrypt the encrypted string.
""" """
global padding_string
ciphertext = base64.b64decode(ciphertext) ciphertext = base64.b64decode(ciphertext)
iv = ciphertext[:AES.block_size] iv = ciphertext[:iv_size]
cipher = AES.new(pad(key), AES.MODE_CFB, iv)
decrypted = cipher.decrypt(ciphertext[AES.block_size:])
return decrypted cipher = Cipher(AES(pad(key)), CFB8(iv), default_backend())
decryptor = cipher.decryptor()
return decryptor.update(ciphertext[iv_size:]) + decryptor.finalize()
def pad(key): def pad(key):
"""Add padding to the key.""" """Add padding to the key."""
global padding_string if isinstance(key, six.text_type):
str_len = len(key) key = key.encode()
# Key must be maximum 32 bytes long, so take first 32 bytes # Key must be maximum 32 bytes long, so take first 32 bytes
if str_len > 32: key = key[:32]
return key[:32]
# If key size id 16, 24 or 32 bytes then padding not require # If key size is 16, 24 or 32 bytes then padding is not required
if str_len == 16 or str_len == 24 or str_len == 32: if len(key) in (16, 24, 32):
return key return key
# Convert bytes to string (python3)
if not hasattr(str, 'decode'):
padding_string = padding_string.decode()
# Add padding to make key 32 bytes long # Add padding to make key 32 bytes long
return key + ((32 - str_len % 32) * padding_string) return key.ljust(32, padding_string)
def pqencryptpassword(password, user): def pqencryptpassword(password, user):