1 module xtea.XteaCrypto; 2 3 /++ 4 + XTEA helper type 5 + see: http://en.wikipedia.org/wiki/XTEA 6 +/ 7 public struct XTEA 8 { 9 /// XTEA delta constant 10 private enum int DELTA = cast(int)0x9E3779B9; 11 12 /// Key - 4 integer 13 private int[4] m_key; 14 15 /// Round to go - 64 are commonly used 16 private int m_rounds; 17 18 /// c'tor 19 public this(int[4] _key, int _rounds) 20 { 21 m_key = _key; 22 m_rounds = _rounds; 23 } 24 25 /// Encrypt given byte array (length to be crypted must be 8 byte aligned) 26 public alias Crypt!(EncryptBlock) Encrypt; 27 /// Decrypt given byte array (length to be crypted must be 8 byte aligned) 28 public alias Crypt!(DecryptBlock) Decrypt; 29 30 /// 31 private const void Crypt(alias T)(byte[] _bytes, size_t _offset=0, long _count=-1) 32 { 33 if(_count == -1) 34 _count = cast(long)(_bytes.length - _offset); 35 36 assert(_count % 8 == 0); 37 38 for (size_t i = _offset; i < (_offset+_count); i += 8) 39 T(_bytes, i); 40 } 41 42 /// Encrypt given block of 8 bytes 43 private const void EncryptBlock(byte[] _bytes, size_t _offset) 44 { 45 auto v0 = ReadInt(_bytes, _offset); 46 auto v1 = ReadInt(_bytes, _offset + 4); 47 48 int sum = 0; 49 50 foreach (i; 0..m_rounds) 51 { 52 v0 += ((v1 << 4 ^ cast(int)(cast(uint)v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); 53 sum += DELTA; 54 v1 += ((v0 << 4 ^ cast(int)(cast(uint)v0 >> 5)) + v0) ^ (sum + m_key[cast(int)(cast(uint)sum >> 11) & 3]); 55 } 56 57 StoreInt(v0, _bytes, _offset); 58 StoreInt(v1, _bytes, _offset + 4); 59 } 60 61 /// Decrypt given block of 8 bytes 62 private const void DecryptBlock(byte[] _bytes, size_t _offset) 63 { 64 auto v0 = ReadInt(_bytes, _offset); 65 auto v1 = ReadInt(_bytes, _offset + 4); 66 67 auto sum = cast(int)(cast(uint)DELTA * cast(uint)m_rounds); 68 69 foreach (i; 0..m_rounds) 70 { 71 v1 -= ((v0 << 4 ^ cast(int)(cast(uint)v0 >> 5)) + v0) ^ (sum + m_key[cast(int)(cast(uint)sum >> 11) & 3]); 72 sum -= DELTA; 73 v0 -= ((v1 << 4 ^ cast(int)(cast(uint)v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); 74 } 75 76 StoreInt(v0, _bytes, _offset); 77 StoreInt(v1, _bytes, _offset + 4); 78 } 79 80 /// Read 32 bit int from buffer 81 private static int ReadInt(byte[] _bytes, size_t _offset) pure nothrow 82 { 83 return (((_bytes[_offset++] & 0xff) << 0) 84 | ((_bytes[_offset++] & 0xff) << 8) 85 | ((_bytes[_offset++] & 0xff) << 16) 86 | ((_bytes[_offset] & 0xff) << 24)); 87 } 88 89 /// Write 32 bit int from buffer 90 private static void StoreInt(int _value, byte[] _bytes, size_t _offset) pure nothrow 91 { 92 auto unsignedValue = cast(uint)_value; 93 _bytes[_offset++] = cast(byte)(unsignedValue >> 0); 94 _bytes[_offset++] = cast(byte)(unsignedValue >> 8); 95 _bytes[_offset++] = cast(byte)(unsignedValue >> 16); 96 _bytes[_offset] = cast(byte)(unsignedValue >> 24); 97 } 98 }