00001
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
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
00040
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