// hmac.h - written and placed in the public domain by Wei Dai #ifndef CRYPTOPP_HMAC_H #define CRYPTOPP_HMAC_H #include "cryptlib.h" #include "misc.h" NAMESPACE_BEGIN(CryptoPP) //! HMAC /*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */ template class HMAC : public MessageAuthenticationCode, public VariableKeyLength<16, 0, UINT_MAX> { public: // put enums here for Metrowerks 4 enum {DIGESTSIZE=T::DIGESTSIZE, BLOCKSIZE=T::BLOCKSIZE}; // CW50 workaround: can't use DEFAULT_KEYLENGTH here HMAC(const byte *userKey, unsigned int keylength = 16); void Update(const byte *input, unsigned int length); void TruncatedFinal(byte *mac, unsigned int size); unsigned int DigestSize() const {return DIGESTSIZE;} private: enum {IPAD=0x36, OPAD=0x5c}; void Init(); SecByteBlock k_ipad, k_opad; T hash; }; template HMAC::HMAC(const byte *userKey, unsigned int keylength) : k_ipad(T::BLOCKSIZE), k_opad(T::BLOCKSIZE) { assert(keylength == KeyLength(keylength)); if (keylength <= T::BLOCKSIZE) memcpy(k_ipad, userKey, keylength); else { T().CalculateDigest(k_ipad, userKey, keylength); keylength = T::DIGESTSIZE; } assert(keylength <= T::BLOCKSIZE); memset(k_ipad+keylength, 0, T::BLOCKSIZE-keylength); for (unsigned int i=0; i void HMAC::Init() { hash.Update(k_ipad, T::BLOCKSIZE); } template void HMAC::Update(const byte *input, unsigned int length) { hash.Update(input, length); } template void HMAC::TruncatedFinal(byte *mac, unsigned int size) { hash.Final(mac); hash.Update(k_opad, T::BLOCKSIZE); hash.Update(mac, DIGESTSIZE); hash.TruncatedFinal(mac, size); Init(); } NAMESPACE_END #endif