pgadmin4/web/pgadmin/utils/crypto.py

79 lines
2.1 KiB
Python

##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2026, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
#########################################################################
"""This File Provides Cryptography."""
import base64
import hashlib
import os
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'}'
iv_size = AES.block_size // 8
def encrypt(plaintext, key):
"""
Encrypt the plaintext with AES method.
Parameters:
plaintext -- String to be encrypted.
key -- Key for encryption.
"""
iv = os.urandom(iv_size)
cipher = Cipher(AES(pad(key)), CFB8(iv), default_backend())
encryptor = cipher.encryptor()
# If user has entered non ascii password (Python2)
# we have to encode it first
if isinstance(plaintext, str):
plaintext = plaintext.encode()
return base64.b64encode(iv + encryptor.update(plaintext) +
encryptor.finalize())
def decrypt(ciphertext, key):
"""
Decrypt the AES encrypted string.
Parameters:
ciphertext -- Encrypted string with AES method.
key -- key to decrypt the encrypted string.
"""
ciphertext = base64.b64decode(ciphertext)
iv = ciphertext[:iv_size]
cipher = Cipher(AES(pad(key)), CFB8(iv), default_backend())
decryptor = cipher.decryptor()
return decryptor.update(ciphertext[iv_size:]) + decryptor.finalize()
def pad(key):
"""Add padding to the key."""
if isinstance(key, str):
key = key.encode()
# Key must be maximum 32 bytes long, so take first 32 bytes
key = key[:32]
# If key size is 16, 24 or 32 bytes then padding is not required
if len(key) in (16, 24, 32):
return key
# Add padding to make key 32 bytes long
return key.ljust(32, padding_string)