HMACEngine.h 2.9 KB

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