|
4 | 4 | import binascii # hex encoding |
5 | 5 | import platform # check platform |
6 | 6 | import subprocess # needed for mac device |
7 | | -from datetime import datetime, timedelta |
| 7 | +import qrcode |
| 8 | +from datetime import datetime, timezone, timedelta |
8 | 9 | from discord_interactions import verify_key # used for signature verification |
| 10 | +from PIL import Image |
| 11 | + |
9 | 12 |
|
10 | 13 | try: |
11 | 14 | if os.name == 'nt': |
@@ -143,7 +146,7 @@ def upgrade(self, user, license): |
143 | 146 | time.sleep(3) |
144 | 147 | os._exit(1) |
145 | 148 |
|
146 | | - def login(self, user, password, hwid=None): |
| 149 | + def login(self, user, password, code=None, hwid=None): |
147 | 150 | self.checkinit() |
148 | 151 | if hwid is None: |
149 | 152 | hwid = others.get_hwid() |
@@ -155,8 +158,11 @@ def login(self, user, password, hwid=None): |
155 | 158 | "hwid": hwid, |
156 | 159 | "sessionid": self.sessionid, |
157 | 160 | "name": self.name, |
158 | | - "ownerid": self.ownerid |
| 161 | + "ownerid": self.ownerid, |
159 | 162 | } |
| 163 | + |
| 164 | + if code is not None: |
| 165 | + post_data["code"] = code |
160 | 166 |
|
161 | 167 | response = self.__do_request(post_data) |
162 | 168 |
|
@@ -170,7 +176,7 @@ def login(self, user, password, hwid=None): |
170 | 176 | time.sleep(3) |
171 | 177 | os._exit(1) |
172 | 178 |
|
173 | | - def license(self, key, hwid=None): |
| 179 | + def license(self, key, code=None, hwid=None): |
174 | 180 | self.checkinit() |
175 | 181 | if hwid is None: |
176 | 182 | hwid = others.get_hwid() |
@@ -183,6 +189,9 @@ def license(self, key, hwid=None): |
183 | 189 | "name": self.name, |
184 | 190 | "ownerid": self.ownerid |
185 | 191 | } |
| 192 | + |
| 193 | + if code is not None: |
| 194 | + post_data["code"] = code |
186 | 195 |
|
187 | 196 | response = self.__do_request(post_data) |
188 | 197 |
|
@@ -507,15 +516,87 @@ def logout(self): |
507 | 516 | else: |
508 | 517 | print(json["message"]) |
509 | 518 | time.sleep(3) |
510 | | - os._exit(1) |
| 519 | + os._exit(1) |
| 520 | + |
| 521 | + def enable2fa(self, code=None): |
| 522 | + self.checkinit() |
| 523 | + |
| 524 | + post_data = { |
| 525 | + "type": "2faenable", |
| 526 | + "sessionid": self.sessionid, |
| 527 | + "name": self.name, |
| 528 | + "ownerid": self.ownerid, |
| 529 | + "code": code |
| 530 | + } |
| 531 | + |
| 532 | + response = self.__do_request(post_data) |
| 533 | + |
| 534 | + json = jsond.loads(response) |
| 535 | + |
| 536 | + if json["success"]: |
| 537 | + if code is None: |
| 538 | + # First request: Display the 2FA secret code |
| 539 | + print(f"Your 2FA secret code is: {json['2fa']['secret_code']}") |
| 540 | + qr_code = json['2fa']['QRCode'] |
| 541 | + self.display_qr_code(qr_code) |
| 542 | + code_input = input("Enter the 6 digit 2fa code to enable 2fa: ") |
| 543 | + self.enable2fa(code_input); |
| 544 | + else: |
| 545 | + # Second request: Confirm successful 2FA activation |
| 546 | + print("2FA has been successfully enabled!") |
| 547 | + time.sleep(3) |
| 548 | + else: |
| 549 | + print(f"Error: {json['message']}") |
| 550 | + time.sleep(3) |
| 551 | + os._exit(1) |
| 552 | + |
| 553 | + def disable2fa(self, code=None): |
| 554 | + self.checkinit() |
| 555 | + |
| 556 | + code = input("Enter the 6 digit 2fa code to disable 2fa: ") |
| 557 | + |
| 558 | + post_data = { |
| 559 | + "type": "2fadisable", |
| 560 | + "sessionid": self.sessionid, |
| 561 | + "name": self.name, |
| 562 | + "ownerid": self.ownerid, |
| 563 | + "code": code |
| 564 | + } |
| 565 | + |
| 566 | + response = self.__do_request(post_data) |
| 567 | + |
| 568 | + json = jsond.loads(response) |
| 569 | + |
| 570 | + print(json['message']) |
| 571 | + time.sleep(3) |
| 572 | + |
| 573 | + |
| 574 | + def display_qr_code(self, qr_code_url): |
| 575 | + # Generate QR code image |
| 576 | + qr = qrcode.QRCode( |
| 577 | + version=1, |
| 578 | + error_correction=qrcode.constants.ERROR_CORRECT_L, |
| 579 | + box_size=10, |
| 580 | + border=4, |
| 581 | + ) |
| 582 | + |
| 583 | + # Add the QR code URL data |
| 584 | + qr.add_data(qr_code_url) |
| 585 | + qr.make(fit=True) |
| 586 | + |
| 587 | + # Create an image from the QR code |
| 588 | + img = qr.make_image(fill='black', back_color='white') |
| 589 | + |
| 590 | + # Display the QR code image |
| 591 | + img.show() |
511 | 592 |
|
512 | 593 | def __do_request(self, post_data): |
513 | 594 | try: |
514 | 595 | response = requests.post( |
515 | | - "https://keyauth.win/api/1.3/", data=post_data, timeout=10 |
| 596 | + "https://keyauth.win/api/1.3/", data=post_data, timeout=10 |
516 | 597 | ) |
517 | 598 |
|
518 | | - if post_data["type"] == "log" or post_data["type"] == "file": |
| 599 | + if post_data["type"] == "log" or post_data["type"] == "file" or post_data["type"] == "2faenable" or post_data["type"] == "2fadisable": |
519 | 600 | return response.text |
520 | 601 |
|
521 | 602 | # Get the signature and timestamp from the headers |
@@ -527,8 +608,12 @@ def __do_request(self, post_data): |
527 | 608 | time.sleep(3) |
528 | 609 | os._exit(1) |
529 | 610 |
|
530 | | - server_time = datetime.utcfromtimestamp(int(timestamp)) |
531 | | - current_time = datetime.utcnow() |
| 611 | + server_time = datetime.fromtimestamp(int(timestamp), timezone.utc) |
| 612 | + current_time = datetime.now(timezone.utc) |
| 613 | + |
| 614 | + #print(f"Server Timestamp (UTC seconds): {timestamp}") |
| 615 | + #print(f"Server Time (UTC seconds): {server_time.timestamp()}") |
| 616 | + #print(f"Current Time (UTC seconds): {current_time.timestamp()}") |
532 | 617 |
|
533 | 618 | buffer_seconds = 5 |
534 | 619 | time_difference = current_time - server_time |
@@ -538,31 +623,17 @@ def __do_request(self, post_data): |
538 | 623 | time.sleep(3) |
539 | 624 | os._exit(1) |
540 | 625 |
|
541 | | - # Proceed with creating debug folders and logging |
542 | | - if not os.path.exists("C:\\ProgramData\\KeyAuth"): |
543 | | - os.makedirs("C:\\ProgramData\\KeyAuth\\Debug") |
544 | | - |
545 | | - exe_name = os.path.basename(__file__) |
546 | | - log_dir = f"C:\\ProgramData\\KeyAuth\\Debug\\{exe_name}" |
547 | | - if not os.path.exists(log_dir): |
548 | | - os.makedirs(log_dir) |
549 | | - |
550 | | - with open(f"{log_dir}\\log.txt", "a") as log_file: |
551 | | - if len(response.text) <= 200: |
552 | | - execution_time = time.strftime("%I:%M %p | %m/%d/%Y") |
553 | | - log_file.write(f"\n{execution_time} | {post_data['type']} \nResponse: {response.text}") |
554 | | - |
555 | 626 | if not verify_key(response.text.encode('utf-8'), signature, timestamp, '5586b4bc69c7a4b487e4563a4cd96afd39140f919bd31cea7d1c6a1e8439422b'): |
556 | 627 | print("Signature checksum failed. Request was tampered with or session ended most likely.") |
557 | | - print("Response: " + response.text) |
558 | 628 | time.sleep(3) |
559 | 629 | os._exit(1) |
560 | 630 |
|
561 | 631 | return response.text |
562 | 632 |
|
563 | | - except requests.exceptions.Timeout: |
| 633 | + except requests.exceptions.Timeout: |
564 | 634 | print("Request timed out. Server is probably down/slow at the moment") |
565 | | - |
| 635 | + |
| 636 | + |
566 | 637 | class application_data_class: |
567 | 638 | numUsers = numKeys = app_ver = customer_panel = onlineUsers = "" |
568 | 639 |
|
|