1 module xtea.XteaCrypto; 2 @safe: 3 nothrow: 4 pure: 5 6 ubyte[] encrypt(XTEA crypto, const(ubyte)[] m) 7 { 8 auto ans = m.dup; 9 crypto.Encrypt(ans); 10 return ans; 11 } 12 unittest 13 { 14 enum sourceData = cast(ubyte[])[6, 2, 87, 66, 77, 289, 623, 39823]; 15 enum encrypted = XTEA([1,2,3,4], 64).encrypt(sourceData); 16 import std.algorithm:equal; 17 static assert(encrypted.equal([49, 144, 90, 128, 35, 56, 194, 0])); 18 } 19 20 ubyte[] decrypt(XTEA crypto, const(ubyte)[] m) { 21 auto ans = m.dup; 22 crypto.Decrypt(ans); 23 return ans; 24 } 25 unittest 26 { 27 enum sourceData = cast(ubyte[])[6, 2, 87, 66, 77, 289, 623, 39823]; 28 enum encrypted = cast(ubyte[])[49, 144, 90, 128, 35, 56, 194, 0]; 29 enum dencrypted = XTEA([1,2,3,4], 64).decrypt(encrypted); 30 import std.algorithm:equal; 31 static assert(dencrypted.equal(sourceData)); 32 } 33 // Coverage % 34 unittest { 35 enum sourceData = cast(ubyte[])[6, 2, 87, 66, 77, 289, 623, 39823]; 36 enum crypto = XTEA([1,2,3,4], 64); 37 auto runtime = crypto.decrypt(crypto.encrypt(sourceData)); 38 import std.algorithm:equal; 39 assert(runtime.equal(sourceData)); 40 } 41 42 /++ 43 + XTEA helper type 44 + see: http://en.wikipedia.org/wiki/XTEA 45 +/ 46 public struct XTEA 47 { 48 @safe: 49 nothrow: 50 pure: 51 /// XTEA delta constant 52 private enum int DELTA = cast(int)0x9E3779B9; 53 54 /// Key - 4 integer 55 private int[4] m_key; 56 57 /// Round to go - 64 are commonly used 58 private int m_rounds; 59 60 /// c'tor 61 public this(int[4] _key, int _rounds) 62 { 63 m_key = _key; 64 m_rounds = _rounds; 65 } 66 67 /// Encrypt given ubyte array (length to be crypted must be 8 ubyte aligned) 68 public alias Crypt!(EncryptBlock) Encrypt; 69 /// Decrypt given ubyte array (length to be crypted must be 8 ubyte aligned) 70 public alias Crypt!(DecryptBlock) Decrypt; 71 72 /// 73 private const void Crypt(alias T)(ubyte[] _ubytes, size_t _offset=0, long _count=-1) 74 { 75 if(_count == -1) 76 _count = cast(long)(_ubytes.length - _offset); 77 78 assert(_count % 8 == 0); 79 80 for (size_t i = _offset; i < (_offset+_count); i += 8) 81 T(_ubytes, i); 82 } 83 84 /// Encrypt given block of 8 ubytes 85 private const void EncryptBlock(ubyte[] _ubytes, size_t _offset) 86 { 87 auto v0 = ReadInt(_ubytes, _offset); 88 auto v1 = ReadInt(_ubytes, _offset + 4); 89 90 int sum = 0; 91 92 foreach (i; 0..m_rounds) 93 { 94 v0 += ((v1 << 4 ^ cast(int)(cast(uint)v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); 95 sum += DELTA; 96 v1 += ((v0 << 4 ^ cast(int)(cast(uint)v0 >> 5)) + v0) ^ (sum + m_key[cast(int)(cast(uint)sum >> 11) & 3]); 97 } 98 99 StoreInt(v0, _ubytes, _offset); 100 StoreInt(v1, _ubytes, _offset + 4); 101 } 102 103 /// Decrypt given block of 8 ubytes 104 private const void DecryptBlock(ubyte[] _ubytes, size_t _offset) 105 { 106 auto v0 = ReadInt(_ubytes, _offset); 107 auto v1 = ReadInt(_ubytes, _offset + 4); 108 109 auto sum = cast(int)(cast(uint)DELTA * cast(uint)m_rounds); 110 111 foreach (i; 0..m_rounds) 112 { 113 v1 -= ((v0 << 4 ^ cast(int)(cast(uint)v0 >> 5)) + v0) ^ (sum + m_key[cast(int)(cast(uint)sum >> 11) & 3]); 114 sum -= DELTA; 115 v0 -= ((v1 << 4 ^ cast(int)(cast(uint)v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); 116 } 117 118 StoreInt(v0, _ubytes, _offset); 119 StoreInt(v1, _ubytes, _offset + 4); 120 } 121 122 /// Read 32 bit int from buffer 123 private static int ReadInt(ubyte[] _ubytes, size_t _offset) 124 { 125 return (((_ubytes[_offset++] & 0xff) << 0) 126 | ((_ubytes[_offset++] & 0xff) << 8) 127 | ((_ubytes[_offset++] & 0xff) << 16) 128 | ((_ubytes[_offset] & 0xff) << 24)); 129 } 130 131 /// Write 32 bit int from buffer 132 private static void StoreInt(int _value, ubyte[] _ubytes, size_t _offset) 133 { 134 auto unsignedValue = cast(uint)_value; 135 _ubytes[_offset++] = cast(ubyte)(unsignedValue >> 0); 136 _ubytes[_offset++] = cast(ubyte)(unsignedValue >> 8); 137 _ubytes[_offset++] = cast(ubyte)(unsignedValue >> 16); 138 _ubytes[_offset] = cast(ubyte)(unsignedValue >> 24); 139 } 140 } 141 unittest 142 { 143 import std.algorithm:equal; 144 145 enum ubyte[] sourceData = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; 146 ubyte[] data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; 147 148 auto crypto = XTEA([1,2,3,4], 64); 149 150 crypto.Encrypt(data); 151 crypto.Decrypt(data); 152 assert(equal(sourceData,data)); 153 }