There is a padding issue with my code, at first time when password.txt (the file in which I save the decrypted passwords) but the issue is when I run the code for the second time I get this error:
`66lHmLVe~
The password is strong
Encrypted password: b'\xe1\x19\x04\x88</\xf4,\xd9\x10\xe9\xef\x8f4\x00\t'
Decrypted password: `66lHmLVe~
Traceback (most recent call last):
File "c:\Users\basse\Project_3.py", line 78, in <module>
decrypted_password = decrypt_data(bytes.fromhex(iv), bytes.fromhex(encrypted_password), key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\basse\Project_3.py", line 55, in decrypt_data
decrypted_data = unpad(cipher.decrypt(encrypted_data), block_size)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\basse\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\Crypto\Util\Padding.py", line 92, in unpad
raise ValueError("Padding is incorrect.")
ValueError: Padding is incorrect.
here is the full code:
import re
import random
import string
def password_generator(size=10):
if size <= 8:
print("Size must be at least 4")
return None
password = []
while len(password) < size:
password.append(random.choice(string.ascii_lowercase)) # ensure at least one lowercase letter
if len(password) < size:
password.append(random.choice(string.ascii_uppercase)) # ensure at least one uppercase letter
if len(password) < size:
password.append(random.choice(string.digits)) # ensure at least one digit
if len(password) < size:
password.append(random.choice(string.punctuation)) # ensure at least one special character
random.shuffle(password) # shuffle to remove the predictability
return ''.join(password)
def password_checker(password):
if len(password) >= 8:
if bool(re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z\d])', password)):
print("The password is strong")
else:
print("The password is weak")
else:
print("You have entered a short or invalid password.")
# Generate a password
generated_password = password_generator()
print(generated_password)
# Check the generated password
password_checker(generated_password)
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import os
# AES requires that plaintexts be a multiple of 16, so we need to pad the data
block_size = 16
# Generate a random 128-bit IV for AES
iv = get_random_bytes(16)
def encrypt_data(iv,data, key):
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
encrypted_data = cipher.encrypt(pad(data.encode('utf-8'), block_size))
return cipher.iv, encrypted_data
def decrypt_data(iv, encrypted_data, key):
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
decrypted_data = unpad(cipher.decrypt(encrypted_data), block_size)
return decrypted_data.decode('utf-8')
# Generate a random 256-bit key for AES
key = get_random_bytes(32)
# Encrypt the generated password
iv, encrypted_password = encrypt_data(iv,generated_password, key)
print(f"Encrypted password: {encrypted_password}")
# Decrypt the encrypted password
decrypted_password = decrypt_data(iv, encrypted_password, key)
print(f"Decrypted password: {decrypted_password}")
# Save the encrypted password to a file
with open('C:/Users/foo/Project/Password.txt', 'a', encoding='utf-8') as f:
f.write(f"{iv.hex()}:{encrypted_password.hex()}\n")
# Read the encrypted password from the file
with open('C:/Users/foo/Project/Password.txt', 'r', encoding='utf-8') as f:
for line in f.readlines():
line = line.strip() # Remove the trailing newline character
iv, encrypted_password = line.split(':')
decrypted_password = decrypt_data(bytes.fromhex(iv), bytes.fromhex(encrypted_password), key)
I want to for the Passwords to be saved in Password.txt in encrypted form so when I call it, it decrypts the password and show in its original form for the Password Manager. so, if there any way I can save the passwords rather than text file it is okay, but I would love to use text file.
It may be better to not use the the padding package from cryptography instead use the code from this answer instead as I have ripped most of this from their answer.
The text file wont affect anything the .txt file extension just says what application should be opening it and can still be used to write bytes into but I generally don't use a file extension for encrypted data as it's quicker to write but as shown in the documentation .bin is usually used. I more often use RSA encryption so I recommend you read through the pycrypto docs.
(make sure you have hashlib installed since I added it)
import re
import random
import string
def password_generator(size=10):
if size <= 8:
print("Size must be at least 4")
return None
password = []
while len(password) < size:
password.append(random.choice(string.ascii_lowercase)) # ensure at least one lowercase letter
if len(password) < size:
password.append(random.choice(string.ascii_uppercase)) # ensure at least one uppercase letter
if len(password) < size:
password.append(random.choice(string.digits)) # ensure at least one digit
if len(password) < size:
password.append(random.choice(string.punctuation)) # ensure at least one special character
random.shuffle(password) # shuffle to remove the predictability
return ''.join(password)
def password_checker(password):
if len(password) >= 8:
if bool(re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z\d])', password)):
print("The password is strong")
else:
print("The password is weak")
else:
print("You have entered a short or invalid password.")
# Generate a password
generated_password = password_generator()
print(generated_password)
# Check the generated password
password_checker(generated_password)
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import base64
import hashlib
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key).digest()
def encrypt_data(self, iv, raw):
raw = self._pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return cipher.iv, iv + cipher.encrypt(raw.encode())
def decrypt_data(self, iv, enc):
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return AESCipher._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
# Generate a random 128-bit IV for AES
iv = get_random_bytes(16)
# Generate a random 256-bit key for AES
key = get_random_bytes(32) # save this maybe?
Cipher = AESCipher(key)
# Encrypt the generated password
iv, encrypted_password = Cipher.encrypt_data(iv, generated_password)
print(f"Encrypted password: {encrypted_password}")
# Decrypt the encrypted password
decrypted_password = Cipher.decrypt_data(iv, encrypted_password)
print(f"Decrypted password: {decrypted_password}")
# Save the encrypted password to a file
with open(
'Password.txt',
'a', encoding='utf-8') as f:
f.write(f"{iv.hex()}:{encrypted_password.hex()}\n")
# Read the encrypted password from the file
with open(
'Password.txt',
'r', encoding='utf-8') as f:
for line in f.readlines():
line = line.strip() # Remove the trailing newline character
iv, encrypted_password = line.split(':')
decrypted_password = Cipher.decrypt_data(bytes.fromhex(iv), bytes.fromhex(encrypted_password))
Side notes for improvement:
'C:/Users/basse/OneDrive - King Salman International University/Semester 5/Introduction to Cyber Security/Password.txt'
this C:/Users/foo/Project/Password.txt'
just in case of personal information gets leaked!Hope this helps