HMACEngine.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. //
  2. // HMACEngine.h
  3. //
  4. // Library: Foundation
  5. // Package: Crypt
  6. // Module: HMACEngine
  7. //
  8. // Definition of the HMACEngine class.
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Foundation_HMACEngine_INCLUDED
  16. #define Foundation_HMACEngine_INCLUDED
  17. #include "Poco/Foundation.h"
  18. #include "Poco/DigestEngine.h"
  19. #include <cstring>
  20. namespace Poco {
  21. template <class Engine>
  22. class HMACEngine: public DigestEngine
  23. /// This class implementes the HMAC message
  24. /// authentication code algorithm, as specified
  25. /// in RFC 2104. The underlying DigestEngine
  26. /// (MD5Engine, SHA1Engine, etc.) must be given as
  27. /// template argument.
  28. /// Since the HMACEngine is a DigestEngine, it can
  29. /// be used with the DigestStream class to create
  30. /// a HMAC for a stream.
  31. {
  32. public:
  33. enum
  34. {
  35. BLOCK_SIZE = Engine::BLOCK_SIZE,
  36. DIGEST_SIZE = Engine::DIGEST_SIZE
  37. };
  38. HMACEngine(const std::string& passphrase)
  39. {
  40. init(passphrase.data(), passphrase.length());
  41. }
  42. HMACEngine(const char* passphrase, std::size_t length)
  43. {
  44. poco_check_ptr (passphrase);
  45. init(passphrase, length);
  46. }
  47. ~HMACEngine()
  48. {
  49. std::memset(_ipad, 0, BLOCK_SIZE);
  50. std::memset(_opad, 0, BLOCK_SIZE);
  51. delete [] _ipad;
  52. delete [] _opad;
  53. }
  54. std::size_t digestLength() const
  55. {
  56. return DIGEST_SIZE;
  57. }
  58. void reset()
  59. {
  60. _engine.reset();
  61. _engine.update(_ipad, BLOCK_SIZE);
  62. }
  63. const DigestEngine::Digest& digest()
  64. {
  65. const DigestEngine::Digest& d = _engine.digest();
  66. char db[DIGEST_SIZE];
  67. char* pdb = db;
  68. for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end(); ++it)
  69. *pdb++ = *it;
  70. _engine.reset();
  71. _engine.update(_opad, BLOCK_SIZE);
  72. _engine.update(db, DIGEST_SIZE);
  73. const DigestEngine::Digest& result = _engine.digest();
  74. reset();
  75. return result;
  76. }
  77. protected:
  78. void init(const char* passphrase, std::size_t length)
  79. {
  80. _ipad = new char[BLOCK_SIZE];
  81. _opad = new char[BLOCK_SIZE];
  82. std::memset(_ipad, 0, BLOCK_SIZE);
  83. std::memset(_opad, 0, BLOCK_SIZE);
  84. if (length > BLOCK_SIZE)
  85. {
  86. _engine.reset();
  87. _engine.update(passphrase, length);
  88. const DigestEngine::Digest& d = _engine.digest();
  89. char* ipad = _ipad;
  90. char* opad = _opad;
  91. int n = BLOCK_SIZE;
  92. for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end() && n-- > 0; ++it)
  93. {
  94. *ipad++ = *it;
  95. *opad++ = *it;
  96. }
  97. }
  98. else
  99. {
  100. std::memcpy(_ipad, passphrase, length);
  101. std::memcpy(_opad, passphrase, length);
  102. }
  103. for (int i = 0; i < BLOCK_SIZE; ++i)
  104. {
  105. _ipad[i] ^= 0x36;
  106. _opad[i] ^= 0x5c;
  107. }
  108. reset();
  109. }
  110. void updateImpl(const void* data, std::size_t length)
  111. {
  112. _engine.update(data, length);
  113. }
  114. private:
  115. HMACEngine();
  116. HMACEngine(const HMACEngine&);
  117. HMACEngine& operator = (const HMACEngine&);
  118. Engine _engine;
  119. char* _ipad;
  120. char* _opad;
  121. };
  122. } // namespace Poco
  123. #endif // Foundation_HMACEngine_INCLUDED