PageRenderTime 61ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/torque_sockets/symmetric_cipher.h

https://github.com/nardo/torque_sockets
C Header | 107 lines | 94 code | 10 blank | 3 comment | 8 complexity | 16c70b7faee128b689b97bd5196ca11d MD5 | raw file
  1. /// Class for symmetric encryption of data across a connection. Internally it uses
  2. /// the libtomcrypt AES algorithm to encrypt the data.
  3. class symmetric_cipher : public ref_object
  4. {
  5. public:
  6. enum {
  7. block_size = 16,
  8. key_size = 16,
  9. };
  10. private:
  11. struct key
  12. {
  13. uint32 e_k[64], d_k[64];
  14. int n_r;
  15. };
  16. uint32 _counter[block_size >> 2];
  17. uint8 _init_vector[block_size];
  18. uint8 _pad[block_size];
  19. key _symmetric_key;
  20. uint32 _pad_len;
  21. public:
  22. symmetric_cipher(const uint8 key[key_size], const uint8 init_vector[block_size])
  23. {
  24. rijndael_setup(key, key_size, 0, (symmetric_key *) &_symmetric_key);
  25. memcpy(_init_vector, init_vector, block_size);
  26. memcpy(_counter, init_vector, block_size);
  27. rijndael_ecb_encrypt((uint8 *) _counter, _pad, (symmetric_key *) &_symmetric_key);
  28. _pad_len = 0;
  29. }
  30. symmetric_cipher(const byte_buffer_ptr the_bytes)
  31. {
  32. if(the_bytes->get_buffer_size() != key_size * 2)
  33. {
  34. uint8 buffer[key_size];
  35. memset(buffer, 0, key_size);
  36. rijndael_setup(buffer, key_size, 0, (symmetric_key *) &_symmetric_key);
  37. memcpy(_init_vector, buffer, block_size);
  38. }
  39. else
  40. {
  41. rijndael_setup(the_bytes->get_buffer(), key_size, 0, (symmetric_key *) &_symmetric_key);
  42. memcpy(_init_vector, the_bytes->get_buffer() + key_size, block_size);
  43. }
  44. memcpy(_counter, _init_vector, block_size);
  45. rijndael_ecb_encrypt((uint8 *) _counter, _pad, (symmetric_key *) &_symmetric_key);
  46. _pad_len = 0;
  47. }
  48. void get_init_vector(uint8 iv[block_size])
  49. {
  50. memcpy(iv, _init_vector, block_size);
  51. }
  52. void setup_counter(uint32 counter_value1, uint32 counter_value2, uint32 counter_value3, uint32 counter_value4)
  53. {
  54. uint8 *iv_walk = _init_vector;
  55. for(uint32 i = 0; i < 4; i++)
  56. {
  57. _counter[i] = buffer_to_uint32(iv_walk);
  58. iv_walk += 4;
  59. }
  60. _counter[0] += counter_value1;
  61. _counter[1] += counter_value2;
  62. _counter[2] += counter_value3;
  63. _counter[3] += counter_value4;
  64. for(uint32 i = 0; i < 4; i++)
  65. host_to_little_endian(_counter[i]);
  66. rijndael_ecb_encrypt((uint8 *) _counter, _pad, (symmetric_key *) &_symmetric_key);
  67. _pad_len = 0;
  68. }
  69. void encrypt(const uint8 *plain_text, uint8 *cipher_text, uint32 len)
  70. {
  71. while(len-- > 0)
  72. {
  73. if(_pad_len == block_size)
  74. {
  75. // we've reached the end of the pad, so compute a new pad
  76. rijndael_ecb_encrypt(_pad, _pad, (symmetric_key *) &_symmetric_key);
  77. _pad_len = 0;
  78. }
  79. uint8 encrypted_char = *plain_text++ ^ _pad[_pad_len];
  80. _pad[_pad_len++] = *cipher_text++ = encrypted_char;
  81. }
  82. }
  83. void decrypt(const uint8 *cipher_text, uint8 *plain_text, uint32 len)
  84. {
  85. while(len-- > 0)
  86. {
  87. if(_pad_len == block_size)
  88. {
  89. rijndael_ecb_encrypt(_pad, _pad, (symmetric_key *) &_symmetric_key);
  90. _pad_len = 0;
  91. }
  92. uint8 encrypted_char = *cipher_text++;
  93. *plain_text++ = encrypted_char ^ _pad[_pad_len];
  94. _pad[_pad_len++] = encrypted_char;
  95. }
  96. }
  97. };