diff --git a/README.md b/README.md index 8a3cc9f..82cdd14 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Thank you for your compliance, we work hard on the development of KeyAuth and do ## **What is KeyAuth?** -KeyAuth is an Open source authentication system with cloud hosting plans as well. Client SDKs available for [C#](https://github.com/KeyAuth/KeyAuth-CSHARP-Example), [C++](https://github.com/KeyAuth/KeyAuth-CPP-Example), [Python](https://github.com/KeyAuth/KeyAuth-Python-Example), [Java](https://github.com/KeyAuth-Archive/KeyAuth-JAVA-api), [JavaScript](https://github.com/mazkdevf/KeyAuth-JS-Example), [VB.NET](https://github.com/KeyAuth/KeyAuth-VB-Example), [PHP](https://github.com/KeyAuth/KeyAuth-PHP-Example), [Rust](https://github.com/KeyAuth/KeyAuth-Rust-Example), [Go](https://github.com/mazkdevf/KeyAuth-Go-Example), [Lua](https://github.com/mazkdevf/KeyAuth-Lua-Examples), [Ruby](https://github.com/mazkdevf/KeyAuth-Ruby-Example), and [Perl](https://github.com/mazkdevf/KeyAuth-Perl-Example). KeyAuth has several unique features such as memory streaming, webhook function where you can send requests to API without leaking the API, discord webhook notifications, ban the user securely through the application at your discretion. Feel free to join https://t.me/keyauth if you have questions or suggestions. +KeyAuth is a powerful cloud-based authentication system designed to protect your software from piracy and unauthorized access. With KeyAuth, you can implement secure licensing, user management, and subscription systems in minutes. Client SDKs available for [C#](https://github.com/KeyAuth/KeyAuth-CSHARP-Example), [C++](https://github.com/KeyAuth/KeyAuth-CPP-Example), [Python](https://github.com/KeyAuth/KeyAuth-Python-Example), [Java](https://github.com/KeyAuth-Archive/KeyAuth-JAVA-api), [JavaScript](https://github.com/mazkdevf/KeyAuth-JS-Example), [VB.NET](https://github.com/KeyAuth/KeyAuth-VB-Example), [PHP](https://github.com/KeyAuth/KeyAuth-PHP-Example), [Rust](https://github.com/KeyAuth/KeyAuth-Rust-Example), [Go](https://github.com/mazkdevf/KeyAuth-Go-Example), [Lua](https://github.com/mazkdevf/KeyAuth-Lua-Examples), [Ruby](https://github.com/mazkdevf/KeyAuth-Ruby-Example), and [Perl](https://github.com/mazkdevf/KeyAuth-Perl-Example). KeyAuth has several unique features such as memory streaming, webhook function where you can send requests to API without leaking the API, discord webhook notifications, ban the user securely through the application at your discretion. Feel free to join https://t.me/keyauth if you have questions or suggestions. > [!TIP] > https://vaultcord.com FREE Discord bot to Backup server, members, channels, messages & more. Custom verify page, block alt accounts, VPNs & more. @@ -44,7 +44,7 @@ For API, `keyauth.cc` will not work because I purposefully blocked it on there s You can either use Pyinstaller or Nuitka. Links: -- Nutika: https://nuitka.net/ +- Nuitka: https://nuitka.net/ - Pyinstaller: https://pyinstaller.org/ Pyinstaller: @@ -230,6 +230,22 @@ Function only works after login. keyauthapp.ban() ``` +## **Enable Two Factor Authentication (2fa)** + +Enable two factor authentication (2fa) on a client account. + +```py +keyauthapp.enable2fa() +``` + +## **Disable Two Factor Authentication (2fa)** + +Disable two factor authentication (2fa) on a client account. + +```py +keyauthapp.disable2fa() +``` + ## **Logout session** Logout the users session and close the application. diff --git a/keyauth.py b/keyauth.py index 0b66678..4eb9558 100644 --- a/keyauth.py +++ b/keyauth.py @@ -4,8 +4,11 @@ import binascii # hex encoding import platform # check platform import subprocess # needed for mac device -from datetime import datetime, timedelta +import qrcode +from datetime import datetime, timezone, timedelta from discord_interactions import verify_key # used for signature verification +from PIL import Image + try: if os.name == 'nt': @@ -143,7 +146,7 @@ def upgrade(self, user, license): time.sleep(3) os._exit(1) - def login(self, user, password, hwid=None): + def login(self, user, password, code=None, hwid=None): self.checkinit() if hwid is None: hwid = others.get_hwid() @@ -155,8 +158,11 @@ def login(self, user, password, hwid=None): "hwid": hwid, "sessionid": self.sessionid, "name": self.name, - "ownerid": self.ownerid + "ownerid": self.ownerid, } + + if code is not None: + post_data["code"] = code response = self.__do_request(post_data) @@ -170,7 +176,7 @@ def login(self, user, password, hwid=None): time.sleep(3) os._exit(1) - def license(self, key, hwid=None): + def license(self, key, code=None, hwid=None): self.checkinit() if hwid is None: hwid = others.get_hwid() @@ -183,6 +189,9 @@ def license(self, key, hwid=None): "name": self.name, "ownerid": self.ownerid } + + if code is not None: + post_data["code"] = code response = self.__do_request(post_data) @@ -507,15 +516,87 @@ def logout(self): else: print(json["message"]) time.sleep(3) - os._exit(1) + os._exit(1) + + def enable2fa(self, code=None): + self.checkinit() + + post_data = { + "type": "2faenable", + "sessionid": self.sessionid, + "name": self.name, + "ownerid": self.ownerid, + "code": code + } + + response = self.__do_request(post_data) + + json = jsond.loads(response) + + if json["success"]: + if code is None: + # First request: Display the 2FA secret code + print(f"Your 2FA secret code is: {json['2fa']['secret_code']}") + qr_code = json['2fa']['QRCode'] + self.display_qr_code(qr_code) + code_input = input("Enter the 6 digit 2fa code to enable 2fa: ") + self.enable2fa(code_input); + else: + # Second request: Confirm successful 2FA activation + print("2FA has been successfully enabled!") + time.sleep(3) + else: + print(f"Error: {json['message']}") + time.sleep(3) + os._exit(1) + + def disable2fa(self, code=None): + self.checkinit() + + code = input("Enter the 6 digit 2fa code to disable 2fa: ") + + post_data = { + "type": "2fadisable", + "sessionid": self.sessionid, + "name": self.name, + "ownerid": self.ownerid, + "code": code + } + + response = self.__do_request(post_data) + + json = jsond.loads(response) + + print(json['message']) + time.sleep(3) + + + def display_qr_code(self, qr_code_url): + # Generate QR code image + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=10, + border=4, + ) + + # Add the QR code URL data + qr.add_data(qr_code_url) + qr.make(fit=True) + + # Create an image from the QR code + img = qr.make_image(fill='black', back_color='white') + + # Display the QR code image + img.show() def __do_request(self, post_data): try: response = requests.post( - "https://keyauth.win/api/1.3/", data=post_data, timeout=10 + "https://keyauth.win/api/1.3/", data=post_data, timeout=10 ) - if post_data["type"] == "log" or post_data["type"] == "file": + if post_data["type"] == "log" or post_data["type"] == "file" or post_data["type"] == "2faenable" or post_data["type"] == "2fadisable": return response.text # Get the signature and timestamp from the headers @@ -527,8 +608,12 @@ def __do_request(self, post_data): time.sleep(3) os._exit(1) - server_time = datetime.utcfromtimestamp(int(timestamp)) - current_time = datetime.utcnow() + server_time = datetime.fromtimestamp(int(timestamp), timezone.utc) + current_time = datetime.now(timezone.utc) + + #print(f"Server Timestamp (UTC seconds): {timestamp}") + #print(f"Server Time (UTC seconds): {server_time.timestamp()}") + #print(f"Current Time (UTC seconds): {current_time.timestamp()}") buffer_seconds = 5 time_difference = current_time - server_time @@ -538,31 +623,17 @@ def __do_request(self, post_data): time.sleep(3) os._exit(1) - # Proceed with creating debug folders and logging - if not os.path.exists("C:\\ProgramData\\KeyAuth"): - os.makedirs("C:\\ProgramData\\KeyAuth\\Debug") - - exe_name = os.path.basename(__file__) - log_dir = f"C:\\ProgramData\\KeyAuth\\Debug\\{exe_name}" - if not os.path.exists(log_dir): - os.makedirs(log_dir) - - with open(f"{log_dir}\\log.txt", "a") as log_file: - if len(response.text) <= 200: - execution_time = time.strftime("%I:%M %p | %m/%d/%Y") - log_file.write(f"\n{execution_time} | {post_data['type']} \nResponse: {response.text}") - if not verify_key(response.text.encode('utf-8'), signature, timestamp, '5586b4bc69c7a4b487e4563a4cd96afd39140f919bd31cea7d1c6a1e8439422b'): print("Signature checksum failed. Request was tampered with or session ended most likely.") - print("Response: " + response.text) time.sleep(3) os._exit(1) return response.text - except requests.exceptions.Timeout: + except requests.exceptions.Timeout: print("Request timed out. Server is probably down/slow at the moment") - + + class application_data_class: numUsers = numKeys = app_ver = customer_panel = onlineUsers = "" diff --git a/main.py b/main.py index 8aaded8..6fc86d7 100644 --- a/main.py +++ b/main.py @@ -17,7 +17,7 @@ import os import hashlib from time import sleep -from datetime import datetime +from datetime import datetime, UTC # import json as jsond # ^^ only for auto login/json writing/reading @@ -28,11 +28,12 @@ def clear(): if platform.system() == 'Windows': os.system('cls & title Python Example') # clear console, change title elif platform.system() == 'Linux': - os.system('clear') # clear console - sys.stdout.write("\x1b]0;Python Example\x07") # change title + os.system('clear') # Clear the terminal + sys.stdout.write("\033]0;Python Example\007") # Set terminal title + sys.stdout.flush() elif platform.system() == 'Darwin': - os.system("clear && printf '\e[3J'") # clear console - os.system('''echo - n - e "\033]0;Python Example\007"''') # change title + os.system("clear && printf '\033[3J'") # Clear terminal and scrollback + os.system('echo -n -e "\033]0;Python Example\007"') # Set terminal title print("Initializing") @@ -46,9 +47,9 @@ def getchecksum(): keyauthapp = api( - name = "", # Application Name - ownerid = "", # Owner ID - version = "1.0", # Application Version + name = "", # App name + ownerid = "", # Account ID + version = "", # Application version. Used for automatic downloads see video here https://www.youtube.com/watch?v=kW195PLCBKs hash_to_check = getchecksum() ) @@ -63,7 +64,8 @@ def answer(): if ans == "1": user = input('Provide username: ') password = input('Provide password: ') - keyauthapp.login(user, password) + code = input('Enter 2fa code: (not using 2fa? Just press enter)') + keyauthapp.login(user, password, code) elif ans == "2": user = input('Provide username: ') password = input('Provide password: ') @@ -75,7 +77,8 @@ def answer(): keyauthapp.upgrade(user, license) elif ans == "4": key = input('Enter your license: ') - keyauthapp.license(key) + code = input('Enter 2fa code: (not using 2fa? Just press enter)') + keyauthapp.license(key, code) else: print("\nInvalid option") sleep(1) @@ -164,7 +167,16 @@ def answer(): print(e) os._exit(1)''' +keyauthapp.fetchStats() +# Display Application Data +print("\nApplication data: ") +print("App Version: " + keyauthapp.app_data.app_ver) +print("Customer Panel Link: " + keyauthapp.app_data.customer_panel) +print("Number of Keys: " + keyauthapp.app_data.numKeys) +print("Number of Users: " + keyauthapp.app_data.numUsers) +print("Online Users: " + keyauthapp.app_data.onlineUsers) +# Display User Data print("\nUser data: ") print("Username: " + keyauthapp.user_data.username) print("IP address: " + keyauthapp.user_data.ip) @@ -173,15 +185,29 @@ def answer(): subs = keyauthapp.user_data.subscriptions # Get all Subscription names, expiry, and timeleft for i in range(len(subs)): sub = subs[i]["subscription"] # Subscription from every Sub - expiry = datetime.utcfromtimestamp(int(subs[i]["expiry"])).strftime( + expiry = datetime.fromtimestamp(int(subs[i]["expiry"]), UTC).strftime( '%Y-%m-%d %H:%M:%S') # Expiry date from every Sub timeleft = subs[i]["timeleft"] # Timeleft from every Sub print(f"[{i + 1} / {len(subs)}] | Subscription: {sub} - Expiry: {expiry} - Timeleft: {timeleft}") -print("Created at: " + datetime.utcfromtimestamp(int(keyauthapp.user_data.createdate)).strftime('%Y-%m-%d %H:%M:%S')) -print("Last login at: " + datetime.utcfromtimestamp(int(keyauthapp.user_data.lastlogin)).strftime('%Y-%m-%d %H:%M:%S')) -print("Expires at: " + datetime.utcfromtimestamp(int(keyauthapp.user_data.expires)).strftime('%Y-%m-%d %H:%M:%S')) +print("Created at: " + datetime.fromtimestamp(int(keyauthapp.user_data.createdate), UTC).strftime('%Y-%m-%d %H:%M:%S')) +print("Last login at: " + datetime.fromtimestamp(int(keyauthapp.user_data.lastlogin), UTC).strftime('%Y-%m-%d %H:%M:%S')) +print("Expires at: " + datetime.fromtimestamp(int(keyauthapp.user_data.expires), UTC).strftime('%Y-%m-%d %H:%M:%S')) + +# Two Factor Authentication +print("\nTwo Factor Authentication:") +print("1. Enable 2FA") +print("2. Disable 2FA") + +tfaans = input("Select Option: ") +if tfaans == "1": + keyauthapp.enable2fa() # You only need to call this once as it's called in the API file. +elif tfaans == "2": + keyauthapp.disable2fa() # You only need to call this once as it's called in the API file, and should ideally only need to be called once anyways. +else: + print("\nInvalid Option") + print("\nExiting in five seconds..") sleep(5) os._exit(1) diff --git a/requirements.txt b/requirements.txt index 1778876..b57953d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ requests pywin32 discord-interactions +qrcode +pillow