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 Fri Aug 13 09:56:53 2004 for Crypto++ by doxygen 1.3.7