Last active
September 24, 2023 18:22
-
-
Save savaged/e793b8940d6450861c2bd9db91a4f74b to your computer and use it in GitHub Desktop.
TEA implementation
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
// Credit to Page Brooks https://www.codeproject.com/Articles/6137/Tiny-Encryption-Algorithm-TEA-for-the-Compact-Fram | |
var key = "mykey"; | |
var encrypted = Encrypt("testing", key); | |
var decrypted = Decrypt(encrypted, key); | |
Console.WriteLine(decrypted); | |
static string Encrypt(string data, string key) | |
{ | |
if (data.Length == 0) | |
throw new ArgumentOutOfRangeException("data must be at least 1 character in length."); | |
uint[] formattedKey = FormatKey(key); | |
if (data.Length % 2 != 0) data += '\0'; // Make sure array is even in length. | |
byte[] dataBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(data); | |
var cipher = string.Empty; | |
uint[] tempData = new uint[2]; | |
for(int i = 0; i < dataBytes.Length; i += 2) | |
{ | |
tempData[0] = dataBytes[i]; | |
tempData[1] = dataBytes[i + 1]; | |
Code(tempData, formattedKey); | |
cipher += ConvertUIntToString(tempData[0]) + ConvertUIntToString(tempData[1]); | |
} | |
return cipher; | |
} | |
static string Decrypt(string data, string key) | |
{ | |
uint[] formattedKey = FormatKey(key); | |
int x = 0; | |
uint[] tempData = new uint[2]; | |
byte[] dataBytes = new byte[data.Length / 8 * 2]; | |
for (int i = 0; i < data.Length; i += 8) | |
{ | |
tempData[0] = ConvertStringToUInt(data.Substring(i, 4)); | |
tempData[1] = ConvertStringToUInt(data.Substring(i + 4, 4)); | |
Decode(tempData, formattedKey); | |
dataBytes[x++] = (byte)tempData[0]; | |
dataBytes[x++] = (byte)tempData[1]; | |
} | |
var decipheredString = System.Text.ASCIIEncoding.ASCII.GetString(dataBytes, 0, dataBytes.Length); | |
if (decipheredString[decipheredString.Length - 1] == '\0') // Strip the null char if it was added. | |
decipheredString = decipheredString.Substring(0, decipheredString.Length - 1); | |
return decipheredString; | |
} | |
static uint[] FormatKey(string key) | |
{ | |
if (string.IsNullOrEmpty(key)) | |
throw new ArgumentNullException(nameof(key)); | |
if (key.Length == 0) | |
throw new ArgumentOutOfRangeException("key must be between 1 and 16 characters in length"); | |
key = key.PadRight(16, ' ').Substring(0, 16); // Ensure that the key is 16 chars in length. | |
uint[] formattedKey = new uint[4]; | |
// Get the key into the correct format for TEA usage. | |
int j = 0; | |
for (int i = 0; i < key.Length; i += 4) | |
formattedKey[j++] = ConvertStringToUInt(key.Substring(i, 4)); | |
return formattedKey; | |
} | |
/// <summary> | |
/// Converts a string of length 4 to a 32-bit unsigned integer. | |
/// </summary> | |
/// <param name="input">The string of length 4 to convert.</param> | |
/// <returns>An encoded integer value representing a string of length 4.</returns> | |
static uint ConvertStringToUInt(string input) | |
{ | |
uint output = (uint)input[0]; | |
output += ((uint)input[1] << 8); | |
output += ((uint)input[2] << 16); | |
output += ((uint)input[3] << 24); | |
return output; | |
} | |
/// <summary> | |
/// Converts a 32-bit unsigned integer to a string of length 4. | |
/// </summary> | |
/// <param name="input">The unsigned integer to convert to a string.</param> | |
/// <returns>A string value represented by the encoded integer.</returns> | |
static string ConvertUIntToString(uint input) | |
{ | |
var output = new System.Text.StringBuilder(); | |
output.Append((char)((input & 0xFF))); | |
output.Append((char)((input >> 8) & 0xFF)); | |
output.Append((char)((input >> 16) & 0xFF)); | |
output.Append((char)((input >> 24) & 0xFF)); | |
return output.ToString(); | |
} | |
#region Tea Algorithm | |
static void Code(uint[] v, uint[] k) | |
{ | |
uint y = v[0]; | |
uint z = v[1]; | |
uint sum = 0; | |
uint delta = 0x9e3779b9; | |
uint n = 32; | |
while (n-- > 0) | |
{ | |
sum += delta; | |
y += (z << 4) + k[0] ^ z + sum ^ (z >> 5) + k[1]; | |
z += (y << 4) + k[2] ^ y + sum ^ (y >> 5) + k[3]; | |
} | |
v[0] = y; | |
v[1] = z; | |
} | |
static void Decode(uint[] v, uint[] k) | |
{ | |
uint n = 32; | |
uint y = v[0]; | |
uint z = v[1]; | |
uint delta = 0x9e3779b9; | |
uint sum = delta << 5 ; | |
while (n-- > 0) | |
{ | |
z -= (y << 4) + k[2] ^ y + sum ^ (y >> 5) + k[3]; | |
y -= (z << 4) + k[0] ^ z + sum ^ (z >> 5) + k[1]; | |
sum -= delta; | |
} | |
v[0] = y; | |
v[1] = z; | |
} | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment