Skip to content

Commit 566d91f

Browse files
committed
Refactor character shifting logic into reusable function
Extracted character shifting into a reusable PHP function to reduce code duplication and improve clarity. Updated both key obfuscation and decryption logic to use the new function. Added detailed documentation for Java methods demonstrating encryption and decryption processes.
1 parent 2641871 commit 566d91f

File tree

1 file changed

+86
-33
lines changed

1 file changed

+86
-33
lines changed

index.php

Lines changed: 86 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
/**
33
* Jummania.php
44
*
5-
* Replicates the Java Jummania class in PHP:
6-
* 1. Generates an AES-128 key, encodes it without padding, shifts each char +1
7-
* 2. Reverses that to recover the raw key
8-
* 3. Encrypts a URL with AES/ECB/PKCS5Padding, Base64-encodes it, then shifts each char −1
9-
* 4. Shifts back +1, Base64-decodes, and decrypts to recover the original URL
5+
* A PHP implementation that mirrors the functionality of the Java `Jummania` class.
6+
*
7+
* Features:
8+
* 1. Generates a 128-bit AES key, Base64-encodes it (without padding), and shifts each character by +1.
9+
* 2. Reverses the obfuscation to recover the raw key by shifting characters by -1 and Base64-decoding.
10+
* 3. Encrypts a URL using AES/ECB/PKCS5Padding, Base64-encodes the result, and shifts each character by -1.
11+
* 4. To decrypt, shifts characters back by +1, Base64-decodes, and decrypts to retrieve the original URL.
12+
*
13+
* Author: Jummania
14+
* Date: 2024-05-14
15+
* Email: sharifuddinjumman@gmail.com
16+
* Location: Dhaka, Bangladesh
1017
*/
1118

1219

@@ -35,29 +42,25 @@
3542
// 1. Generate a lightweight AES-128 key (16 raw bytes)
3643
$base64Key = rtrim(base64_encode(random_bytes(16)), '=');
3744

38-
// 2. Obfuscate the key: shift each character by +1
39-
$encKeyChars = '';
40-
for ($i = 0, $l = strlen($base64Key); $i < $l; $i++) {
41-
$encKeyChars .= chr(ord($base64Key[$i]) + 1);
42-
}
43-
44-
// 3. Function to reverse key obfuscation
45-
function getSecretKey(string $keyStr): string
45+
// 2. Reusable function to shift characters
46+
function shiftChars(string $input, int $shift): string
4647
{
47-
$decoded = '';
48-
for ($i = 0, $l = strlen($keyStr); $i < $l; $i++) {
49-
$decoded .= chr(ord($keyStr[$i]) - 1);
48+
$output = '';
49+
for ($i = 0, $l = strlen($input); $i < $l; $i++) {
50+
$output .= chr(ord($input[$i]) + $shift);
5051
}
51-
return base64_decode($decoded);
52+
return $output;
5253
}
5354

54-
$secretKey = getSecretKey($encKeyChars);
55+
// 2. Obfuscate the key: shift each character by +1
56+
$encKeyChars = shiftChars($base64Key, +1);
57+
$secretKey = base64_decode(shiftChars($encKeyChars, -1));
5558

5659
// 4. Encrypt the text and shift each char by -1
5760
function encryptShift(string $plainText, string $key): string
5861
{
5962
$encrypted = openssl_encrypt($plainText, 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
60-
$b64 = base64_encode($encrypted);
63+
$b64 = rtrim(base64_encode($encrypted), '=');
6164

6265
$shifted = '';
6366
for ($i = 0, $l = strlen($b64); $i < $l; $i++) {
@@ -68,34 +71,84 @@ function encryptShift(string $plainText, string $key): string
6871

6972
$shiftedEnc = encryptShift($string, $secretKey);
7073

71-
74+
$created = date("d/n/y");
7275
$javaCode = <<<JAVA
76+
/**
77+
* The {@code Jummania} class demonstrates AES encryption key reconstruction and
78+
* decryption of a string that was obfuscated using character shifting and Base64 encoding.
79+
* <p>
80+
* This is an example of lightweight obfuscation layered on top of symmetric encryption,
81+
* suitable for scenarios where additional obscurity is desired beyond encryption.
82+
*
83+
* <p><b>Note:</b> This code is for educational or internal use only and not recommended for
84+
* production-grade cryptographic implementations.
85+
*
86+
* <p><b>Created by:</b> Jummania
87+
* <br><b>Date:</b> $created
88+
* <br><b>Email:</b> sharifuddinjumman@gmail.com
89+
* <br><b>Location:</b> Dhaka, Bangladesh
90+
*/
7391
public class Jummania {
74-
public static String getString() {
92+
93+
94+
/**
95+
* Retrieves the decrypted original string using a hardcoded encrypted text and secret key.
96+
* <p>
97+
* This method internally constructs a {@link javax.crypto.SecretKey} from a predefined obfuscated Base64 key string,
98+
* and then decrypts a predefined obfuscated and Base64-encoded string using that key.
99+
*
100+
* @return the decrypted original string
101+
* @throws Exception if any error occurs during key reconstruction or decryption
102+
*/
103+
public static String getString() throws Exception {
75104
javax.crypto.SecretKey secretKey = getSecretKey("$encKeyChars");
76105
return getString(secretKey, "$shiftedEnc");
77106
}
78107
79-
public static javax.crypto.SecretKey getSecretKey(String key) {
108+
109+
/**
110+
* Converts an obfuscated Base64-encoded AES key string into a SecretKey object.
111+
* The input string is shifted by -1 on each character before Base64 decoding.
112+
*
113+
* @param key The obfuscated Base64-encoded AES key string
114+
* @return SecretKey instance for AES algorithm
115+
*/
116+
public javax.crypto.SecretKey getSecretKey(String key) {
80117
String string = shiftChars(key, -1);
81118
byte[] decodedKey = java.util.Base64.getDecoder().decode(string);
82119
return new javax.crypto.spec.SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
83120
}
84121
85-
public static String getString(javax.crypto.SecretKey secretKey, String encryptedText) {
86-
try {
87-
String string = shiftChars(encryptedText, 1);
88-
java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
89-
byte[] encryptedTextByte = decoder.decode(string);
90-
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES");
91-
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey);
92-
return new String(cipher.doFinal(encryptedTextByte));
93-
} catch (Exception e) {
94-
return null;
95-
}
96122
123+
/**
124+
* Decrypts an encrypted Base64-encoded string using the provided AES secret key.
125+
* <p>
126+
* The input string is first character-shifted (each character increased by 1),
127+
* then decoded from Base64, and finally decrypted using AES.
128+
*
129+
* @param secretKey the AES {@link javax.crypto.SecretKey} used for decryption
130+
* @param encryptedText the obfuscated and Base64-encoded string to decrypt
131+
* @return the original plain text after decryption
132+
* @throws Exception if any decryption step fails (e.g., decoding, cipher initialization, or decryption)
133+
*/
134+
public static String getString(javax.crypto.SecretKey secretKey, String encryptedText) throws Exception {
135+
String string = shiftChars(encryptedText, 1);
136+
java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
137+
byte[] encryptedTextByte = decoder.decode(string);
138+
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES");
139+
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey);
140+
return new String(cipher.doFinal(encryptedTextByte));
97141
}
98142
143+
144+
/**
145+
* Applies a character-wise shift to each character in the input string.
146+
* For each character c, returns (char)(c + shift).
147+
*
148+
* @param input The input string to be shifted
149+
* @param shift The integer shift to apply (positive or negative)
150+
* @return The shifted string after applying the character shift
151+
*/
99152
public static String shiftChars(String input, int shift) {
100153
StringBuilder result = new StringBuilder();
101154
for (char c : input.toCharArray()) {

0 commit comments

Comments
 (0)