Commit ea1985e5 authored by Sadnan Kibria Kawshik's avatar Sadnan Kibria Kawshik

Initial commit

parents
# Python cache
__pycache__/
*.py[cod]
# Virtual environments
venv/
.venv/
env/
ENV/
# System files
.DS_Store
Thumbs.db
# IDE/editor settings
.vscode/
.idea/
# Encrypted or secret configs
config.json
config.py
*.key
*.pem
# JWT tokens or test outputs
*.token
*.enc
*.log
# Packaging/build artifacts
dist/
build/
*.egg-info/
# OS shell files (optional scripts)
*.bat
*.sh
# aes_utils.py
import base64
import hashlib
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from config import AES_ENCRYPTION_KEY, AES_ENCRYPTION_IV
class TokenDecryptionException(Exception):
pass
class AESUtils:
def __init__(self):
self.encryption_key = AES_ENCRYPTION_KEY.encode('utf-8')
self.encryption_iv = AES_ENCRYPTION_IV.encode('utf-8')
def _make_key(self):
return hashlib.sha256(self.encryption_key).digest()
def _make_iv(self):
return self.encryption_iv # Already bytes
def encrypt(self, plaintext: str) -> str:
cipher = AES.new(self._make_key(), AES.MODE_CBC, self._make_iv())
encrypted = cipher.encrypt(pad(plaintext.encode('utf-8'), AES.block_size))
return base64.b64encode(encrypted).decode('utf-8')
def decrypt(self, encrypted_b64: str) -> str:
try:
cipher = AES.new(self._make_key(), AES.MODE_CBC, self._make_iv())
decrypted = unpad(cipher.decrypt(base64.b64decode(encrypted_b64)), AES.block_size)
return decrypted.decode('utf-8')
except Exception as e:
raise TokenDecryptionException(f"can't decrypt token! : {e}") from e
import base64
import jwt
import time
from jwt import InvalidTokenError, ExpiredSignatureError
from typing import Optional, List, Any
from datetime import datetime,timezone,timedelta
class TokenDecryptionException(Exception):
pass
class JwtClaimName:
FIRST_NAME = "firstName"
LAST_NAME = "lastName"
AUTHORITIES = "authorities"
class JwtUtils:
def __init__(self, jwt_secret: str):
# Mimic `DatatypeConverter.parseBase64Binary(secret)`
self.jwt_secret = base64.b64decode(jwt_secret)
def create_jwt(self, claims: dict, expire_seconds: int = 3600) -> str:
payload = claims.copy()
payload["iat"] = int(time.time())
payload["exp"] = payload["iat"] + expire_seconds
token = jwt.encode(payload, self.jwt_secret, algorithm="HS512")
# PyJWT >=2.0 returns str, else bytes
if isinstance(token, bytes):
token = token.decode('utf-8')
return token
def parse_token(self, header: str, token_type: str = "Bearer") -> Optional[str]:
if header and header.startswith(token_type + " "):
return header[len(token_type) + 1:]
return None
def parse_claims_from_jwt(self, token: str) -> dict:
try:
payload = jwt.decode(token, self.jwt_secret, algorithms=["HS512"])
bdt = timezone(timedelta(hours=6))
iat = payload.get("iat")
exp = payload.get("exp")
if iat:
iat_str = datetime.fromtimestamp(iat, bdt).strftime("%a %b %d %H:%M:%S %Z %Y")
payload["iat"] = iat_str
if exp:
exp_str = datetime.fromtimestamp(exp, bdt).strftime("%a %b %d %H:%M:%S %Z %Y")
payload["exp"] = exp_str
return payload
except (InvalidTokenError, ExpiredSignatureError) as e:
raise TokenDecryptionException(f"Invalid JWT token: {e}")
def get_claim_from_jwt(self, token: str, claim_name: str) -> Optional[Any]:
if not token:
return None
claims = self.parse_claims_from_jwt(token)
return claims.get(claim_name)
def get_full_name_from_jwt(self, token: str) -> Optional[str]:
if not token:
return None
first = self.get_claim_from_jwt(token, JwtClaimName.FIRST_NAME)
last = self.get_claim_from_jwt(token, JwtClaimName.LAST_NAME)
return f"{first} {last}" if first and last else None
def get_authorities_from_jwt(self, token: str) -> List[str]:
return self.get_claim_from_jwt(token, JwtClaimName.AUTHORITIES) or []
def is_jwt_token_valid(self, token: str) -> bool:
try:
jwt.decode(token, self.jwt_secret, algorithms=["HS256"])
return True
except (InvalidTokenError, ExpiredSignatureError):
return False
def get_expiry_from_jwt(self, token: str) -> Optional[datetime]:
claims = self.parse_claims_from_jwt(token)
exp = claims.get("exp")
if exp:
return datetime.fromtimestamp(exp)
return None
from aes_utils import AESUtils, TokenDecryptionException
from jwt_utils import JwtUtils, TokenDecryptionException as JwtException
import config
def aes_menu(aes):
while True:
choice = input("AES -> (E)ncrypt / (D)ecrypt / (B)ack: ").strip().lower()
if choice == 'e':
text = input("Text to encrypt: ")
print("Encrypted:", aes.encrypt(text))
elif choice == 'd':
text = input("Encrypted (Base64): ")
try:
print("Decrypted:", aes.decrypt(text))
except TokenDecryptionException as e:
print("Error:", e)
elif choice == 'b':
break
else:
print("Invalid choice.")
def print_claims(claims):
for key, value in claims.items():
print(f"{key}: {value}")
def jwt_menu(jwt, aes):
while True:
# print("(N) Create JWT + Encrypt")
print("(D) Decrypt + Parse JWT")
# print("(F) Get full name from JWT")
# print("(C) Get all claims")
# print("(V) Validate JWT")
print("(Q) quit")
choice = input("Choice: ").strip().lower()
if choice == 'n':
first = input("First name: ")
last = input("Last name: ")
auth_str = input("Authorities (comma-separated): ")
authorities = [a.strip() for a in auth_str.split(",") if a.strip()]
claims = {
"firstName": first,
"lastName": last,
"authorities": authorities
}
token = jwt.create_jwt(claims)
print("Created JWT:", token)
encrypted = aes.encrypt(token)
print("Encrypted JWT:", encrypted)
elif choice == 'd':
encrypted_token = input("Enter encrypted JWT: ")
try:
decrypted_token = aes.decrypt(encrypted_token)
print("Your JWT has been decrypted successfully.")
print("Decrypted JWT:", decrypted_token)
print("")
ch = input("Do you want to see the claims? (y/n): ").strip().lower()
if ch == 'y':
claims = jwt.parse_claims_from_jwt(decrypted_token)
print("Claims:", claims)
print()
else:
break
except (TokenDecryptionException, JwtException) as e:
print("Failed:", e)
elif choice == 'f':
token = input("Enter JWT token: ")
try:
print("Full name:", jwt.get_full_name_from_jwt(token))
except JwtException as e:
print("Error:", e)
elif choice == 'c':
token = input("Enter JWT token: ")
try:
decoded_token = aes.decrypt(token)
claims = jwt.parse_claims_from_jwt(decoded_token)
print_claims(claims)
except JwtException as e:
print("Error:", e)
elif choice == 'v':
token = input("Enter JWT token: ")
valid = jwt.is_jwt_token_valid(token)
print("JWT Valid:" if valid else "JWT Invalid or expired")
elif choice == 'q':
break
else:
print("Invalid choice.")
def main():
aes = AESUtils()
jwt = JwtUtils(config.JWT_SECRET)
print("\nWelcome to the Token Decryption Tool!")
print("\nHere are your options:")
jwt_menu(jwt, aes)
if __name__ == "__main__":
main()
pycryptodome
pyjwt
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment