crypt.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. from __future__ import annotations
  2. import json
  3. import base64
  4. import hashlib
  5. import random
  6. from Crypto.Cipher import AES
  7. def pad(data: str) -> bytes:
  8. # Convert the string to bytes and calculate the number of bytes to pad
  9. data_bytes = data.encode()
  10. padding = 16 - (len(data_bytes) % 16)
  11. # Append the padding bytes with their value
  12. return data_bytes + bytes([padding] * padding)
  13. def encrypt(data, key):
  14. salt = ""
  15. salted = ""
  16. dx = bytes()
  17. # Generate salt, as 8 random lowercase letters
  18. salt = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(8))
  19. # Our final key and IV come from the key and salt being repeatedly hashed
  20. for x in range(3):
  21. dx = hashlib.md5(dx + key.encode() + salt.encode()).digest()
  22. salted += dx.hex()
  23. # Pad the data before encryption
  24. data = pad(data)
  25. aes = AES.new(
  26. bytes.fromhex(salted[:64]), AES.MODE_CBC, bytes.fromhex(salted[64:96])
  27. )
  28. return json.dumps(
  29. {
  30. "ct": base64.b64encode(aes.encrypt(data)).decode(),
  31. "iv": salted[64:96],
  32. "s": salt.encode().hex(),
  33. }
  34. )
  35. def unpad(data: bytes) -> bytes:
  36. # Extract the padding value from the last byte and remove padding
  37. padding_value = data[-1]
  38. return data[:-padding_value]
  39. def decrypt(data: str, key: str):
  40. # Parse JSON data
  41. parsed_data = json.loads(base64.b64decode(data))
  42. ct = base64.b64decode(parsed_data["ct"])
  43. iv = bytes.fromhex(parsed_data["iv"])
  44. salt = bytes.fromhex(parsed_data["s"])
  45. salted = ''
  46. dx = b''
  47. for x in range(3):
  48. dx = hashlib.md5(dx + key.encode() + salt).digest()
  49. salted += dx.hex()
  50. aes = AES.new(
  51. bytes.fromhex(salted[:64]), AES.MODE_CBC, iv
  52. )
  53. data = aes.decrypt(ct)
  54. if data.startswith(b'[{"key":'):
  55. return unpad(data).decode()