diff options
| -rw-r--r-- | Godot.Secure.AES-256.Release-v4_v4.6.x.-.Latest.py | 545 | ||||
| -rw-r--r-- | Log-2026-08-21_11-43-23-973182-Godot-Secure-AES.txt | 8 | ||||
| -rw-r--r-- | Log-2026-08-21_11-43-45-886657-Godot-Secure-AES.txt | 8 | ||||
| -rw-r--r-- | Log-2026-08-21_11-44-08-879220-Godot-Secure-AES.txt | 8 | ||||
| -rw-r--r-- | Log-2026-08-21_11-44-50-030431-Godot-Secure-AES.txt | 8 | ||||
| -rw-r--r-- | Log-2026-08-21_11-45-07-074435-Godot-Secure-AES.txt | 12 | ||||
| -rw-r--r-- | Log-2026-08-21_11-45-37-736396-Godot-Secure-AES.txt | 68 | ||||
| -rw-r--r-- | core/crypto/security_token.h | 11 | ||||
| -rwxr-xr-x | core/io/file_access_encrypted.cpp | 46 | ||||
| -rwxr-xr-x | core/io/file_access_encrypted.h | 2 | ||||
| -rwxr-xr-x | core/io/file_access_pack.h | 2 | ||||
| -rwxr-xr-x | version.py | 2 |
12 files changed, 703 insertions, 17 deletions
diff --git a/Godot.Secure.AES-256.Release-v4_v4.6.x.-.Latest.py b/Godot.Secure.AES-256.Release-v4_v4.6.x.-.Latest.py new file mode 100644 index 0000000000..e1b3b87114 --- /dev/null +++ b/Godot.Secure.AES-256.Release-v4_v4.6.x.-.Latest.py @@ -0,0 +1,545 @@ +import os +import sys +import random +import string +import binascii +import secrets +import datetime + +class LogColors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +def generate_random_tag(length=4): + return ''.join(random.choices(string.ascii_uppercase, k=length)) + +def generate_random_token(length=32): + return bytes([random.randint(0, 255) for _ in range(length)]) + +def hex_to_bytes(hex_string: str) -> bytes: + return bytes.fromhex(hex_string) + +def generate_magic_header(tag: str, endian='little') -> str: + if len(tag) != 4: + raise ValueError("Tag must be exactly 4 characters.") + + if endian == 'little': + tag = tag[::-1] # Reverse for little-endian + + hex_value = "0x" + ''.join(f"{ord(c):02X}" for c in tag) + return hex_value + +def build_random_key_derivation(): + operands = ["key_ptr[i]", "Security::TOKEN[i]"] + + base_ops = [ + "({a} ^ {b})", + "({a} + {b})", + "({a} | {b})", + "({a} & {b})", + "(({a} << {shift}) | ({a} >> {rshift}))", + "(({a} ^ {b}) + {const})", + "(({a} + {b}) ^ {const})", + ] + + chain_ops = [ + "({expr} ^ {value})", + "({expr} + {value})", + "({expr} | {value})", + "(({expr} << {shift}) | ({expr} >> {rshift}))", + "(({expr} ^ {value}) + {const})", + "(({expr} + {value}) ^ {const})", + ] + + def rotation(): + shift = secrets.randbelow(7) + 1 + return shift, 8 - shift + + def rand_const(): + return secrets.randbelow(255) + 1 # never zero + + layers = secrets.randbelow(5) + 2 + + a = secrets.choice(operands) + b = operands[1] if a == operands[0] else operands[0] + shift, rshift = rotation() + + expression = secrets.choice(base_ops).format(a=a,b=b,shift=shift,rshift=rshift,const=rand_const()) + + for _ in range(layers - 1): + shift, rshift = rotation() + value = secrets.choice(operands) + + # never allow identical cancellation + if value == expression: + value = secrets.choice(operands) + + expression = secrets.choice(chain_ops).format(expr=expression,value=value,shift=shift,rshift=rshift,const=rand_const()) + + return f"token_key.write[i] = (uint8_t)({expression});" + +def save_log(message): + if not str(message).find("\033[") > 0: + with open(logFileName,"a", encoding="utf-8") as logf: logf.write(f"{message}\n") + return message + +def print_success(message): + save_log(f" [✓] {message}") + print(f"{LogColors.OKGREEN} ✓{LogColors.ENDC} {message}") + +def print_error(message): + save_log(f" [✗] {message}\n") + print(f"{LogColors.FAIL} ✗{LogColors.ENDC} {message}") + +def print_info(message): + save_log(f"\n[INFO] - {message}") + print(f"\n{LogColors.OKBLUE} ℹ {LogColors.ENDC} {message}") + +def print_operation(message): + save_log(f" [=>] {message}") + print(f"{LogColors.HEADER} =>{LogColors.ENDC} {message}") + +def print_warning(message): + save_log(f"\n[WARN] - {message}") + print(f"\n{LogColors.WARNING} ⚠ {LogColors.ENDC} {message}") + + +# Generate unique identifiers +global godot_root +global encKey + +baseTag = generate_random_tag() +encTag = generate_random_tag() +security_token = generate_random_token() +token_hex = binascii.hexlify(security_token).decode('utf-8') +token_c_array = ', '.join([f'0x{b:02X}' for b in security_token]) +baseHeader = generate_magic_header(baseTag) +encHeader = generate_magic_header(encTag) +key_derivation_algorithm = "token_key.write[i] = key_ptr[i] ^ Security::TOKEN[i];" + +fileCreated = True +backup_path = None +current_dt = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S-%f") +logFileName = f"Log-{current_dt}-Godot-Secure-AES.txt" + + +# Start Script Startup Operations +if len(sys.argv) == 1: + # No argument provided, use current directory + godot_root = os.getcwd() + print("\nNo directory specified. Using current directory as Godot Source Root.") +elif len(sys.argv) == 2: + # One argument provided, use it as Godot root + godot_root = sys.argv[1] +else: + # Too many arguments provided + print("\nUsage: python Godot_Secure.py <godot_source_root>") + try: + exit = input("\nPress Enter key to exit...") + except EOFError: + pass + sys.exit(1) + + +# Log File Creation +with open(logFileName, "w", encoding="utf-8") as logf: logf.write(f"Created On - {current_dt}\nThis is Godot-Secure Log file, SAVE IT to secure place for later getting values.\n\n") + +# Check for required Godot source components +core_dir = os.path.join(godot_root, "core") +sconstruct_file = os.path.join(godot_root, "SConstruct") + +# Get Current Encryption Key From Enviroment +try: + encKey = os.environ["SCRIPT_AES256_ENCRYPTION_KEY"] +except: + encKey = "Can't Fetch Your Enviroment Variable \"SCRIPT_AES256_ENCRYPTION_KEY\"" + +if not (os.path.isdir(core_dir) and os.path.isfile(sconstruct_file)): + log = save_log("Error: No valid Godot Source Detected in the Specified Directory.") + print(f"{LogColors.FAIL}{log}{LogColors.ENDC}") + try: + exit = input("\nPress Enter key to exit...") + except EOFError: + pass + sys.exit(1) + +print(save_log(f"\nUsing Godot Source Root: {godot_root}")) +confirm = input(f"\n\n ⚠ {LogColors.WARNING}Start Godot Secure Operations on Godot Source Root {LogColors.ENDC}{LogColors.FAIL}(y/n)?{LogColors.ENDC}: ").strip().lower() +if not (confirm == 'y' or confirm == 'yes'): + print(save_log("Closing Setup...")) + try: + exit = input("\nPress Enter key to exit...") + except EOFError: + pass + sys.exit(1) + +save_log(f"Start Godot Secure Operations on Godot Source Root (y/n)?: {confirm}") + +confirm = input(f"\n\n ℹ {LogColors.OKBLUE}Use Custom Headers {LogColors.ENDC}{LogColors.FAIL}(y/n)?{LogColors.ENDC}: ").strip().lower() +save_log(f"\n[INFO] - Use Custom Headers (y/n)?: {confirm}") +if (confirm == 'y' or confirm == 'yes'): + baseTag = input(" Enter Custom Magic Header (e.g. GDPC): ").upper() + baseHeader = generate_magic_header(baseTag) + encTag = input(" Enter Custom Encrypted Magic Header (e.g. GDEC): ").upper() + encHeader = generate_magic_header(encTag) + save_log(f" Enter Custom Magic Header (e.g. GDPC): {baseTag}\n Enter Custom Encrypted Magic Header (e.g. GDEC): {encTag}") + +confirm = input(f"\n\n ℹ {LogColors.OKBLUE}Use Custom Token {LogColors.ENDC}{LogColors.FAIL}(y/n)?{LogColors.ENDC}: ").strip().lower() +save_log(f"\n[INFO] - Use Custom Token (y/n)?: {confirm}") +if (confirm == 'y' or confirm == 'yes'): + token_hex = str(input(" Enter Custom Security Token: ")).lower() + security_token = hex_to_bytes(token_hex) + token_c_array = ', '.join([f'0x{b:02X}' for b in security_token]) + save_log(f" Enter Custom Security Token: {token_hex}") + +confirm = input(f"\n\n ℹ {LogColors.OKBLUE}Use Advanced Key Derivation {LogColors.ENDC}{LogColors.FAIL}(y/n)?{LogColors.ENDC}: ").strip().lower() +save_log(f"\n[INFO] - Use Advanced Key Derivation (y/n)?: {confirm}") +if (confirm == 'y' or confirm == 'yes'): + key_derivation_algorithm = build_random_key_derivation() + save_log(f" Generated Advanced Key Derivation Algorithm:\n {key_derivation_algorithm}") + +# Modifications to be made in source +MODIFICATIONS = [ + #Pre -Steps: + { + "file": "version.py", + "operations": [ + { + "type": "replace_line", + "description": "Modify Godot title To add Godot Secure", + "find": "name = \"Godot Engine\"", + "replace": "name = \"Godot Engine (With Godot Secure)\"" + } + ] + }, + + { + "file": "editor/export/project_export.cpp", + "operations": [ + { + "type": "replace_line", + "description": "Modify Godot export popup title To add Godot Secure", + "find": "set_title(TTR(\"Export\"));", + "replace": "set_title(TTR(\"Export With Godot Secure (AES-256)\"));" + } + ] + }, + + # Step 0: Create security token header + { + "file": "core/crypto/security_token.h", + "operations": [ + { + "type": "create_file", + "description": "Create security token header", + "content": [ + "#ifndef SECURITY_TOKEN_H", + "#define SECURITY_TOKEN_H", + "", + "#include \"core/typedefs.h\"", + "", + "namespace Security {", + f" //Security Token: {token_hex}", + f" static const uint8_t TOKEN[32] = {{ {token_c_array} }};", + "};", + "", + "#endif // SECURITY_TOKEN_H" + ] + } + ] + }, + # Step 1: Magic Header Modification (Packed) + { + "file": "core/io/file_access_pack.h", + "operations": [ + { + "type": "replace_line", + "description": "Modify Packed File Header Magic", + "find": "#define PACK_HEADER_MAGIC 0x43504447", + "replace": f"#define PACK_HEADER_MAGIC {baseHeader} // Generated Tag: \"{baseTag}\"" + } + ] + }, + # Step 2: Magic Header Modification (Encrypted) + { + "file": "core/io/file_access_encrypted.h", + "operations": [ + { + "type": "replace_line", + "description": "Modify Encrypted File Header Magic", + "find": "#define ENCRYPTED_HEADER_MAGIC 0x43454447", + "replace": f"#define ENCRYPTED_HEADER_MAGIC {encHeader} // Generated Tag: \"{encTag}\"" + } + ] + }, + # Step 3: Modify AES Decryption + Token Integration + { + "file": "core/io/file_access_encrypted.cpp", + "operations": [ + { + "type": "insert_after", + "description": "Include security token header", + "find": "#include \"file_access_encrypted.h\"", + "replace": "#include \"core/crypto/security_token.h\"" + }, + { + "type": "replace_block", + "description": "Add token obfuscation for decryption", + "find": [ + "{", + "CryptoCore::AESContext ctx;", + "", + "ctx.set_encode_key(key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption!", + "ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw());", + "}" + ], + "replace": [ + "{", + "CryptoCore::AESContext ctx;", + "", + " // Apply security token to key", + " Vector<uint8_t> token_key;", + " token_key.resize(32);", + " const uint8_t *key_ptr = key.ptr();", + " for (int i = 0; i < 32; i++) {", + f" {key_derivation_algorithm}", + " }", + "", + " ctx.set_encode_key(token_key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption!", + " ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw());", + "}" + ] + } + ] + }, + # Step 4: Modify AES Encryption + Token Integration + { + "file": "core/io/file_access_encrypted.cpp", + "operations": [ + { + "type": "replace_block", + "description": "Add token obfuscation for encryption", + "find": [ + "CryptoCore::AESContext ctx;", + "ctx.set_encode_key(key.ptrw(), 256);", + "", + "if (use_magic) {", + " file->store_32(ENCRYPTED_HEADER_MAGIC);", + "}", + "", + "file->store_buffer(hash, 16);", + "file->store_64(data.size());", + "file->store_buffer(iv.ptr(), 16);", + "", + "ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptr(), compressed.ptr());" + ], + "replace": [ + "CryptoCore::AESContext ctx;", + "", + " // Apply security token to key", + " Vector<uint8_t> token_key;", + " token_key.resize(32);", + " const uint8_t *key_ptr = key.ptr();", + " for (int i = 0; i < 32; i++) {", + f" {key_derivation_algorithm}", + " }", + "", + " ctx.set_encode_key(token_key.ptrw(), 256);", + "", + "if (use_magic) {", + "file->store_32(ENCRYPTED_HEADER_MAGIC);", + "}", + "", + "file->store_buffer(hash, 16);", + "file->store_64(data.size());", + "file->store_buffer(iv.ptr(), 16);", + "", + "ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptr(), compressed.ptr());" + ] + } + ] + } +] + +def apply_modifications(root_dir): + print_info(f"Generated PACK_HEADER_MAGIC : {baseHeader} //Tag : {baseTag}") + print_info(f"Generated ENCRYPTED_HEADER_MAGIC : {encHeader} //Tag : {encTag}") + print_info(f"Security Token: {token_hex}") + + step = 0 + for mod in MODIFICATIONS: + file_path = os.path.join(root_dir, mod["file"]) + step += 1 + + # Handle file creation separately + if any(op.get("type") == "create_file" for op in mod["operations"]): + print_info(f"Step {step} (Creating: {file_path}):") + for op in mod["operations"]: + if op["type"] == "create_file": + print_operation(f"Operation: {op['description']}") + os.makedirs(os.path.dirname(file_path), exist_ok=True) + + if os.path.exists(file_path): + print_warning(f"File already exists: {file_path}") + choice = input(" Do you want to overwrite it? (y/n): ").strip().lower() + if not (choice == 'y' or choice == 'yes'): + global fileCreated + print_operation("Skipping file creation.") + fileCreated = False + continue + + # Backup existing file + global backup_path + backup_path = file_path + ".backup" + try: + os.replace(file_path, backup_path) + print_operation(f"Backup created at: {backup_path}") + except Exception as e: + print_error(f"Failed to create backup: {e}") + print_operation("Skipping file creation.") + fileCreated = False + continue + + try: + with open(file_path, "w") as f: + content = op["content"] + if isinstance(content, list): + content = "\n".join(content) + f.write(content) + print_success(f"File created: {file_path}") + except Exception as e: + print_error(f"Failed to write file: {e}") + continue + + + # Handle file modifications + if not os.path.exists(file_path): + print_error(f"File not found: {file_path}") + continue + + print_info(f"Step {step} (Processing: {file_path}):") + + with open(file_path, "r") as f: + lines = f.readlines() + + modified = False + for op in mod["operations"]: + op_type = op["type"] + description = op.get("description", "") + print_operation(f"Operation: {description}. (Type: {op_type})") + + if op_type == "replace_line": + find = op["find"].strip() + replace = op["replace"] + "\n" + found = False + + for i in range(len(lines)): + if lines[i].strip() == find: + lines[i] = replace + print_success(f"Line replaced at line {i+1}") + found = True + modified = True + break + + if not found: + print_error(f"Target line not found: {find}") + + elif op_type == "replace_block": + find_lines = [ln.strip() for ln in op["find"]] + replace_lines = [ln + "\n" for ln in op["replace"]] + block_found = False + + for i in range(len(lines) - len(find_lines) + 1): + match = True + for j in range(len(find_lines)): + if lines[i + j].strip() != find_lines[j]: + match = False + break + if match: + lines[i:i + len(find_lines)] = replace_lines + print_success(f"Block replaced starting at line {i+1}") + modified = True + block_found = True + break + + if not block_found: + print_error("Target block not found") + + elif op_type == "insert_after": + find = op["find"].strip() + replace_lines = [ln + "\n" for ln in op["replace"]] if isinstance(op["replace"], list) else [op["replace"] + "\n"] + found = False + + for i in range(len(lines)): + if lines[i].strip() == find: + # Check if replacement already exists + already_present = True + for j, rep_line in enumerate(replace_lines): + if i + 1 + j >= len(lines) or lines[i + 1 + j] != rep_line: + already_present = False + break + + if not already_present: + lines[i+1:i+1] = replace_lines + print_success(f"Inserted after line {i+1}") + modified = True + else: + print_success("Content already present, skipping insertion") + found = True + break + + if not found: + print_error(f"Insertion point not found: {find}") + + elif op_type == "append": + replace_lines = [ln + "\n" for ln in op["replace"]] + already_present = False + + # Check if the ending lines match + if len(lines) >= len(replace_lines): + already_present = all( + lines[-len(replace_lines) + i] == replace_lines[i] + for i in range(len(replace_lines)) + ) + + if not already_present: + lines.extend(replace_lines) + print_success("Appended to end of file") + modified = True + else: + print_success("Content already present at end, skipping append") + + if modified: + with open(file_path, "w") as f: + f.writelines(lines) + print_success(f"File updated: {file_path}") + else: + print_warning(f"No changes made to file (Step {step})") + +if __name__ == "__main__": + log = save_log("\n=== Applying Enhanced AES Encryption For Godot ===") + print(f"\n\n{LogColors.HEADER}{log}{LogColors.ENDC}") + apply_modifications(godot_root) + print(f"\n{LogColors.HEADER}=== Operation Complete (View Logs For Info) ==={LogColors.ENDC}\n") + if fileCreated == True: + print(f"{LogColors.BOLD} Security Token:{LogColors.ENDC} {token_hex}\n") + print(f"{LogColors.WARNING} Encryption Key: {LogColors.FAIL}{encKey}{LogColors.ENDC}") + print_warning(f"{LogColors.WARNING} Security Token and Encryption Key are different. Use {LogColors.FAIL}\"Encryption Key\"{LogColors.WARNING} During Export!{LogColors.ENDC}") + print_success(f"{LogColors.OKGREEN} Build is now Cryptographically Unique{LogColors.ENDC}") + save_log(f"\nSecurity Token: {token_hex}\nEncryption Key: {encKey}") + save_log(f"\n[WARN] - Security Token and Encryption Key are different. Use Encryption Key During Export!") + if not (backup_path == None): + save_log(f"\n[INFO] - Old Key Backup Created at: {backup_path}") + print_info(f"{LogColors.OKGREEN} Old Key Backup Created at: {LogColors.ENDC}{LogColors.BOLD}{backup_path}{LogColors.ENDC}\n") + + try: + exit = input("\nPress Enter key to exit...") + except EOFError: + pass + sys.exit(1) diff --git a/Log-2026-08-21_11-43-23-973182-Godot-Secure-AES.txt b/Log-2026-08-21_11-43-23-973182-Godot-Secure-AES.txt new file mode 100644 index 0000000000..c6d6bc9862 --- /dev/null +++ b/Log-2026-08-21_11-43-23-973182-Godot-Secure-AES.txt @@ -0,0 +1,8 @@ +Created On - 2026-08-21_11-43-23-973182 +This is Godot-Secure Log file, SAVE IT to secure place for later getting values. + + +Using Godot Source Root: /var/lib/git/godot +Start Godot Secure Operations on Godot Source Root (y/n)?: y + +[INFO] - Use Custom Headers (y/n)?: y diff --git a/Log-2026-08-21_11-43-45-886657-Godot-Secure-AES.txt b/Log-2026-08-21_11-43-45-886657-Godot-Secure-AES.txt new file mode 100644 index 0000000000..567d56a226 --- /dev/null +++ b/Log-2026-08-21_11-43-45-886657-Godot-Secure-AES.txt @@ -0,0 +1,8 @@ +Created On - 2026-08-21_11-43-45-886657 +This is Godot-Secure Log file, SAVE IT to secure place for later getting values. + + +Using Godot Source Root: /var/lib/git/godot +Start Godot Secure Operations on Godot Source Root (y/n)?: y + +[INFO] - Use Custom Headers (y/n)?: n diff --git a/Log-2026-08-21_11-44-08-879220-Godot-Secure-AES.txt b/Log-2026-08-21_11-44-08-879220-Godot-Secure-AES.txt new file mode 100644 index 0000000000..979554692d --- /dev/null +++ b/Log-2026-08-21_11-44-08-879220-Godot-Secure-AES.txt @@ -0,0 +1,8 @@ +Created On - 2026-08-21_11-44-08-879220 +This is Godot-Secure Log file, SAVE IT to secure place for later getting values. + + +Using Godot Source Root: /var/lib/git/godot +Start Godot Secure Operations on Godot Source Root (y/n)?: y + +[INFO] - Use Custom Headers (y/n)?: y diff --git a/Log-2026-08-21_11-44-50-030431-Godot-Secure-AES.txt b/Log-2026-08-21_11-44-50-030431-Godot-Secure-AES.txt new file mode 100644 index 0000000000..ae38d87766 --- /dev/null +++ b/Log-2026-08-21_11-44-50-030431-Godot-Secure-AES.txt @@ -0,0 +1,8 @@ +Created On - 2026-08-21_11-44-50-030431 +This is Godot-Secure Log file, SAVE IT to secure place for later getting values. + + +Using Godot Source Root: /var/lib/git/godot +Start Godot Secure Operations on Godot Source Root (y/n)?: y + +[INFO] - Use Custom Headers (y/n)?: y diff --git a/Log-2026-08-21_11-45-07-074435-Godot-Secure-AES.txt b/Log-2026-08-21_11-45-07-074435-Godot-Secure-AES.txt new file mode 100644 index 0000000000..1be498ffa7 --- /dev/null +++ b/Log-2026-08-21_11-45-07-074435-Godot-Secure-AES.txt @@ -0,0 +1,12 @@ +Created On - 2026-08-21_11-45-07-074435 +This is Godot-Secure Log file, SAVE IT to secure place for later getting values. + + +Using Godot Source Root: /var/lib/git/godot +Start Godot Secure Operations on Godot Source Root (y/n)?: y + +[INFO] - Use Custom Headers (y/n)?: y + Enter Custom Magic Header (e.g. GDPC): PJEF + Enter Custom Encrypted Magic Header (e.g. GDEC): BHEQ + +[INFO] - Use Custom Token (y/n)?: y diff --git a/Log-2026-08-21_11-45-37-736396-Godot-Secure-AES.txt b/Log-2026-08-21_11-45-37-736396-Godot-Secure-AES.txt new file mode 100644 index 0000000000..b0cf0b9f28 --- /dev/null +++ b/Log-2026-08-21_11-45-37-736396-Godot-Secure-AES.txt @@ -0,0 +1,68 @@ +Created On - 2026-08-21_11-45-37-736396 +This is Godot-Secure Log file, SAVE IT to secure place for later getting values. + + +Using Godot Source Root: /var/lib/git/godot +Start Godot Secure Operations on Godot Source Root (y/n)?: y + +[INFO] - Use Custom Headers (y/n)?: y + Enter Custom Magic Header (e.g. GDPC): PJEF + Enter Custom Encrypted Magic Header (e.g. GDEC): BHEQ + +[INFO] - Use Custom Token (y/n)?: y + Enter Custom Security Token: 762834 + +[INFO] - Use Advanced Key Derivation (y/n)?: y + Generated Advanced Key Derivation Algorithm: + token_key.write[i] = (uint8_t)(((((((((Security::TOKEN[i] ^ key_ptr[i]) + key_ptr[i]) ^ Security::TOKEN[i]) + 219) ^ key_ptr[i]) + 135) ^ key_ptr[i]) + 121)); + +=== Applying Enhanced AES Encryption For Godot === + +[INFO] - Generated PACK_HEADER_MAGIC : 0x46454A50 //Tag : PJEF + +[INFO] - Generated ENCRYPTED_HEADER_MAGIC : 0x51454842 //Tag : BHEQ + +[INFO] - Security Token: 762834 + +[INFO] - Step 1 (Processing: /var/lib/git/godot/version.py): + [=>] Operation: Modify Godot title To add Godot Secure. (Type: replace_line) + [✓] Line replaced at line 2 + [✓] File updated: /var/lib/git/godot/version.py + +[INFO] - Step 2 (Processing: /var/lib/git/godot/editor/export/project_export.cpp): + [=>] Operation: Modify Godot export popup title To add Godot Secure. (Type: replace_line) + [✗] Target line not found: set_title(TTR("Export")); + + +[WARN] - No changes made to file (Step 2) + +[INFO] - Step 3 (Creating: /var/lib/git/godot/core/crypto/security_token.h): + [=>] Operation: Create security token header + [✓] File created: /var/lib/git/godot/core/crypto/security_token.h + +[INFO] - Step 4 (Processing: /var/lib/git/godot/core/io/file_access_pack.h): + [=>] Operation: Modify Packed File Header Magic. (Type: replace_line) + [✓] Line replaced at line 41 + [✓] File updated: /var/lib/git/godot/core/io/file_access_pack.h + +[INFO] - Step 5 (Processing: /var/lib/git/godot/core/io/file_access_encrypted.h): + [=>] Operation: Modify Encrypted File Header Magic. (Type: replace_line) + [✓] Line replaced at line 36 + [✓] File updated: /var/lib/git/godot/core/io/file_access_encrypted.h + +[INFO] - Step 6 (Processing: /var/lib/git/godot/core/io/file_access_encrypted.cpp): + [=>] Operation: Include security token header. (Type: insert_after) + [✓] Inserted after line 31 + [=>] Operation: Add token obfuscation for decryption. (Type: replace_block) + [✓] Block replaced starting at line 102 + [✓] File updated: /var/lib/git/godot/core/io/file_access_encrypted.cpp + +[INFO] - Step 7 (Processing: /var/lib/git/godot/core/io/file_access_encrypted.cpp): + [=>] Operation: Add token obfuscation for encryption. (Type: replace_block) + [✓] Block replaced starting at line 165 + [✓] File updated: /var/lib/git/godot/core/io/file_access_encrypted.cpp + +Security Token: 762834 +Encryption Key: f2d2fe537ce75c61062dadaf3fa6647b494cba92623661b12485944d02598aa7 + +[WARN] - Security Token and Encryption Key are different. Use Encryption Key During Export! diff --git a/core/crypto/security_token.h b/core/crypto/security_token.h new file mode 100644 index 0000000000..a08aad95bf --- /dev/null +++ b/core/crypto/security_token.h @@ -0,0 +1,11 @@ +#ifndef SECURITY_TOKEN_H +#define SECURITY_TOKEN_H + +#include "core/typedefs.h" + +namespace Security { + //Security Token: 762834 + static const uint8_t TOKEN[32] = { 0x76, 0x28, 0x34 }; +}; + +#endif // SECURITY_TOKEN_H
\ No newline at end of file diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 270b3dcdda..351b7d6e3e 100755 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "file_access_encrypted.h" +#include "core/crypto/security_token.h" #include "core/variant/variant.h" @@ -98,12 +99,20 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u uint64_t blen = p_base->get_buffer(data.ptrw(), ds); ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT); - { - CryptoCore::AESContext ctx; +{ +CryptoCore::AESContext ctx; - ctx.set_encode_key(key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption! - ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw()); - } + // Apply security token to key + Vector<uint8_t> token_key; + token_key.resize(32); + const uint8_t *key_ptr = key.ptr(); + for (int i = 0; i < 32; i++) { + token_key.write[i] = (uint8_t)(((((((((Security::TOKEN[i] ^ key_ptr[i]) + key_ptr[i]) ^ Security::TOKEN[i]) + 219) ^ key_ptr[i]) + 135) ^ key_ptr[i]) + 121)); + } + + ctx.set_encode_key(token_key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption! + ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw()); +} data.resize(length); @@ -153,18 +162,27 @@ void FileAccessEncrypted::_close() { memcpy(compressed.ptr(), data.ptr(), data.size()); memset(compressed.ptr() + data.size(), 0, len - data.size()); - CryptoCore::AESContext ctx; - ctx.set_encode_key(key.ptrw(), 256); +CryptoCore::AESContext ctx; - if (use_magic) { - file->store_32(ENCRYPTED_HEADER_MAGIC); - } + // Apply security token to key + Vector<uint8_t> token_key; + token_key.resize(32); + const uint8_t *key_ptr = key.ptr(); + for (int i = 0; i < 32; i++) { + token_key.write[i] = (uint8_t)(((((((((Security::TOKEN[i] ^ key_ptr[i]) + key_ptr[i]) ^ Security::TOKEN[i]) + 219) ^ key_ptr[i]) + 135) ^ key_ptr[i]) + 121)); + } + + ctx.set_encode_key(token_key.ptrw(), 256); + +if (use_magic) { +file->store_32(ENCRYPTED_HEADER_MAGIC); +} - file->store_buffer(hash, 16); - file->store_64(data.size()); - file->store_buffer(iv.ptr(), 16); +file->store_buffer(hash, 16); +file->store_64(data.size()); +file->store_buffer(iv.ptr(), 16); - ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptr(), compressed.ptr()); +ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptr(), compressed.ptr()); file->store_buffer(compressed.ptr(), compressed.size()); data.clear(); diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index 304b939372..a084d116a9 100755 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -33,7 +33,7 @@ #include "core/crypto/crypto_core.h" #include "core/io/file_access.h" -#define ENCRYPTED_HEADER_MAGIC 0x43454447 +#define ENCRYPTED_HEADER_MAGIC 0x51454842 // Generated Tag: "BHEQ" class FileAccessEncrypted : public FileAccess { GDSOFTCLASS(FileAccessEncrypted, FileAccess); diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 490778f203..d037c497a0 100755 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -38,7 +38,7 @@ #include "core/templates/list.h" // Godot's packed file magic header ("GDPC" in ASCII). -#define PACK_HEADER_MAGIC 0x43504447 +#define PACK_HEADER_MAGIC 0x46454A50 // Generated Tag: "PJEF" #define PACK_FORMAT_VERSION_V2 2 #define PACK_FORMAT_VERSION_V3 3 diff --git a/version.py b/version.py index 4b0e55c61b..d08276b190 100755 --- a/version.py +++ b/version.py @@ -1,5 +1,5 @@ short_name = "godot" -name = "Godot Engine" +name = "Godot Engine (With Godot Secure)" major = 4 minor = 7 patch = 2 |
