hash/hmac: add simple HMAC-MD5
This commit is contained in:
parent
277354807e
commit
f4fe636cb0
@ -45,6 +45,8 @@ UTIL_FILES = \
|
||||
hash/crc.cpp \
|
||||
hash/crc.hpp \
|
||||
hash/fletcher.hpp \
|
||||
hash/hmac.cpp \
|
||||
hash/hmac.hpp \
|
||||
hash/md2.cpp \
|
||||
hash/md2.hpp \
|
||||
hash/md4.cpp \
|
||||
@ -238,6 +240,7 @@ TEST_BIN = \
|
||||
test/extent \
|
||||
test/fixed \
|
||||
test/float \
|
||||
test/hmac \
|
||||
test/hton \
|
||||
test/ip \
|
||||
test/json_types \
|
||||
|
102
hash/hmac.cpp
Normal file
102
hash/hmac.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of libgim.
|
||||
*
|
||||
* libgim is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* libgim is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "hmac.hpp"
|
||||
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using util::hash::HMAC;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static const uint8_t IFILL = 0x36;
|
||||
static const uint8_t OFILL = 0x5C;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HMAC::HMAC (const uint8_t *restrict key, size_t len)
|
||||
{
|
||||
CHECK (key);
|
||||
CHECK_LE (len, m_ikey.size ());
|
||||
CHECK_LE (len, m_okey.size ());
|
||||
|
||||
static_assert (sizeof (m_ikey) == sizeof (m_okey), "key padding must match");
|
||||
|
||||
|
||||
std::copy (key, key + len, m_ikey.begin ());
|
||||
std::fill (m_ikey.begin () + len,
|
||||
m_ikey.end (),
|
||||
0);
|
||||
|
||||
m_okey = m_ikey;
|
||||
|
||||
std::transform (m_ikey.begin (),
|
||||
m_ikey.end (),
|
||||
m_ikey.begin (),
|
||||
[] (auto v) { return v ^ IFILL; });
|
||||
|
||||
std::transform (m_okey.begin (),
|
||||
m_okey.end (),
|
||||
m_okey.begin (),
|
||||
[] (auto v) { return v ^ OFILL; });
|
||||
|
||||
m_hash.update (m_ikey.data (), m_ikey.size ());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
HMAC::update (const void *restrict data, size_t len)
|
||||
{
|
||||
m_hash.update ((const uint8_t*)data, len);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
HMAC::finish (void)
|
||||
{
|
||||
m_hash.finish ();
|
||||
auto d = m_hash.digest ();
|
||||
|
||||
m_hash.reset ();
|
||||
m_hash.update (m_okey.data (), m_okey.size ());
|
||||
m_hash.update (d.data (), d.size ());
|
||||
m_hash.finish ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
HMAC::reset (void)
|
||||
{
|
||||
m_hash.reset ();
|
||||
m_hash.update (m_ikey.data (), m_ikey.size ());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HMAC::digest_t
|
||||
HMAC::digest (void)
|
||||
{
|
||||
return m_hash.digest ();
|
||||
}
|
47
hash/hmac.hpp
Normal file
47
hash/hmac.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of libgim.
|
||||
*
|
||||
* libgim is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* libgim is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_HASH_HMAC_HPP
|
||||
#define __UTIL_HASH_HMAC_HPP
|
||||
|
||||
#include "md5.hpp"
|
||||
|
||||
namespace util { namespace hash {
|
||||
/// RFC 2104 key-hashing for message authentication
|
||||
class HMAC {
|
||||
public:
|
||||
using digest_t = MD5::digest_t;
|
||||
|
||||
HMAC (const uint8_t *key, size_t);
|
||||
|
||||
void update (const void *restrict, size_t);
|
||||
void finish (void);
|
||||
void reset (void);
|
||||
|
||||
digest_t digest (void);
|
||||
|
||||
private:
|
||||
std::array<uint8_t,64> m_ikey;
|
||||
std::array<uint8_t,64> m_okey;
|
||||
|
||||
MD5 m_hash;
|
||||
};
|
||||
} }
|
||||
|
||||
#endif
|
67
test/hmac.cpp
Normal file
67
test/hmac.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "hash/hmac.hpp"
|
||||
#include "types.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using util::hash::HMAC;
|
||||
|
||||
|
||||
static const struct {
|
||||
std::vector<uint8_t> key;
|
||||
std::vector<uint8_t> dat;
|
||||
HMAC::digest_t res;
|
||||
} TESTS[] = {
|
||||
// RFC 2104 test data, MD5
|
||||
{
|
||||
{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b },
|
||||
{ 'H', 'i', ' ', 'T', 'h', 'e', 'r', 'e' },
|
||||
{ { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
|
||||
0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d } }
|
||||
},
|
||||
|
||||
{
|
||||
{ 'J', 'e', 'f', 'e' },
|
||||
{ 'w', 'h', 'a', 't', ' ', 'd', 'o', ' ',
|
||||
'y', 'a', ' ', 'w', 'a', 'n', 't', ' ',
|
||||
'f', 'o', 'r', ' ', 'n', 'o', 't', 'h',
|
||||
'i', 'n', 'g', '?' },
|
||||
{ { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
|
||||
0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 } }
|
||||
},
|
||||
|
||||
{
|
||||
{ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA },
|
||||
{ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
0xDD, 0xDD },
|
||||
{ { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
|
||||
0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 } }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int, char**)
|
||||
{
|
||||
for (const auto &t: TESTS) {
|
||||
util::hash::HMAC h (t.key.data (), t.key.size ());
|
||||
h.update (t.dat.data (), t.dat.size ());
|
||||
h.finish ();
|
||||
|
||||
if (h.digest () != t.res)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user