// hmac.h - written and placed in the public domain by Wei Dai #ifndef CRYPTOPP_HMAC_H #define CRYPTOPP_HMAC_H #include "seckey.h" #include "secblock.h" NAMESPACE_BEGIN(CryptoPP) template class HMAC_Base : public VariableKeyLength<16, 0, UINT_MAX>, public MessageAuthenticationCode { public: static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";} // put enums here for Metrowerks 4 enum {DIGESTSIZE=T::DIGESTSIZE, BLOCKSIZE=T::BLOCKSIZE}; HMAC_Base() : m_innerHashKeyed(false) {} void UncheckedSetKey(const byte *userKey, unsigned int keylength); void Restart(); void Update(const byte *input, unsigned int length); void TruncatedFinal(byte *mac, unsigned int size); unsigned int DigestSize() const {return DIGESTSIZE;} private: void KeyInnerHash(); enum {IPAD=0x36, OPAD=0x5c}; FixedSizeSecBlock k_ipad, k_opad; FixedSizeSecBlock m_innerHash; T m_hash; bool m_innerHashKeyed; }; //! HMAC /*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */ template class HMAC : public MessageAuthenticationCodeTemplate > { public: HMAC() {} HMAC(const byte *key, unsigned int length=HMAC_Base::DEFAULT_KEYLENGTH) {SetKey(key, length);} }; template void HMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength) { AssertValidKeyLength(keylength); Restart(); if (keylength <= T::BLOCKSIZE) memcpy(k_ipad, userKey, keylength); else { m_hash.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_Base::KeyInnerHash() { assert(!m_innerHashKeyed); m_hash.Update(k_ipad, T::BLOCKSIZE); m_innerHashKeyed = true; } template void HMAC_Base::Restart() { if (m_innerHashKeyed) { m_hash.Restart(); m_innerHashKeyed = false; } } template void HMAC_Base::Update(const byte *input, unsigned int length) { if (!m_innerHashKeyed) KeyInnerHash(); m_hash.Update(input, length); } template void HMAC_Base::TruncatedFinal(byte *mac, unsigned int size) { ThrowIfInvalidTruncatedSize(size); if (!m_innerHashKeyed) KeyInnerHash(); m_hash.Final(m_innerHash); m_hash.Update(k_opad, T::BLOCKSIZE); m_hash.Update(m_innerHash, DIGESTSIZE); m_hash.TruncatedFinal(mac, size); m_innerHashKeyed = false; } NAMESPACE_END #endif