是否需要在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函數相同。