Encryption algorithms should use secure modes and padding schemes where appropriate to guarantee data confidentiality and integrity.
- For block cipher encryption algorithms (like AES):
- The ECB (Electronic Codebook) cipher mode doesn’t provide serious message confidentiality: under a given key any given plaintext block
always gets encrypted to the same ciphertext block. This mode should never be used.
- The CBC (Cipher Block Chaining) mode by itself provides only data confidentiality. This cipher mode is also vulnerable to padding oracle attacks when used with padding. Using CBC along with Message
Authentication Code can provide data integrity and should prevent such attacks. In practice the implementation has many pitfalls and it’s
recommended to avoid CBC with padding completely.
- The GCM (Galois Counter Mode) mode which works
internally with zero/no padding scheme, is recommended, as it is designed to provide both data authenticity (integrity) and confidentiality.
Other similar modes are CCM, CWC, EAX, IAPM and OCB.
- For RSA encryption algorithm, the recommended padding scheme is OAEP.
Noncompliant Code Example
pycryptodomex library:
from Cryptodome.Cipher import AES, PKCS1_OAEP, PKCS1_v1_5
from Cryptodome.Random import get_random_bytes
from Cryptodome.PublicKey import RSA
# Example for a symmetric cipher: AES
AES.new(key, AES.MODE_ECB) # Noncompliant
AES.new(key, AES.MODE_CBC) # Noncompliant
# Example for a asymmetric cipher: RSA
cipher = PKCS1_v1_5.new(key) # Noncompliant
pyca library:
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# Example for a symmetric cipher: AES
aes = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) # Noncompliant
aes = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend()) # Noncompliant
# Example for a asymmetric cipher: RSA
ciphertext = public_key.encrypt(
message,
padding.PKCS1v15() # Noncompliant
)
plaintext = private_key.decrypt(
ciphertext,
padding.PKCS1v15() # Noncompliant
)
pydes library:
# For DES cipher
des = pyDes.des('ChangeIt') # Noncompliant
des = pyDes.des('ChangeIt', pyDes.CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) # Noncompliant
des = pyDes.des('ChangeIt', pyDes.ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) # Noncompliant
pycrypto library is not maintained and therefore should not be used:
# https://pycrypto.readthedocs.io/en/latest/
from Crypto.Cipher import *
from Crypto.Random import get_random_bytes
from Crypto.Util import Counter
from Crypto.PublicKey import RSA
# Example for a symmetric cipher: AES
AES.new(key, AES.MODE_ECB) # Noncompliant
AES.new(key, AES.MODE_CBC, IV=iv) # Noncompliant
# Example for a asymmetric cipher: RSA
cipher = PKCS1_v1_5.new(key) # Noncompliant
Compliant Solution
pycryptodomex library:
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
from Cryptodome.PublicKey import RSA
# AES is the recommended symmetric cipher with GCM mode
AES.new(key, AES.MODE_GCM) # Compliant
# RSA is the recommended asymmetric cipher with OAEP padding
cipher = PKCS1_OAEP.new(key) # Compliant
pyca library:
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# AES is the recommended symmetric cipher with GCM mode
aes = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend()) # Compliant
# RSA is the recommended asymmetric cipher with OAEP padding
ciphertext = public_key.encrypt(
message,
padding.OAEP( # Compliant
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP( # Compliant
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
See