-
-
Save xricsz/721aee21c306d4d90041c8c1aebd9444 to your computer and use it in GitHub Desktop.
XXTEA Class Encry/Decrypt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace Skillerm.Controller | |
{ | |
/** | |
* XXTEA_Decrypt | |
* @author Skillerm<CastroMS> | |
* @discord CastroMS#3430 | |
* @mail [email protected] | |
* 2022/12/18 | |
*/ | |
internal class XXTEA_Decrypt | |
{ | |
uint DELTA = 0x9e3779B9; | |
/** | |
* InicializationDecrypt | |
* | |
*/ | |
public byte[] InicializationDecrypt(byte[] data, uint data_len, byte[] key, uint key_len, out uint ret_length) | |
{ | |
// Initialize the return length to 0 | |
ret_length = 0; | |
// If the key length is less than 0x10 (16), fix the key length by adding 0s to the end of the key | |
// Otherwise, use the original key | |
byte[] fixed_key = (key_len < 0x10) ? this.fix_key_length(key, key_len) : key; | |
// Decrypt the data using the fixed key and return the decrypted data | |
// Also, set the return length to the length of the decrypted data | |
byte[] decryptedData = this.XXTEA_Decry(data, data_len, fixed_key, out ret_length); | |
return decryptedData; | |
} | |
private byte[] XXTEA_Decry(byte[] data, uint len, byte[] key, out uint ret_len) | |
{ | |
// Convert the data and key into arrays of unsigned integers | |
uint[] v = this.XXTEA_LongArray(data, len, 0, out uint num); | |
uint[] k = this.XXTEA_LongArray(key, 0x10, 0, out _); | |
// Decrypt the data using the key | |
this.XXTEA_Decry_Long(ref v, num, ref k); | |
// Convert the decrypted data back into a byte array and set the return length to the length of the decrypted data | |
return this.XXTEA_ByteArray(v, num, 1, out ret_len); | |
} | |
// This function creates a new array (fixed_key) of 16 bytes (0x10) and copies the contents of the input array (key) | |
// into it, up to a maximum of "key_len" bytes. | |
private byte[] fix_key_length(byte[] key, uint key_len) | |
{ | |
// Initialize a new array of 16 bytes | |
byte[] fixed_key = new byte[0x10]; | |
// Copy the contents of the input array (key) into the new array (fixed_key), up to a maximum of "key_len" bytes | |
Array.Copy(key, fixed_key, (long)key_len); | |
// Return the new array | |
return fixed_key; | |
} | |
// This function decrypts an array of 32-bit unsigned integers (v) of length "len" | |
// using the key (k) provided. | |
private void XXTEA_Decry_Long(ref uint[] v, uint len, ref uint[] k) | |
{ | |
// Initialize the index to the last element in the array | |
uint index = len - 1; | |
// Initialize num2 to the last element in the array | |
uint num2 = v[index]; | |
// Initialize num3 to the first element in the array | |
uint num3 = v[0]; | |
// Initialize num6 to a constant value that is used in the decryption process | |
uint num6 = (uint)((6 + (0x34 / (index + 1))) * -1_640_531_527); | |
// Continue decrypting until num6 is 0 | |
while (num6 != 0) | |
{ | |
// Calculate the value of num7, which is used in the decryption process | |
uint num7 = (num6 >> 2) & 3; | |
// Initialize num4 to the value of index | |
uint num4 = index; | |
// Continue decrypting until num4 is 0 | |
while (num4 != 0) | |
{ | |
// Set num2 to the element in the array at the previous index | |
num2 = v[((int)num4) - 1]; | |
// Decrypt the current element in the array (num4) by using the previous element (num2) | |
// and the current element (num3) in the decryption process | |
num3 = v[num4] -= (((num2 >> 5) ^ (num3 << 2)) + ((num3 >> 3) ^ (num2 << 4))) ^ ((num6 ^ num3) + (k[(num4 & 3) ^ num7] ^ num2)); | |
// Decrement num4 | |
num4--; | |
} | |
// Set num2 to the last element in the array | |
num2 = v[index]; | |
// Decrypt the first element in the array by using the last element (num2) | |
// and the current element (num3) in the decryption process | |
num3 = v[0] -= (((num2 >> 5) ^ (num3 << 2)) + ((num3 >> 3) ^ (num2 << 4))) ^ ((num6 ^ num3) + (k[(num4 & 3) ^ num7] ^ num2)); | |
// Decrement num6 | |
num6 -= this.DELTA; //0x9e3779b9 //0x464C457F | |
} | |
} | |
// This function converts an array of 32-bit unsigned integers (data) of length "len" | |
// into an array of bytes, and returns the resulting array. | |
// If "include_length" is set to 1, the length of the input array is included in the output. | |
// The length of the returned array is stored in the "ret_len" output parameter. | |
private byte[] XXTEA_ByteArray(uint[] data, uint len, int include_length, out uint ret_len) | |
{ | |
// Initialize ret_len to 0 | |
ret_len = 0; | |
// Calculate the length of the output array in bytes | |
uint num2 = len << 2; | |
// If include_length is set to 1, check if the last element in the input array | |
// contains the length of the array, and if so, set num2 to that value | |
if (include_length == 1) | |
{ | |
uint num3 = data[((int)len) - 1]; | |
if ((num3 >= (num2 - 7)) && (num3 <= (num2 - 4))) | |
{ | |
num2 = num3; | |
} | |
else | |
{ | |
// Return null if the last element in the input array does not contain the length of the array | |
return null; | |
} | |
} | |
// Initialize a new array of bytes with a length of num2 | |
byte[] buffer = new byte[num2]; | |
// Initialize the index to 0 | |
uint index = 0; | |
// Continue converting the input array to bytes until the index is equal to num2 | |
while (index < num2) | |
{ | |
// Convert the current element in the input array to a byte and store it in the output array | |
buffer[index] = (byte)((data[index >> 2] >> (((int)(index & 3) << 3) & 0x1f)) & 0xff); | |
// Increment the index | |
index++; | |
} | |
// Store the length of the output array in ret_len | |
ret_len = num2; | |
// Return the output array | |
return buffer; | |
} | |
// This function converts an array of bytes (data) of length "len" | |
// into an array of 32-bit unsigned integers, and returns the resulting array. | |
// If "include_length" is set to 1, the length of the input array is included in the output. | |
// The length of the returned array is stored in the "ret_len" output parameter. | |
private uint[] XXTEA_LongArray(byte[] data, uint len, int include_length, out uint ret_len) | |
{ | |
// Initialize an array of 32-bit unsigned integers | |
uint[] numArray; | |
// Calculate the number of 32-bit unsigned integers in the input array | |
uint index = len >> 2; | |
index = ((len & 3) == 0) ? index : (index + 1); | |
// If include_length is set to 1, initialize the array with an additional element to store the length of the input array | |
if (include_length != 1) | |
{ | |
numArray = new uint[index << 2]; | |
ret_len = index; | |
} | |
else | |
{ | |
numArray = new uint[(index + 1) << 2]; | |
numArray[index] = len; | |
ret_len = index + 1; | |
} | |
// Convert the input array to 32-bit unsigned integers and store them in the output array | |
for (uint i = 0; i < len; i += 4) | |
{ | |
numArray[i >> 2] = BitConverter.ToUInt32(data, (int)i); | |
} | |
// Return the output array | |
return numArray; | |
} | |
/** | |
* Encode Area | |
* ============================================================================ | |
*/ | |
public byte[] InicializationEncrypt(byte[] data, uint data_len, byte[] key, uint key_len, out uint ret_length) | |
{ | |
ret_length = 0; | |
byte[] fixed_key = (key_len < 0x10) ? this.fix_key_length(key, key_len) : key; | |
return this.XXTEAA_Encrypt(data, data_len, fixed_key, out ret_length); | |
} | |
private byte[] XXTEAA_Encrypt(byte[] data, uint len, byte[] key, out uint ret_len) | |
{ | |
uint[] v = this.XXTEA_LongArray(data, len, 1, out uint num); | |
uint[] k = this.XXTEA_LongArray(key, 0x10, 0, out _); | |
this.XXTEA_Encrypt_Long(ref v, num, ref k); | |
return this.XXTEA_ByteArray(v, num, 0, out ret_len); | |
} | |
// This function encrypts an array of 32-bit unsigned integers (v) of length "len" | |
// using the key (k) provided. | |
private void XXTEA_Encrypt_Long(ref uint[] v, uint len, ref uint[] k) | |
{ | |
// Initialize the index to the last element in the array | |
uint index = len - 1; | |
// Initialize num2 to the last element in the array | |
uint num2 = v[index]; | |
// Initialize num3 to the first element in the array | |
uint num3 = v[0]; | |
// Initialize num5 to a constant value that is used in the encryption process | |
uint num5 = 6 + (0x34 / (index + 1)); | |
// Initialize num6 to 0 | |
uint num6 = 0; | |
// If the length of the array is greater than or equal to 1, perform the encryption | |
if (index >= 1) | |
{ | |
// Encrypt the array num5 times | |
for (uint i = 0; i < num5; i++) | |
{ | |
// Increment num6 | |
num6 += this.DELTA; | |
// Encrypt each element in the array, except for the last element | |
for (uint j = 0; j < index; j++) | |
{ | |
// Set num3 to the element in the array at the next index | |
num3 = v[j + 1]; | |
// Encrypt the current element in the array (j) by using the next element (num3) | |
// and the current element (num2) in the encryption process | |
num2 = v[j] += (((num2 >> 5) ^ (num3 << 2)) + ((num3 >> 3) ^ (num2 << 4))) ^ ((num6 ^ num3) + (k[j & 3] ^ num2)); | |
} | |
// Set num3 to the first element in the array | |
num3 = v[0]; | |
// Encrypt the last element in the array by using the first element (num3) | |
// and the current element (num2) in the encryption process | |
num2 = v[index] += (((num2 >> 5) ^ (num3 << 2)) + ((num3 >> 3) ^ (num2 << 4))) ^ ((num6 ^ num3) + (k[index & 3] ^ num2)); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment