Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

hmac.h

00001 // hmac.h - written and placed in the public domain by Wei Dai
00002 
00003 #ifndef CRYPTOPP_HMAC_H
00004 #define CRYPTOPP_HMAC_H
00005 
00006 #include "seckey.h"
00007 #include "secblock.h"
00008 
00009 NAMESPACE_BEGIN(CryptoPP)
00010 
00011 template <class T>
00012 class HMAC_Base : public VariableKeyLength<16, 0, UINT_MAX>, public MessageAuthenticationCode
00013 {
00014 public:
00015         static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";}
00016 
00017         // put enums here for Metrowerks 4
00018         enum {DIGESTSIZE=T::DIGESTSIZE, BLOCKSIZE=T::BLOCKSIZE};
00019 
00020         HMAC_Base() : m_innerHashKeyed(false) {}
00021         void UncheckedSetKey(const byte *userKey, unsigned int keylength);
00022 
00023         void Restart();
00024         void Update(const byte *input, unsigned int length);
00025         void TruncatedFinal(byte *mac, unsigned int size);
00026         unsigned int DigestSize() const {return DIGESTSIZE;}
00027 
00028 private:
00029         void KeyInnerHash();
00030 
00031         enum {IPAD=0x36, OPAD=0x5c};
00032 
00033         FixedSizeSecBlock<byte, BLOCKSIZE> k_ipad, k_opad;
00034         FixedSizeSecBlock<byte, DIGESTSIZE> m_innerHash;
00035         T m_hash;
00036         bool m_innerHashKeyed;
00037 };
00038 
00039 //! <a href="http://www.weidai.com/scan-mirror/mac.html#HMAC">HMAC</a>
00040 /*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */
00041 template <class T>
00042 class HMAC : public MessageAuthenticationCodeTemplate<HMAC_Base<T> >
00043 {
00044 public:
00045         HMAC() {}
00046         HMAC(const byte *key, unsigned int length=HMAC_Base<T>::DEFAULT_KEYLENGTH)
00047                 {SetKey(key, length);}
00048 };
00049 
00050 template <class T>
00051 void HMAC_Base<T>::UncheckedSetKey(const byte *userKey, unsigned int keylength)
00052 {
00053         AssertValidKeyLength(keylength);
00054 
00055         Restart();
00056 
00057         if (keylength <= T::BLOCKSIZE)
00058                 memcpy(k_ipad, userKey, keylength);
00059         else
00060         {
00061                 m_hash.CalculateDigest(k_ipad, userKey, keylength);
00062                 keylength = T::DIGESTSIZE;
00063         }
00064 
00065         assert(keylength <= T::BLOCKSIZE);
00066         memset(k_ipad+keylength, 0, T::BLOCKSIZE-keylength);
00067 
00068         for (unsigned int i=0; i<T::BLOCKSIZE; i++)
00069         {
00070                 k_opad[i] = k_ipad[i] ^ OPAD;
00071                 k_ipad[i] ^= IPAD;
00072         }
00073 }
00074 
00075 template <class T>
00076 void HMAC_Base<T>::KeyInnerHash()
00077 {
00078         assert(!m_innerHashKeyed);
00079         m_hash.Update(k_ipad, T::BLOCKSIZE);
00080         m_innerHashKeyed = true;
00081 }
00082 
00083 template <class T>
00084 void HMAC_Base<T>::Restart()
00085 {
00086         if (m_innerHashKeyed)
00087         {
00088                 m_hash.Restart();
00089                 m_innerHashKeyed = false;
00090         }
00091 }
00092 
00093 template <class T>
00094 void HMAC_Base<T>::Update(const byte *input, unsigned int length)
00095 {
00096         if (!m_innerHashKeyed)
00097                 KeyInnerHash();
00098         m_hash.Update(input, length);
00099 }
00100 
00101 template <class T>
00102 void HMAC_Base<T>::TruncatedFinal(byte *mac, unsigned int size)
00103 {
00104         ThrowIfInvalidTruncatedSize(size);
00105 
00106         if (!m_innerHashKeyed)
00107                 KeyInnerHash();
00108         m_hash.Final(m_innerHash);
00109 
00110         m_hash.Update(k_opad, T::BLOCKSIZE);
00111         m_hash.Update(m_innerHash, DIGESTSIZE);
00112         m_hash.TruncatedFinal(mac, size);
00113 
00114         m_innerHashKeyed = false;
00115 }
00116 
00117 NAMESPACE_END
00118 
00119 #endif

Generated on Sun Mar 14 20:44:26 2004 for Crypto++ by doxygen 1.3.6-20040222