Skip to content

Commit 82e6d73

Browse files
committed
Added PHP script that can decrypt data generated by Consturct 3's Cryptography plugin
1 parent 49ddb64 commit 82e6d73

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
// This script attempts to decrypt an urlencoded & base64 encoded string that
4+
// was generated using Construct 3's Cryptography plugin using password-based
5+
// AES 256 encryption.
6+
// The decrypt_c3_aes_gcm function takes a base64 encoded string as an input.
7+
// The script expects the payload in the "data" GET parameter; since base64
8+
// strings are not URL safe, the payload must be urlencoded as well.
9+
10+
define('PASSWORD', 'hackerman'); // enter the same password you specified in C3
11+
12+
function decrypt_c3_aes_gcm($encrypted_base64, $password) {
13+
14+
// Base64 decode the input
15+
$encrypted_data = base64_decode($encrypted_base64);
16+
17+
if ($encrypted_data === false) {
18+
return false; // Return false if Base64 decoding fails
19+
}
20+
21+
// Extract parts from the binary data based on the format described here:
22+
// https://www.construct.net/en/make-games/manuals/construct-3/plugin-reference/cryptography#internalH1Link4
23+
24+
$reserved = ord($encrypted_data[0]); // Reserved byte (should be 0)
25+
$salt = substr($encrypted_data, 1, 16); // Salt (16 bytes)
26+
$iv = substr($encrypted_data, 17, 12); // Initialization Vector (12 bytes)
27+
$iterations = unpack('N', substr($encrypted_data, 29, 4))[1]; // Iterations (4 bytes, uint32)
28+
$ciphertext = substr($encrypted_data, 33); // Ciphertext starts from byte 33 onwards
29+
// Validate the reserved byte is zero
30+
if ($reserved !== 0) {
31+
return false; // Invalid format (reserved byte is not 0)
32+
}
33+
34+
// Derive the encryption key using PBKDF2 with the provided password, salt, and iterations
35+
$key = hash_pbkdf2('sha256', $password, $salt, $iterations, 32, true); // 256-bit (32-byte) key
36+
// Separate the encrypted payload and the GCM authentication tag
37+
$tag = substr($ciphertext, -16); // GCM authentication tag (16 bytes at the end)
38+
$encrypted_payload = substr($ciphertext, 0, -16); // Encrypted data (without tag)
39+
// Decrypt the payload
40+
$decrypted_data = openssl_decrypt(
41+
$encrypted_payload, // Ciphertext
42+
'aes-256-gcm', // Cipher method
43+
$key, // Key derived from password
44+
OPENSSL_RAW_DATA, // Output raw data
45+
$iv, // Initialization vector (IV)
46+
$tag // GCM tag
47+
);
48+
49+
// Return the decrypted text if successful, or false if decryption failed
50+
return $decrypted_data !== false ? $decrypted_data : false;
51+
}
52+
53+
// Get the encrypted data from the "data" GET parameter and urldecode it
54+
$encrypted_data_base64 = urldecode(filter_input(INPUT_GET, 'data'));
55+
56+
// Try to decrypt the data
57+
$decrypted_text = decrypt_c3_aes_gcm($encrypted_data_base64, PASSWORD);
58+
59+
if ($decrypted_text !== false) {
60+
echo 'Decrypted Text: ' . $decrypted_text;
61+
} else {
62+
echo 'Decryption failed!';
63+
}

0 commit comments

Comments
 (0)