PYTHON AES 加密算法
是否需要在Python中使用密码或私钥加密某些文本? 您当然来对了地方。 AES-256是一种固态对称密码,通常用于为自己加密数据。 换句话说,正在加密数据的同一个人通常也将其解密(请考虑密码管理器 )。
依存关系
对于本教程,我们将使用Python 3,因此请确保安装pycryptodome ,这将使我们能够访问AES-256的实现:
pip3 install pycryptodomex
填充-由GCM处理
AES-256通常要求以16个字节的块提供要加密的数据,您可能已经在其他站点或教程中看到了。 但是,在GCM模式下,AES-256不需要任何特殊填充即可由我们手动完成。
正在加密
现在我们创建一个简单的crypto(plain_text,password)函数。 此功能使用密码来加密纯文本。 因此,任何有权访问加密文本和密码的人都可以对其解密。
# AES 256 encryption/decryption using pycryptodome library from base64 import b64encode, b64decode import hashlib from Cryptodome.Cipher import AES import os from Cryptodome.Random import get_random_bytes def encrypt (plain_text, password) : # generate a random salt salt = get_random_bytes(AES.block_size) # use the Scrypt KDF to get a private key from the password private_key = hashlib.scrypt( password.encode(), salt=salt, n= 2 ** 14 , r= 8 , p= 1 , dklen= 32 ) # create cipher config cipher_config = AES.new(private_key, AES.MODE_GCM) # return a dictionary with the encrypted text cipher_text, tag = cipher_config.encrypt_and_digest(bytes(plain_text, 'utf-8' )) return { 'cipher_text' : b64encode(cipher_text).decode( 'utf-8' ), 'salt' : b64encode(salt).decode( 'utf-8' ), 'nonce' : b64encode(cipher_config.nonce).decode( 'utf-8' ), 'tag' : b64encode(tag).decode( 'utf-8' ) } def decrypt (enc_dict, password) : # decode the dictionary entries from base64 salt = b64decode(enc_dict[ 'salt' ]) cipher_text = b64decode(enc_dict[ 'cipher_text' ]) nonce = b64decode(enc_dict[ 'nonce' ]) tag = b64decode(enc_dict[ 'tag' ]) # generate the private key from the password and salt private_key = hashlib.scrypt( password.encode(), salt=salt, n= 2 ** 14 , r= 8 , p= 1 , dklen= 32 ) # create the cipher config cipher = AES.new(private_key, AES.MODE_GCM, nonce=nonce) # decrypt the cipher text decrypted = cipher.decrypt_and_verify(cipher_text, tag) return decrypted def main () : password = input( "Password: " ) # First let us encrypt secret message encrypted = encrypt( "The secretest message here" , password) print(encrypted) # Let us decrypt using our original password decrypted = decrypt(encrypted, password) print(bytes.decode(decrypted)) main()
有关crypto()函数的注意事项
- 随机数 :一个随机数(任意值)必须是我们的加密功能使用相同的密钥每次随机和独特的价值。 可以将其视为密码的随机盐。 图书馆为我们提供了安全的随机数。
- Scrypt :Scrypt用于从密码生成安全私钥。 这将使攻击者更难于暴力破解我们的加密。
- 盐 :每次加密都会使用新的随机盐。 这使得攻击者无法使用预先计算的哈希来破解密码。 ( 见彩虹表 )
- 加密参数 :
- N是成本因素。 它必须是2的幂,并且它越高,密钥就越安全,但是需要更多的资源来运行。
- R是块大小。
- P是并行化因子,可用于在多个内核上运行。
- Base64 :我们将所有字节类型的数据编码为方便的字符串表示形式的base64
- 标签 :在GCM模式下使用AES时,标签用于验证数据。 这样可以确保在解密时没有人不知道我们就无法更改我们的数据。
crypto()函数需要使用与加密相同的盐,随机数和标记。 为了方便解析,我们使用了字典,但是如果我们想要一串密文,则可以使用诸如salt.nonce.tag.cipher_text之类的方案。Scrypt和AES函数上的配置参数必须与crypto函数相同。