def decrypt_user_credentials(encoded_key, encoded_iv, encoded_ct): encrypted_key = standard_b64decode(encoded_key) iv = standard_b64decode(encoded_iv) ciphertext = standard_b64decode(encoded_ct) result = get_private_key() if result.failure: return result private_key = RSA.import_key(result.value) cipher_rsa = PKCS1_OAEP.new(private_key, hashAlgo=SHA256) try: session_key = cipher_rsa.decrypt(encrypted_key) cipher_aes = AES.new(session_key, AES.MODE_CBC, iv) creds_plaintext = unpad(cipher_aes.decrypt(ciphertext), AES.block_size) except KeyError as e: error = f"Decryption Error: {repr(e)}" return Result.Fail(error) except ValueError as e: error = f"Decryption Error: {repr(e)}" return Result.Fail(error) split = creds_plaintext.decode("ascii").split(":") if len(split) != 2: error = 'User credentials not formatted correctly, expected 2 strings separated by ":" char.' return Result.Fail(error) user_creds = dict(email=split[0], password=split[1]) return Result.Ok(user_creds)
def decode_auth_token(auth_token): """Decode the auth token.""" if auth_token.startswith("Bearer "): split = auth_token.split("Bearer") auth_token = split[1].strip() if BlacklistToken.check_blacklist(auth_token): error = "Token blacklisted. Please log in again." return Result.Fail(error) result = get_public_key() if result.success: key = result.value algorithm = "RS256" else: key = current_app.config.get("SECRET_KEY") algorithm = "HS256" try: payload = jwt.decode(auth_token, key, algorithms=[algorithm]) return Result.Ok( dict(public_id=payload["sub"], admin=payload["admin"])) except jwt.ExpiredSignatureError: error = "Authorization token expired. Please log in again." return Result.Fail(error) except jwt.InvalidTokenError: error = "Invalid token. Please log in again." return Result.Fail(error)
def get_public_key(): """Return RSA key used to verify auth tokens in PEM format.""" result = construct_rsa_key() if not result["success"]: return Result.Fail(result["error"]) key = result["value"] public_key = key.publickey().export_key() return Result.Ok(public_key)
def get_private_key(): """Return RSA key used to sign auth tokens in PEM format.""" result = construct_rsa_key() if not result["success"]: return Result.Fail(result["error"]) key = result["value"] private_key = key.export_key() return Result.Ok(private_key)
def test_result_object(self): result_success = Result.Ok(42) self.assertTrue(result_success.success) self.assertFalse(result_success.failure) self.assertEqual(result_success.value, 42) self.assertIsNone(result_success.error) self.assertEqual(str(result_success), "[Success]") self.assertEqual(repr(result_success), f"Result<(success=True>") result_fail = Result.Fail("Something went wrong...") self.assertTrue(result_fail.failure) self.assertFalse(result_fail.success) self.assertIsNone(result_fail.value) self.assertEqual(result_fail.error, "Something went wrong...") self.assertEqual(str(result_fail), "[Failure] Something went wrong...") self.assertEqual( repr(result_fail), f'Result<(success=False, message="Something went wrong...")>', )
def encrypt_user_credentials(email, password): result = construct_rsa_key() if not result["success"]: return Result.Fail(result["error"]) key = result["value"] public_key = key.publickey() session_key = get_random_bytes(16) cipher_rsa = PKCS1_OAEP.new(public_key, hashAlgo=SHA256) encrypted_key = cipher_rsa.encrypt(session_key) cipher_aes = AES.new(session_key, AES.MODE_CBC) plaintext = f"{email}:{password}" ciphertext = cipher_aes.encrypt(pad(plaintext.encode(), AES.block_size)) key = standard_b64encode(encrypted_key).decode("utf-8") iv = standard_b64encode(cipher_aes.iv).decode("utf-8") ct = standard_b64encode(ciphertext).decode("utf-8") enc_user_creds = dict(key=key, iv=iv, ct=ct) return Result.Ok(enc_user_creds)
def get_public_key_hex(): """Return RSA public key in PEM format without header and footer.""" result = get_public_key() if result.failure: return result public_key = result.value split = public_key.split(b"\n") public_key_b64 = b"".join(split[1:len(split) - 1]) public_key_bytes = standard_b64decode(public_key_b64) return Result.Ok(public_key_bytes.hex())