1 /// Implementation of TEA digesters. 2 module tern.digest.tea; 3 4 import tern.digest; 5 import tern.algorithm; 6 import tern.serialization; 7 8 /** 9 * Implementation of Tiny Encryption Algorithm (TEA) digester. 10 * 11 * TEA is a symmetric block cipher with a block size of 64 bits and a key size of 128 bits. 12 * It operates on 64-bit blocks using a Feistel network structure. TEA is designed to be fast 13 * and simple, yet difficult to cryptanalyze. 14 * 15 * Example: 16 * ```d 17 * import tern.digest.tea; 18 * 19 * ubyte[] data = [1, 2, 3, 4, 5]; 20 * string key = "my_secret_key"; 21 * TEA.encrypt(data, key); 22 * ``` 23 */ 24 public static @digester class TEA 25 { 26 public: 27 static: 28 pure: 29 /** 30 * Encrypts the given byte array `data` using TEA algorithm. 31 * 32 * Params: 33 * data = Reference to the input byte array to be encrypted. 34 * key = The encryption key. Must be 128 bits (16 characters). 35 */ 36 void encrypt(ref ubyte[] data, string key) 37 { 38 assert(key.length == 16, "Key must be 128 bits!"); 39 40 uint[4] k = *cast(uint[4]*)key.ptr; 41 uint delta = 0x9E3779B9; 42 uint rounds = 32; 43 uint sum = 0; 44 uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; 45 46 vacpp(data, 8); 47 48 for (size_t i = 0; i < data.length; i += 8) 49 { 50 auto block = data[i .. i + 8].ptr; 51 uint v0 = *cast(uint*)block; 52 uint v1 = *cast(uint*)(block + 4); 53 sum = 0; 54 55 for (uint j = 0; j < rounds; ++j) 56 { 57 sum += delta; 58 v0 += (((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)); 59 v1 += (((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)); 60 } 61 62 *cast(uint*)block = v0; 63 *cast(uint*)(block + 4) = v1; 64 } 65 } 66 67 /** 68 * Decrypts the given byte array `data` using TEA algorithm. 69 * 70 * Params: 71 * data = Reference to the input byte array to be decrypted. 72 * key = The decryption key. Must be 128 bits (16 characters). 73 */ 74 void decrypt(ref ubyte[] data, string key) 75 { 76 assert(key.length == 16, "Key must be 128 bits!"); 77 78 uint[4] k = *cast(uint[4]*)key.ptr; 79 uint delta = 0x9E3779B9; 80 uint rounds = 32; 81 uint sum; 82 uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; 83 84 if (data.length % 8 != 0) 85 vacpp(data, 8); 86 87 for (size_t i = 0; i < data.length; i += 8) 88 { 89 auto block = data[i .. i + 8].ptr; 90 uint v0 = *cast(uint*)block; 91 uint v1 = *cast(uint*)(block + 4); 92 sum = delta << 5; 93 94 for (uint j = 0; j < rounds; ++j) 95 { 96 v1 -= (((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3)); 97 v0 -= (((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1)); 98 sum -= delta; 99 } 100 101 *cast(uint*)block = v0; 102 *cast(uint*)(block + 4) = v1; 103 } 104 105 unvacpp(data); 106 } 107 } 108 109 /** 110 * Implementation of eXtended Tiny Encryption Algorithm (XTEA) digester. 111 * 112 * XTEA is an extension of TEA with a larger block size (64 bits) and a more complex key schedule. 113 * It offers higher security than TEA, making it suitable for applications requiring stronger encryption. 114 * 115 * Example: 116 * ```d 117 * import tern.digest.tea; 118 * 119 * ubyte[] data = [1, 2, 3, 4, 5]; 120 * string key = "my_secret_key"; 121 * XTEA.encrypt(data, key); 122 * ``` 123 */ 124 public static @digester class XTEA 125 { 126 public: 127 static: 128 pure: 129 /** 130 * Encrypts the given byte array `data` using XTEA algorithm. 131 * 132 * Params: 133 * data = Reference to the input byte array to be encrypted. 134 * key = The encryption key. Must be 128 bits (16 characters). 135 */ 136 void encrypt(ref ubyte[] data, string key) 137 { 138 assert(key.length == 16, "Key must be 128 bits!"); 139 140 int[4] k = *cast(int[4]*)key.ptr; 141 int delta = 0x9E3779B9; 142 int rounds = 32; 143 int sum = 0; 144 145 vacpp(data, 8); 146 147 for (size_t i = 0; i < data.length; i += 8) 148 { 149 auto block = data[i .. i + 8].ptr; 150 int v0 = *cast(int*)block; 151 int v1 = *cast(int*)(block + 4); 152 sum = 0; 153 154 for (int j = 0; j < rounds; ++j) 155 { 156 sum += delta; 157 v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[(sum >> 11) & 3]); 158 v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[sum & 3]); 159 } 160 161 *cast(int*)block = v0; 162 *cast(int*)(block + 4) = v1; 163 } 164 } 165 166 /** 167 * Decrypts the given byte array `data` using XTEA algorithm. 168 * 169 * Params: 170 * data = Reference to the input byte array to be decrypted. 171 * key = The decryption key. Must be 128 bits (16 characters). 172 */ 173 void decrypt(ref ubyte[] data, string key) 174 { 175 assert(key.length == 16, "Key must be 128 bits!"); 176 177 int[4] k = *cast(int[4]*)key.ptr; 178 int delta = 0x9E3779B9; 179 int rounds = 32; 180 int sum; 181 182 if (data.length % 8 != 0) 183 vacpp(data, 8); 184 185 for (size_t i = 0; i < data.length; i += 8) 186 { 187 auto block = data[i .. i + 8].ptr; 188 int v0 = *cast(int*)block; 189 int v1 = *cast(int*)(block + 4); 190 sum = delta << 5; 191 192 for (int j = 0; j < rounds; ++j) 193 { 194 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[sum & 3]); 195 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[(sum >> 11) & 3]); 196 sum -= delta; 197 } 198 199 *cast(int*)block = v0; 200 *cast(int*)(block + 4) = v1; 201 } 202 203 unvacpp(data); 204 } 205 } 206 207 /** 208 * Implementation of XXTEA (Corrected Block TEA) digester. 209 * 210 * XXTEA is a corrected version of XTEA with a fixed block size of 64 bits and a simpler key schedule. 211 * It is designed to be more resistant against certain types of attacks compared to XTEA. 212 * 213 * Example: 214 * ```d 215 * import tern.digest.tea; 216 * 217 * ubyte[] data = [1, 2, 3, 4, 5]; 218 * string key = "my_secret_key"; 219 * XXTEA.encrypt(data, key); 220 * ``` 221 */ 222 public static @digester class XXTEA 223 { 224 public: 225 static: 226 pure: 227 /** 228 * Encrypts the given byte array `data` using XXTEA algorithm. 229 * 230 * Params: 231 * data = Reference to the input byte array to be encrypted. 232 * key = The encryption key. Must be 128 bits (16 characters). 233 */ 234 void encrypt(ref ubyte[] data, string key) 235 { 236 assert(key.length == 16, "Key must be 128 bits!"); 237 238 int[4] k = *cast(int[4]*)key.ptr; 239 int delta = 0x9E3779B9; 240 int rounds = 32; 241 int sum = 0; 242 243 vacpp(data, 8); 244 245 for (size_t i = 0; i < data.length; i += 8) 246 { 247 auto block = data[i..(i + 8)].ptr; 248 int v0 = *cast(int*)block; 249 int v1 = *cast(int*)(block + 4); 250 sum = 0; 251 252 for (int j = 0; j < rounds; ++j) 253 { 254 sum += delta; 255 v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[(sum >> 11) & 3]); 256 v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[sum & 3]); 257 } 258 259 *cast(int*)block = v0; 260 *cast(int*)(block + 4) = v1; 261 } 262 } 263 264 /** 265 * Decrypts the given byte array `data` using XXTEA algorithm. 266 * 267 * Params: 268 * data = Reference to the input byte array to be decrypted. 269 * key = The decryption key. Must be 128 bits (16 characters). 270 */ 271 void decrypt(ref ubyte[] data, string key) 272 { 273 assert(key.length == 16, "Key must be 128 bits!"); 274 275 int[4] k = *cast(int[4]*)key.ptr; 276 int delta = 0x9E3779B9; 277 int rounds = 32; 278 int sum; 279 280 if (data.length % 8 != 0) 281 vacpp(data, 8); 282 283 for (size_t i = 0; i < data.length; i += 8) 284 { 285 auto block = data[i .. i + 8].ptr; 286 int v0 = *cast(int*)block; 287 int v1 = *cast(int*)(block + 4); 288 sum = delta << 5; 289 290 for (int j = 0; j < rounds; ++j) 291 { 292 v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[sum & 3]); 293 v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[(sum >> 11) & 3]); 294 sum -= delta; 295 } 296 297 *cast(int*)block = v0; 298 *cast(int*)(block + 4) = v1; 299 } 300 301 unvacpp(data); 302 } 303 }