我正在用 python 制作一个密码管理器,它使用用户设置的主密码来存储和加密密码(使用 pycriptodome 模块),但解密不起作用 这是我用来解密密码的函数
def decrypt_data(key, iv, ct): # Makes the credentials readable and usable
print(f'{bcolors.warning}\nDebug decrypt_data(1):\tiv:\t\t\t{iv}') # debug text
print(f'Debug decrypt_data(2):\tiv variable type:\t{type(iv)}') # debug text
print(f'Debug decrypt_data(3):\tiv_bytes:\t\t{bytes(iv, 'utf-8')}') # debug text
print(f'Debug decrypt_data(4):\tiv_bytes type:\t\t{type(bytes(iv, 'utf-8'))}\n{bcolors.endc}') # debug text
cipher = AES.new(key, AES.MODE_CBC)
pt = unpad(cipher.decrypt(bytes(ct, 'utf-8')), AES.block_size)
print(f'{bcolors.okcyan}Decripting done{bcolors.endc}')
return decrypted.decode("UTF-8")
控制台输出:
Debug decrypt_data(1): iv: +00X7cdUZm7L61ifRb9EDQ==
Debug decrypt_data(2): iv variable type: <class 'str'>
Debug decrypt_data(3): iv_bytes: b'+00X7cdUZm7L61ifRb9EDQ=='
Debug decrypt_data(4): iv_bytes type: <class 'bytes'>
Traceback (most recent call last):
File "D:\py_proj\Password Manager\.venv\Lib\pw_manager.py", line 151, in <module>
print(f'{bcolors.warning}Debug main(5):\t\tdecrypted main_pw:\t{decrypt_data(padded_key, encrypt_data(padded_key, main_pw)[1], encrypt_data(padded_key, main_pw)[0])}') # debug text
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\py_proj\Password Manager\.venv\Lib\pw_manager.py", line 107, in decrypt_data
pt = unpad(cipher.decrypt(bytes(ct, 'utf-8')), AES.block_size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Utente\AppData\Local\Programs\Python\Python312\Lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 246, in decrypt
raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
ValueError: Data must be padded to 16 byte boundary in CBC mode
仅供参考,这里是加密代码和部分主要功能
def encrypt_data(key, pt): # protects the credentials in the file once saved
print(f'\nDebug encrypt_data(1):\tplaintext:\t\t{pt}') # debug text
print(f'Debug encrypt_data(2):\tbytetext:\t\t{bytes(pt, 'utf-8')}') # debug text
print(f'Debug encrypt_data(3):\tpadded plaintext:\t{pad(bytes(pt, 'utf-8'), AES.block_size)}') # debug text
cipher = AES.new(key, AES.MODE_CBC)
ct_bytes = cipher.encrypt(pad(bytes(pt, 'utf-8'), AES.block_size))
print(f'Debug encrypt_data(4):\tct_bytes:\t\t{ct_bytes}') # debug text
iv = b64encode(cipher.iv).decode('utf-8')
ct = b64encode(ct_bytes).decode('utf-8')
print(f'Debug encrypt_data(5):\tb64 decoded ct:\t\t{ct}') # debug text
print(f'Debug encrypt_data(6):\tiv:\t\t\t{iv}') # debug text
print(f'Debug encrypt_data(7):\tciphertext:\t\t{ct}\n') # debug text
print(f'Encripting done')
return ct, iv
if __name__ == '__main__':
# login screen
if not os.path.exists(credentials_file):
signin()
main_pw = login()
padded_key = pad(bytes(main_pw, 'utf-8'), AES.block_size) # Pad the key to the correct length
print(f'Debug main(1):\t\tmain_pw:\t\t{main_pw}') # debug text
print(f'Debug main(2):\t\tbyte_pw:\t\t{bytes(main_pw, 'utf-8')}') # debug text
print(f'Debug main(3):\t\tpadded_key:\t\t{padded_key}') # debug text
print(f'Debug main(4):\t\tencrypted main_pw:\t{encrypt_data(padded_key, main_pw)[0]}') # debug text
print(f'Debug main(5):\t\tdecrypted main_pw:\t{decrypt_data(padded_key, encrypt_data(padded_key, main_pw)[1], encrypt_data(padded_key, main_pw)[0])}') # debug text
print(f'Debug main(6):\t\tunpadded decrypted main_pw:\t{decrypt_data(padded_key, encrypt_data(padded_key, main_pw)[1], encrypt_data(padded_key, main_pw)[0])}\n') # debug text
这是控制台的完整输出:
Debug main(1): main_pw: test
Debug main(2): byte_pw: b'test'
Debug main(3): padded_key: b'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
Debug encrypt_data(1): plaintext: test
Debug encrypt_data(2): bytetext: b'test'
Debug encrypt_data(3): padded plaintext: b'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
Debug encrypt_data(4): ct_bytes: b'I\xdd\x95\x9fXl"\xa1\xd9Xfd~\xc5\xc2\xcd'
Debug encrypt_data(5): b64 decoded ct: Sd2Vn1hsIqHZWGZkfsXCzQ==
Debug encrypt_data(6): iv: lmuFGlygOos07SPYpBWNBw==
Debug encrypt_data(7): ciphertext: Sd2Vn1hsIqHZWGZkfsXCzQ==
Encripting done
Debug main(4): encrypted main_pw: Sd2Vn1hsIqHZWGZkfsXCzQ==
Debug encrypt_data(1): plaintext: test
Debug encrypt_data(2): bytetext: b'test'
Debug encrypt_data(3): padded plaintext: b'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
Debug encrypt_data(4): ct_bytes: b'\t\r\xfbd\x07\x1d\xcay>\xa49\xdeK\xd9W\xbb'
Debug encrypt_data(5): b64 decoded ct: CQ37ZAcdynk+pDneS9lXuw==
Debug encrypt_data(6): iv: +00X7cdUZm7L61ifRb9EDQ==
Debug encrypt_data(7): ciphertext: CQ37ZAcdynk+pDneS9lXuw==
Encripting done
Debug encrypt_data(1): plaintext: test
Debug encrypt_data(2): bytetext: b'test'
Debug encrypt_data(3): padded plaintext: b'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
Debug encrypt_data(4): ct_bytes: b'=\xf6\xa4\xcetfD\xe4\x12\xef\xff\xce\x0f(]t'
Debug encrypt_data(5): b64 decoded ct: PfakznRmROQS7//ODyhddA==
Debug encrypt_data(6): iv: w/FfW0RCcLqv8FjqRtCpxg==
Debug encrypt_data(7): ciphertext: PfakznRmROQS7//ODyhddA==
Encripting done
Debug decrypt_data(1): iv: +00X7cdUZm7L61ifRb9EDQ==
Debug decrypt_data(2): iv variable type: <class 'str'>
Debug decrypt_data(3): iv_bytes: b'+00X7cdUZm7L61ifRb9EDQ=='
Debug decrypt_data(4): iv_bytes type: <class 'bytes'>
Traceback (most recent call last):
File "D:\py_proj\Password Manager\.venv\Lib\pw_manager.py", line 151, in <module>
print(f'Debug main(5):\t\tdecrypted main_pw:\t{decrypt_data(padded_key, encrypt_data(padded_key, main_pw)[1], encrypt_data(padded_key, main_pw)[0])}') # debug text
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\py_proj\Password Manager\.venv\Lib\pw_manager.py", line 107, in decrypt_data
pt = unpad(cipher.decrypt(bytes(ct, 'utf-8')), AES.block_size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Utente\AppData\Local\Programs\Python\Python312\Lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 246, in decrypt
raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
ValueError: Data must be padded to 16 byte boundary in CBC mode
[processo terminato con codice 1 (0x00000001)]
我在解密之前尝试使用
pt = unpad(cipher.decrypt(pad(bytes(ct, 'utf-8'), AES.block_size)), AES.block_size)
而不是 pt = unpad(cipher.decrypt(pad(bytes(ct, 'utf-8'), AES.block_size)), AES.block_size)
进行填充,但它给出了此错误:
Traceback (most recent call last):
File "D:\py_proj\Password Manager\.venv\Lib\pw_manager.py", line 151, in <module>
print(f'Debug main(5):\t\tdecrypted main_pw:\t{decrypt_data(padded_key, encrypt_data(padded_key, main_pw)[1], encrypt_data(padded_key, main_pw)[0])}') # debug text
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\py_proj\Password Manager\.venv\Lib\pw_manager.py", line 107, in decrypt_data
pt = unpad(cipher.decrypt(pad(bytes(ct, 'utf-8'), AES.block_size)), AES.block_size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Utente\AppData\Local\Programs\Python\Python312\Lib\site-packages\Crypto\Util\Padding.py", line 92, in unpad
raise ValueError("Padding is incorrect.")
ValueError: Padding is incorrect.
[processo terminato con codice 1 (0x00000001)]
这是代码的简化版和功能版本,为简单起见,它接受 base64 编码的纯文本字符串作为密钥和 IV 材料(这些很容易存储在文本文件等中)。
请注意,CBC 模式可能不是您想要的,因为它不提供任何身份验证(即您将取回最初加密的文本)。
import base64
import secrets
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad, pad
def encrypt_data(key_str: str, plaintext: str) -> tuple[str, str]:
key_bytes = base64.b64decode(key_str.encode("utf-8"))
cipher = AES.new(key_bytes, AES.MODE_CBC)
ct_bytes = cipher.encrypt(pad(plaintext.encode("utf-8"), AES.block_size))
iv = base64.b64encode(cipher.iv).decode("utf-8")
ciphertext = base64.b64encode(ct_bytes).decode("utf-8")
return ciphertext, iv
def decrypt_data(key_str: str, iv_str: str, ciphertext_str: str) -> str:
key_bytes = base64.b64decode(key_str.encode("utf-8"))
iv_bytes = base64.b64decode(iv_str.encode("utf-8"))
ciphertext_bytes = base64.b64decode(ciphertext_str.encode("utf-8"))
cipher = AES.new(key_bytes, AES.MODE_CBC, iv=iv_bytes)
plaintext_bytes = unpad(cipher.decrypt(ciphertext_bytes), AES.block_size)
return plaintext_bytes.decode("UTF-8")
key_bytes = secrets.token_bytes(32)
key_str = base64.b64encode(key_bytes).decode("utf-8")
plaintext = "Hello, World!"
print(f"{key_str=}, {plaintext=}")
ciphertext, iv = encrypt_data(key_str, plaintext)
print(f"{ciphertext=}, {iv=}")
decrypted = decrypt_data(key_str, iv, ciphertext)
print(f"{decrypted=}")
打印出来(例如)
key_str='Zdu1DUQC/dZhGC8Q1n0raD8BlW7pfzLZxwmPqn0o6s8=', plaintext='Hello, World!'
ciphertext='Es7w8eWcRHGhfpwBDnr6vQ==', iv='Grf/VFkH8Qp7VS6RVj2e2g=='
decrypted='Hello, World!'