AnCH Framework  0.1
Another C++ Hack Framework
hmac.hpp
1 /*
2  ANCH Framework: ANother C++ Hack is a C++ framework based on C++11 standard
3  Copyright (C) 2012 Vincent Lachenal
4 
5  This file is part of ANCH Framework.
6 
7  ANCH Framework is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  ANCH Framework is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with ANCH Framework. If not, see <http://www.gnu.org/licenses/>.
19 */
20 #ifndef _ANCH_CRYPTO_HMAC_
21 #define _ANCH_CRYPTO_HMAC_
22 
23 #include <sstream>
24 #include <array>
25 
26 
27 namespace anch {
28  namespace crypto {
29 
37  template<class H>
38  H HMAC(const std::string& key, const std::string& message) {
39  // Treatment on key +
40  std::ostringstream keyBuf;
41  const std::size_t block = H::getBlockSize();
42  if(key.length() > block) {
43  keyBuf << H(key);
44  } else {
45  keyBuf << key;
46  }
47  std::array<uint8_t,block> keyArray;
48  keyArray.fill(0x00);
49  const std::string& buffer = keyBuf.str();
50  for(std::size_t i = 0 ; i < buffer.length() ; ++i) {
51  keyArray[i] = static_cast<uint8_t>(buffer[i]);
52  }
53  // Treatment on key -
54 
55  // Compute paddings +
56  std::size_t msgLen = message.length();
57  std::size_t inSize = block + msgLen;
58  uint8_t* inPad = new uint8_t[inSize];
59  std::array<uint8_t, (block + H::getOutputSize())> outPad;
60  // 'Magic numbers' 0x36 and 0x5c are specified in RFC2104 to have a large hamming distance
61  for(std::size_t i = 0 ; i < block ; ++i) {
62  inPad[i] = static_cast<uint8_t>(0x36) ^ keyArray[i];
63  outPad[i] = static_cast<uint8_t>(0x5c) ^ keyArray[i];
64  }
65  // Compute paddings -
66 
67  // First hash +
68  const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.c_str());
69  for(std::size_t i = 0 ; i < msgLen ; ++i) {
70  inPad[i + block] = msg[i];
71  }
72  const std::array<uint8_t,H::getOutputSize()>& inDigest = H(inPad, inSize).digest();
73  delete[] inPad;
74  // First hash -
75 
76  // Second hash +
77  std::size_t idx = block;
78  for(uint8_t byte : inDigest) {
79  outPad[idx] = byte;
80  ++idx;
81  }
82  return H(outPad.data(), outPad.size());
83  // Second hash -
84  }
85 
93  template<class H>
94  H HMAC(const char* const key, const char* const message) {
95  return HMAC<H>(std::string(key), std::string(message));
96  }
97 
98  }
99 }
100 
101 #endif // _ANCH_CRYPTO_HMAC_
H HMAC(const std::string &, const std::string &)
Definition: hmac.hpp:38
AnCH framework base namespace.
Definition: base64.hpp:28