Merge remote-tracking branch 'origin/master'

This commit is contained in:
Danny Robson 2018-01-16 15:17:25 +11:00
commit b4e242ffd4
102 changed files with 959 additions and 7194 deletions

View File

@ -134,7 +134,6 @@ endif ()
# Common files
list (
APPEND UTIL_FILES
hash/md2.cpp
adapter.hpp
adapter.cpp
algo/sort.cpp
@ -186,18 +185,6 @@ list (
coord/ops.hpp
coord/store.hpp
coord/traits.hpp
crypto/arc4.cpp
crypto/arc4.hpp
crypto/ice.cpp
crypto/ice.hpp
crypto/salsa.cpp
crypto/salsa.hpp
crypto/tea.cpp
crypto/tea.hpp
crypto/xtea.cpp
crypto/xtea.hpp
crypto/xxtea.cpp
crypto/xxtea.hpp
debug.cpp
debug.hpp
debug.ipp
@ -241,8 +228,6 @@ list (
geom/tri.hpp
hash.hpp
hash/fwd.hpp
hash/simple.hpp
hash/simple.cpp
hash/adler.cpp
hash/adler.hpp
hash/bsdsum.cpp
@ -255,18 +240,6 @@ list (
hash/fletcher.hpp
hash/fnv1a.cpp
hash/fnv1a.hpp
hash/hmac.cpp
hash/hmac.hpp
hash/hotp.cpp
hash/hotp.hpp
hash/keccak.cpp
hash/keccak.hpp
hash/md2.cpp
hash/md2.hpp
hash/md4.cpp
hash/md4.hpp
hash/md5.cpp
hash/md5.hpp
hash/murmur/common.cpp
hash/murmur/common.hpp
hash/murmur.hpp
@ -276,18 +249,7 @@ list (
hash/murmur/murmur2.hpp
hash/murmur/murmur3.cpp
hash/murmur/murmur3.hpp
hash/pbkdf1.cpp
hash/pbkdf1.hpp
hash/pbkdf2.cpp
hash/pbkdf2.hpp
hash/ripemd.cpp
hash/ripemd.hpp
hash/sha1.cpp
hash/sha1.hpp
hash/sha2.cpp
hash/sha2.hpp
hash/wang.hpp
hash/wang.ipp
hash/xxhash.cpp
hash/xxhash.hpp
introspection.cpp
@ -459,7 +421,7 @@ target_link_libraries(cruft-util PUBLIC ${MATH_LIBS})
###############################################################################
foreach (tool hash json-clean json-schema json-validate scratch)
foreach (tool json-clean json-schema json-validate scratch)
add_executable (util_${tool} tools/${tool}.cpp)
set_target_properties (util_${tool} PROPERTIES OUTPUT_NAME ${tool})
target_link_libraries (util_${tool} cruft-util)
@ -491,12 +453,6 @@ if (TESTS)
colour
comparator
coord
crypto/arc4
crypto/ice
crypto/salsa
crypto/tea
crypto/xtea
crypto/xxtea
encode/base
endian
exe
@ -509,16 +465,8 @@ if (TESTS)
hash/checksum
hash/crc
hash/fasthash
hash/hmac
hash/hotp
hash/keccak
hash/md2
hash/md4
hash/md5
hash/fnv1a
hash/murmur
hash/ripemd
hash/sha1
hash/sha2
hash/xxhash
hton
introspection

4
README
View File

@ -1,5 +1,3 @@
A simple cross-platform C++ utility library.
Supported compilers: >=clang-4.x, >=gcc7.x; specifically, we require c++17 features such as structured bindings which aren't present in older compilers. No attempt has been made to compile under MSVC.
For the love of God, do not use the crypto routines. I am not a cryptographer or a security specialist. You have been warned.
Supported compilers: >=clang-5.x, >=gcc7.x; specifically, we require c++17 features such as structured bindings which aren't present in older compilers. No attempt has been made to compile under MSVC.

View File

@ -1,66 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#include "arc4.hpp"
#include <algorithm>
#include <numeric>
using util::crypto::ARC4;
///////////////////////////////////////////////////////////////////////////////
ARC4::ARC4 (const uint8_t *restrict key, size_t len):
x (0),
y (0)
{
std::iota (S.begin (), S.end (), 0);
for (size_t i = 0, j = 0; i < 256; ++i) {
j = (j + S[i] + key[i % len]) % 256;
std::swap (S[i], S[j]);
}
}
//-----------------------------------------------------------------------------
void
ARC4::discard (size_t len)
{
while (len--)
get ();
}
//-----------------------------------------------------------------------------
void
ARC4::generate (uint8_t *restrict dst, size_t len)
{
std::generate_n (dst, len, [this] (void) { return get (); });
}
//-----------------------------------------------------------------------------
uint8_t
ARC4::get (void)
{
x = (x + 1) % 256;
y = (y + S[x]) % 256;
std::swap (S[x], S[y]);
return S[(S[x] + S[y]) % 256];
}

View File

@ -1,40 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_RC4_HPP
#define __UTIL_RC4_HPP
#include <array>
#include <cstdint>
#include <cstddef>
namespace util::crypto {
class ARC4 {
public:
ARC4 (const uint8_t *restrict key, size_t len);
void discard (size_t);
void generate (uint8_t *restrict dst, size_t len);
private:
uint8_t get (void);
size_t x, y;
std::array<uint8_t,256> S;
};
}
#endif

View File

@ -1,441 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/
// Derived from Mathew Kwan's 1996 C++ public domain implementation of ICE:
// http://www.darkside.com.au/ice/
//
// M. Kwan, The Design of the ICE Encryption Algorithm, proceedings of Fast
// Software Encryption - Fourth International Workshop, Haifa, Israel,
// Springer-Verlag, pp. 69-82, 1997
#include "ice.hpp"
#include "../endian.hpp"
#include "../debug.hpp"
#include <cstdint>
///////////////////////////////////////////////////////////////////////////////
/*
* C++ implementation of the ICE encryption algorithm.
*
* Written by Matthew Kwan - July 1996
*/
/* The S-boxes */
static uint32_t ice_sbox[4][1024];
static bool ice_sboxes_initialised = false;
/* Modulo values for the S-boxes */
static
constexpr
uint_fast16_t
ice_smod[4][4] = {
{333, 313, 505, 369},
{379, 375, 319, 391},
{361, 445, 451, 397},
{397, 425, 395, 505}
};
/* XOR values for the S-boxes */
constexpr
uint8_t
ice_sxor[4][4] = {
{0x83, 0x85, 0x9b, 0xcd},
{0xcc, 0xa7, 0xad, 0x41},
{0x4b, 0x2e, 0xd4, 0x33},
{0xea, 0xcb, 0x2e, 0x04}
};
/* Permutation values for the P-box */
constexpr
uint32_t
ice_pbox[32] = {
0x00000001, 0x00000080, 0x00000400, 0x00002000,
0x00080000, 0x00200000, 0x01000000, 0x40000000,
0x00000008, 0x00000020, 0x00000100, 0x00004000,
0x00010000, 0x00800000, 0x04000000, 0x20000000,
0x00000004, 0x00000010, 0x00000200, 0x00008000,
0x00020000, 0x00400000, 0x08000000, 0x10000000,
0x00000002, 0x00000040, 0x00000800, 0x00001000,
0x00040000, 0x00100000, 0x02000000, 0x80000000
};
/* The key rotation schedule */
constexpr
std::array<uint_fast8_t,8>
ice_keyrot[2] = {
{ 0, 1, 2, 3, 2, 1, 3, 0, },
{ 1, 3, 2, 0, 3, 1, 0, 2, },
};
/*
* 8-bit Galois Field multiplication of a by b, modulo m.
* Just like arithmetic multiplication, except that additions and
* subtractions are replaced by XOR.
*/
template <typename T>
static
T
gf_mult (T a, T b, const T m)
{
T res = 0;
while (b) {
if (b & 1u)
res ^= a;
a <<= 1u;
b >>= 1u;
if (a >= 256)
a ^= m;
}
return res;
}
/*
* Galois Field exponentiation.
* Raise the base to the power of 7, modulo m.
*/
template <typename T>
static
T
gf_exp7 (const T b,
const T m)
{
if (b == 0)
return 0;
T x;
x = gf_mult (b, b, m);
x = gf_mult (b, x, m);
x = gf_mult (x, x, m);
return gf_mult (b, x, m);
}
/*
* Carry out the ICE 32-bit P-box permutation.
*/
static
uint32_t
ice_perm32 (uint32_t x)
{
uint32_t res = 0;
const uint32_t *pbox = ice_pbox;
while (x) {
if (x & 1)
res |= *pbox;
pbox++;
x >>= 1;
}
return res;
}
/*
* Initialise the ICE S-boxes.
* This only has to be done once.
*/
static
void
ice_sboxes_init (void)
{
for (unsigned i = 0; i < 1024; i++) {
const uint_fast16_t col = (i >> 1) & 0xff;
const uint_fast16_t row = (i & 0x1) | ((i & 0x200) >> 8);
for (unsigned j = 0; j < 4; ++j) {
const auto p = gf_exp7<uint_fast16_t> (
col ^ ice_sxor[j][row],
ice_smod[j][row]
) << (24 - j * 8);
ice_sbox[j][i] = ice_perm32 (static_cast<uint32_t>(p));
}
}
}
/*
* Create a new ICE key.
*/
ice::ice (unsigned n,
const uint64_t *key_first,
const uint64_t *key_last)
{
if (!ice_sboxes_initialised) {
ice_sboxes_init ();
ice_sboxes_initialised = true;
}
if (n < 1) {
m_size = 1;
m_rounds = 8;
} else {
m_size = n;
m_rounds = n * 16;
}
m_schedule.resize (m_rounds);
set (key_first, key_last);
}
/*
* Destroy an ICE key.
*/
ice::~ice ()
{
for (auto &s: m_schedule)
std::fill (std::begin (s), std::end (s), 0);
m_rounds = m_size = 0;
}
/*
* The single round ICE f function.
*/
static
uint32_t
ice_f (uint32_t p, const ice::subkey_t &sk)
{
uint_fast64_t tl, tr; /* Expanded 40-bit values */
uint_fast64_t al, ar; /* Salted expanded 40-bit values */
/* Left half expansion */
tl = ((p >> 16) & 0x3ff) | (((p >> 14) | (p << 18)) & 0xffc00);
/* Right half expansion */
tr = (p & 0x3ff) | ((p << 2) & 0xffc00);
/* Perform the salt permutation */
// al = (tr & sk->val[2]) | (tl & ~sk->val[2]);
// ar = (tl & sk->val[2]) | (tr & ~sk->val[2]);
al = sk[2] & (tl ^ tr);
ar = al ^ tr;
al ^= tl;
al ^= sk[0]; /* XOR with the subkey */
ar ^= sk[1];
/* S-box lookup and permutation */
return (
ice_sbox[0][al >> 10] | ice_sbox[1][al & 0x3ff]
| ice_sbox[2][ar >> 10] | ice_sbox[3][ar & 0x3ff]
);
}
/*
* Encrypt a block of 8 bytes of data with the given ICE key.
*/
uint64_t
ice::encrypt (const uint64_t _ptext) const
{
union {
uint64_t pword;
uint8_t pbytes[8];
};
pword = util::hton (_ptext);
uint32_t l, r;
l = (((uint32_t) pbytes[0]) << 24u)
| (((uint32_t) pbytes[1]) << 16u)
| (((uint32_t) pbytes[2]) << 8u)
| pbytes[3];
r = (((uint32_t) pbytes[4]) << 24u)
| (((uint32_t) pbytes[5]) << 16u)
| (((uint32_t) pbytes[6]) << 8u)
| pbytes[7];
for (unsigned i = 0; i < m_rounds; i += 2) {
l ^= ice_f (r, m_schedule[i]);
r ^= ice_f (l, m_schedule[i + 1]);
}
union {
uint64_t cword;
uint8_t cbytes[8];
};
for (unsigned i = 0; i < 4; i++) {
cbytes[3 - i] = r & 0xff;
cbytes[7 - i] = l & 0xff;
r >>= 8u;
l >>= 8u;
}
return util::hton (cword);
}
/*
* Decrypt a block of 8 bytes of data with the given ICE key.
*/
uint64_t
ice::decrypt (const uint64_t _ctext) const
{
union {
uint64_t cword;
uint8_t cbytes[8];
};
cword = util::hton (_ctext);
uint32_t l, r;
l = (((uint32_t) cbytes[0]) << 24u)
| (((uint32_t) cbytes[1]) << 16u)
| (((uint32_t) cbytes[2]) << 8u)
| cbytes[3];
r = (((uint32_t) cbytes[4]) << 24u)
| (((uint32_t) cbytes[5]) << 16u)
| (((uint32_t) cbytes[6]) << 8u)
| cbytes[7];
for (int i = m_rounds - 1; i > 0; i -= 2) {
l ^= ice_f (r, m_schedule[i]);
r ^= ice_f (l, m_schedule[i - 1]);
}
union {
uint64_t pword;
uint8_t pbytes[8];
};
for (unsigned i = 0; i < 4; i++) {
pbytes[3 - i] = r & 0xff;
pbytes[7 - i] = l & 0xff;
r >>= 8;
l >>= 8;
}
return util::hton (pword);
}
/*
* Set 8 rounds [n, n+7] of the key schedule of an ICE key.
*/
void
ice::scheduleBuild (std::array<uint16_t,4> &kb,
int n,
const std::array<uint_fast8_t,8> &keyrot)
{
for (unsigned i = 0; i < 8; i++) {
int kr = keyrot[i];
subkey_t &isk = m_schedule[n + i];
std::fill (std::begin (isk), std::end (isk), 0);
for (unsigned j = 0; j < 15; j++) {
uint32_t &curr_sk = isk[j % 3];
for (unsigned k = 0; k < 4; k++) {
auto &curr_kb = kb[(kr + k) & 3];
unsigned bit = curr_kb & 1;
curr_sk = (curr_sk << 1) | bit;
curr_kb = (curr_kb >> 1) | ((bit ^ 1) << 15);
}
}
}
}
/*
* Set the key schedule of an ICE key.
*/
void
ice::set (const uint64_t *_key_first, const uint64_t *_key_last)
{
(void)_key_last;
CHECK_EQ ((unsigned)(_key_last - _key_first), m_size);
auto key = reinterpret_cast<const uint8_t*> (_key_first);
if (m_rounds == 8) {
std::array<uint16_t,4> kb;
for (unsigned i = 0; i < 4; i++)
kb[3 - i] = (key[i * 2] << 8) | key[i * 2 + 1];
scheduleBuild (kb, 0, ice_keyrot[0]);
return;
}
for (unsigned i = 0; i < m_size; i++) {
std::array<uint16_t,4> kb;
for (unsigned j = 0; j < 4; j++)
kb[3 - j] = (key[i * 8 + j * 2] << 8) | key[i * 8 + j * 2 + 1];
scheduleBuild (kb, i * 8, ice_keyrot[0]);
scheduleBuild (kb, m_rounds - 8 - i * 8, ice_keyrot[1]);
}
}
/*
* Return the key size, in bytes.
*/
unsigned
ice::key_size () const
{
return (m_size * 8);
}
/*
* Return the block size, in bytes.
*/
unsigned
ice::block_size () const
{
return (8);
}

View File

@ -1,64 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __CRYPTO_ICE_HPP
#define __CRYPTO_ICE_HPP
#include <cstdint>
#include <array>
#include <vector>
// An implementation of the ICE symmetric-key block cipher
//
// we make a token attempt to zero our buffers, but we can't guarantee this
// will take place (given compiler optimisations). further security is
// outside the scope of this class.
class ice {
public:
ice (unsigned n, uint64_t key);
ice (unsigned n,
const uint64_t *key_first,
const uint64_t *key_last);
~ice ();
void
set (const uint64_t *key_first, const uint64_t *key_last);
uint64_t encrypt (uint64_t plaintext) const;
uint64_t decrypt (uint64_t ciphertext) const;
unsigned key_size () const;
unsigned block_size () const;
using subkey_t = std::array<uint32_t,3>;
private:
void
scheduleBuild (std::array<uint16_t,4> &k,
int n,
const std::array<uint_fast8_t,8> &keyrot);
unsigned m_size;
unsigned m_rounds;
std::vector<subkey_t> m_schedule;
};
struct ice_error : public std::runtime_error { using runtime_error::runtime_error; };
struct level_error : public ice_error { using ice_error::ice_error; };
#endif

View File

@ -1,24 +0,0 @@
#include "./salsa.hpp"
///////////////////////////////////////////////////////////////////////////////
std::array<uint8_t,64>
util::crypto::salsa20 (const std::array<uint8_t,64> bytes) noexcept
{
auto x = *reinterpret_cast<const std::array<uint32_t,16>*> (&bytes);
auto y = x;
for (auto &t: x)
t = util::ltoh (t);
for (int i = 0; i < 10; ++i)
x = salsa::doubleround (x);
for (size_t i = 0; i < std::size (y); ++i)
x[i] += y[i];
for (auto &t: x)
t = util::htol (t);
return *reinterpret_cast<std::array<uint8_t,64>*> (&x);
}

View File

@ -1,86 +0,0 @@
#include <cstdint>
#include <array>
#include "../bitwise.hpp"
#include "../endian.hpp"
namespace util::crypto::salsa {
///////////////////////////////////////////////////////////////////////////
constexpr
uint32_t
R (uint32_t a, uint32_t b, uint32_t c, uint32_t k)
{
return b ^ util::rotatel (a + c, k);
}
///////////////////////////////////////////////////////////////////////////
constexpr
std::array<uint32_t,4>
quarter (std::array<uint32_t,4> y) noexcept
{
std::array<uint32_t,4> z {};
z[1] = R (y[0], y[1], y[3], 7);
z[2] = R (z[1], y[2], y[0], 9);
z[3] = R (z[2], y[3], z[1], 13);
z[0] = R (z[3], y[0], z[2], 18);
return z;
}
///////////////////////////////////////////////////////////////////////////
constexpr
std::array<uint32_t,16>
row (const std::array<uint32_t,16> y) noexcept
{
const auto [z00, z01, z02, z03] = quarter ({y[ 0], y[ 1], y[ 2], y[ 3]});
const auto [z05, z06, z07, z04] = quarter ({y[ 5], y[ 6], y[ 7], y[ 4]});
const auto [z10, z11, z08, z09] = quarter ({y[10], y[11], y[ 8], y[ 9]});
const auto [z15, z12, z13, z14] = quarter ({y[15], y[12], y[13], y[14]});
return {
z00, z01, z02, z03,
z04, z05, z06, z07,
z08, z09, z10, z11,
z12, z13, z14, z15
};
}
///////////////////////////////////////////////////////////////////////////
constexpr
std::array<uint32_t,16>
col (const std::array<uint32_t,16> x) noexcept
{
const auto [y00, y04, y08, y12] = quarter ({x[ 0], x[ 4], x[ 8], x[12]});
const auto [y05, y09, y13, y01] = quarter ({x[ 5], x[ 9], x[13], x[ 1]});
const auto [y10, y14, y02, y06] = quarter ({x[10], x[14], x[ 2], x[ 6]});
const auto [y15, y03, y07, y11] = quarter ({x[15], x[ 3], x[ 7], x[11]});
return {
y00, y01, y02, y03,
y04, y05, y06, y07,
y08, y09, y10, y11,
y12, y13, y14, y15,
};
}
///////////////////////////////////////////////////////////////////////////
constexpr
std::array<uint32_t,16>
doubleround (const std::array<uint32_t,16> x) noexcept
{
return row (col (x));
}
}
namespace util::crypto {
///////////////////////////////////////////////////////////////////////////
std::array<uint8_t,64>
salsa20 (const std::array<uint8_t,64>) noexcept;
}

View File

@ -1,86 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#include "tea.hpp"
#include <cstdint>
#include <stdexcept>
using util::crypto::TEA;
///////////////////////////////////////////////////////////////////////////////
static const std::uint32_t MAGIC = 0x9E3779B9;
// each iteration performs two feistel rounds, for a total of 64
static const unsigned ITERATIONS = 32;
///////////////////////////////////////////////////////////////////////////////
TEA::TEA (key_t _key):
m_key (_key)
{ ; }
//-----------------------------------------------------------------------------
void
TEA::encrypt (uint32_t *restrict data, size_t count)
{
if (count % 2)
throw std::invalid_argument ("TEA requires even data count");
auto last = data + count;
while (data < last) {
uint32_t sum = 0;
uint32_t v0 = data[0];
uint32_t v1 = data[1];
for (unsigned i = 0; i < ITERATIONS; ++i) {
sum += MAGIC;
v0 += ((v1 << 4) + m_key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + m_key[1]);
v1 += ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]);
}
*data++ = v0;
*data++ = v1;
}
}
//-----------------------------------------------------------------------------
void
TEA::decrypt (uint32_t *restrict data, size_t count)
{
if (count % 2)
throw std::invalid_argument ("TEA requires even data count");
auto last = data + count;
while (data < last) {
uint32_t sum = MAGIC << 5;
uint32_t v0 = data[0];
uint32_t v1 = data[1];
for (unsigned i = 0; i < ITERATIONS; ++i) {
v1 -= ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]);
v0 -= ((v1 << 4) + m_key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + m_key[1]);
sum -= MAGIC;
}
*data++ = v0;
*data++ = v1;
}
}

View File

@ -1,40 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_TEA_HPP
#define __UTIL_TEA_HPP
#include <array>
#include <cstdint>
#include <cstddef>
namespace util::crypto {
// http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
class TEA {
public:
using key_t = std::array<uint32_t,4>;
explicit TEA (key_t);
void encrypt (uint32_t *restrict data, size_t count);
void decrypt (uint32_t *restrict data, size_t count);
private:
key_t m_key;
};
}
#endif

View File

@ -1,84 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#include "xtea.hpp"
using util::crypto::XTEA;
///////////////////////////////////////////////////////////////////////////////
static const uint32_t MAGIC = 0x9E3779B9;
// each iteration performs two feistel rounds, for a total of 64
static const unsigned ITERATIONS = 32;
///////////////////////////////////////////////////////////////////////////////
XTEA::XTEA (key_t _key):
m_key (_key)
{ }
//-----------------------------------------------------------------------------
void
XTEA::encrypt (uint32_t *restrict data, size_t count)
{
if (count % 2)
throw std::invalid_argument ("XTEA requires even data count");
auto last = data + count;
while (data < last) {
uint32_t sum = 0;
uint32_t v0 = data[0];
uint32_t v1 = data[1];
for (unsigned i = 0; i < ITERATIONS; ++i) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]);
sum += MAGIC;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]);
}
*data++ = v0;
*data++ = v1;
}
}
//-----------------------------------------------------------------------------
void
XTEA::decrypt (uint32_t *restrict data, size_t count)
{
if (count % 2)
throw std::invalid_argument ("XTEA requires even data count");
auto last = data + count;
while (data < last) {
uint32_t sum = ITERATIONS * MAGIC;
uint32_t v0 = data[0];
uint32_t v1 = data[1];
for (unsigned i = 0; i < ITERATIONS; ++i) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]);
sum -= MAGIC;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]);
}
*data++ = v0;
*data++ = v1;
}
}

View File

@ -1,40 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_TEA_HPP
#define __UTIL_TEA_HPP
#include <array>
#include <cstdint>
#include <cstddef>
namespace util::crypto {
// http://en.wikipedia.org/wiki/XTEA
class XTEA {
public:
using key_t = std::array<uint32_t,4>;
explicit XTEA (key_t);
void encrypt (uint32_t *restrict data, size_t count);
void decrypt (uint32_t *restrict data, size_t count);
private:
key_t m_key;
};
}
#endif

View File

@ -1,106 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#include "xxtea.hpp"
#include <cstring>
// test vectors: http://www.cix.co.uk/~klockstone/teavect.htm
using util::crypto::XXTEA;
//-----------------------------------------------------------------------------
static const uint32_t MAGIC = 0x9E3779B9;
//-----------------------------------------------------------------------------
static constexpr
uint32_t
mix (uint32_t Z,
uint32_t Y,
uint32_t S,
size_t E,
size_t P,
const uint32_t *restrict K)
{
return ((Z >> 5 ^ Y << 2) + (Y >> 3 ^ Z << 4)) ^ ((S ^ Y) + (K[(P & 3) ^ E] ^ Z));
}
//-----------------------------------------------------------------------------
XXTEA::XXTEA (key_t _key):
m_key (_key)
{ ; }
//-----------------------------------------------------------------------------
void
XXTEA::encrypt (uint32_t *restrict data, size_t count)
{
if (count < 2)
throw std::invalid_argument ("minimum blocksize is 64 bits");
uint32_t sum = 0;
uint32_t z = data[count - 1];
uint32_t y, p;
unsigned rounds = 6 + 52 / count;
do {
sum += MAGIC;
uint32_t e = (sum >> 2) & 3;
for (p = 0; p < count - 1; p++) {
y = data[p + 1];
z = data[p] += mix (z, y, sum, e, p, m_key.data ());
}
y = data[0];
z = data[count - 1] += mix (z, y, sum, e, p, m_key.data ());
} while (--rounds);
}
//-----------------------------------------------------------------------------
void
XXTEA::decrypt (uint32_t *restrict data, size_t count)
{
if (count < 2)
throw std::invalid_argument ("minimum blocksize is 64 bits");
uint32_t y, z, sum;
uint32_t rounds;
size_t p;
rounds = 6 + 52 / count;
sum = rounds * MAGIC;
y = data[0];
do {
uint32_t e = (sum >> 2) & 3;
for (p = count - 1; p > 0; p--) {
z = data[p - 1];
y = data[p ] -= mix (z, y, sum, e, p, m_key.data ());
}
z = data[count - 1];
y = data[ 0] -= mix (z, y, sum, e, p, m_key.data ());
sum -= MAGIC;
} while (--rounds);
}

View File

@ -1,42 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_TEA_HPP
#define __UTIL_TEA_HPP
#include <array>
#include <cstdint>
#include <cstddef>
namespace util::crypto {
// http://en.wikipedia.org/wiki/XXTEA
// 'corrected' block TEA
class XXTEA {
public:
using key_t = std::array<uint32_t,4>;
explicit XXTEA (key_t);
void encrypt (uint32_t *restrict data, size_t count);
void decrypt (uint32_t *restrict data, size_t count);
private:
key_t m_key;
};
}
#endif

View File

@ -23,8 +23,18 @@
#include <cstdlib>
namespace util::hash {
constexpr std::uint32_t mix (std::uint32_t a, std::uint32_t b) { return murmur2::mix (a, b); }
constexpr std::uint64_t mix (std::uint64_t a, std::uint64_t b) { return murmur2::mix (a, b); }
constexpr std::uint32_t
mix (std::uint32_t a, std::uint32_t b)
{
return murmur2<std::uint32_t>::mix (a, b);
}
constexpr std::uint64_t
mix (std::uint64_t a, std::uint64_t b)
{
return murmur2<std::uint64_t>::mix (a, b);
}
}
#endif

View File

@ -16,9 +16,6 @@
#include "adler.hpp"
#include "fletcher.hpp"
#include "../debug.hpp"
static constexpr unsigned MODULUS = 65521;
using util::hash::adler32;
@ -29,21 +26,3 @@ adler32::adler32 ():
fletcher (MODULUS, 1, 0)
{ ; }
/////////////////////////////////////////////////////////////////////////////////
//uint32_t
//util::hash::adler32 (const void* restrict _data, size_t _size) noexcept
//{
// return adler32 (
// static_cast<const uint8_t*> (_data),
// static_cast<const uint8_t*> (_data) + _size
// );
//}
//
//
////-----------------------------------------------------------------------------
//uint32_t
//util::hash::adler32 (const uint8_t *restrict first, const uint8_t *restrict last) noexcept
//{
// return fletcher<32, MODULUS, 1, 0> (first, last - first);
//}

View File

@ -11,67 +11,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2010 Danny Robson <danny@nerdcruft.net>
* Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
*/
#include "bsdsum.hpp"
#include "../debug.hpp"
#include "../bitwise.hpp"
using util::hash::bsdsum;
///////////////////////////////////////////////////////////////////////////////
bsdsum::bsdsum ()
{
reset ();
}
//-----------------------------------------------------------------------------
void
bsdsum::reset (void)
{
m_accum = 0;
}
///////////////////////////////////////////////////////////////////////////////
void
bsdsum::update (const void *restrict data, size_t size) noexcept
{
auto first = static_cast<const uint8_t *restrict> (data);
update (first, first + size);
}
///////////////////////////////////////////////////////////////////////////////
void
bsdsum::update (const uint8_t *const restrict first,
const uint8_t *const restrict last) noexcept
{
CHECK (first);
CHECK (last);
CHECK_LE (first, last);
for (auto cursor = first; cursor != last; ++cursor) {
m_accum = (m_accum >> 1u) | ((m_accum & 0x01u) << 15u);
m_accum += *cursor;
}
}
//-----------------------------------------------------------------------------
void
bsdsum::finish (void)
{ ; }
//-----------------------------------------------------------------------------
typename bsdsum::digest_t
bsdsum::digest (void) const
bsdsum::operator() (util::view<const uint8_t*> data) const noexcept
{
return m_accum;
digest_t accum = 0;
for (const auto i: data)
accum = util::rotater (accum, 1) + i;
return accum;
}

View File

@ -11,11 +11,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
* Copyright 2011-2018 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_BSDSUM_HPP
#define __UTIL_HASH_BSDSUM_HPP
#ifndef CRUFT_UTIL_HASH_BSDSUM_HPP
#define CRUFT_UTIL_HASH_BSDSUM_HPP
#include "../view.hpp"
#include <cstdint>
#include <cstdlib>
@ -27,18 +29,7 @@ namespace util::hash {
public:
using digest_t = uint16_t;
bsdsum (void);
void reset (void);
void update (const void *restrict data, size_t bytes) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
private:
digest_t m_accum;
digest_t operator() (util::view<const uint8_t*>) const noexcept;
};
}

View File

@ -48,112 +48,23 @@ template <
bool ReflectIn,
bool ReflectOut
>
typename crc<DigestT,Generator,Initial,Final,ReflectIn,ReflectOut>::digest_t
crc<
DigestT,Generator,Initial,Final,ReflectIn,ReflectOut
>::crc () noexcept
>::operator() (const util::view<const uint8_t*> data) const noexcept
{
reset ();
}
auto accum = Initial;
//-----------------------------------------------------------------------------
template <
typename DigestT,
DigestT Generator,
DigestT Initial,
DigestT Final,
bool ReflectIn,
bool ReflectOut
>
void
crc<
DigestT,Generator,Initial,Final,ReflectIn,ReflectOut
>::reset (void) noexcept
{
m_digest = Initial;
}
///////////////////////////////////////////////////////////////////////////////
template <
typename DigestT,
DigestT Generator,
DigestT Initial,
DigestT Final,
bool ReflectIn,
bool ReflectOut
>
void
crc<
DigestT,Generator,Initial,Final,ReflectIn,ReflectOut
>::update (const uint8_t *restrict first,
const uint8_t *restrict last) noexcept
{
CHECK_LE (first, last);
for (auto cursor = first; cursor != last; ++cursor) {
for (auto i: data) {
if (ReflectIn)
m_digest = s_table[*cursor ^ (m_digest & 0xFFu)] ^ (m_digest >> 8u);
accum = s_table[i ^ (accum & 0xFFu)] ^ (accum >> 8u);
else {
constexpr auto shift = sizeof (DigestT) * 8u - 8u;
m_digest = (m_digest << 8u) ^ s_table[(m_digest >> shift) ^ *cursor];
}
accum = (accum << 8u) ^ s_table[(accum >> shift) ^ i];
}
}
//-----------------------------------------------------------------------------
template <
typename DigestT,
DigestT Generator,
DigestT Initial,
DigestT Final,
bool ReflectIn,
bool ReflectOut
>
void
crc<
DigestT,Generator,Initial,Final,ReflectIn,ReflectOut
>::update (const void *restrict _data, size_t len) noexcept
{
auto data = reinterpret_cast<const uint8_t *restrict> (_data);
return update(data, data + len);
}
//-----------------------------------------------------------------------------
template <
typename DigestT,
DigestT Generator,
DigestT Initial,
DigestT Final,
bool ReflectIn,
bool ReflectOut
>
void
crc<
DigestT,Generator,Initial,Final,ReflectIn,ReflectOut
>::finish (void)
{
;
}
//-----------------------------------------------------------------------------
template <
typename DigestT,
DigestT Generator,
DigestT Initial,
DigestT Final,
bool ReflectIn,
bool ReflectOut
>
DigestT
crc<
DigestT,Generator,Initial,Final,ReflectIn,ReflectOut
>::digest (void) const
{
return (ReflectIn != ReflectOut ? util::reverse (m_digest) : m_digest) ^ Final;
return (ReflectIn != ReflectOut ? util::reverse (accum) : accum) ^ Final;
}

View File

@ -11,11 +11,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
* Copyright 2011-2018 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_CRC_HPP
#define __UTIL_HASH_CRC_HPP
#ifndef CRUFT_UTIL_HASH_CRC_HPP
#define CRUFT_UTIL_HASH_CRC_HPP
#include "../view.hpp"
#include <array>
#include <cstdint>
@ -24,7 +26,7 @@
///////////////////////////////////////////////////////////////////////////////
namespace util { namespace hash {
namespace util::hash {
// Implements the crc checksum (from ethernet, png, etc).
//
// Adapted from the PNG specification (ISO/IEC 15948:2003), appendix D and
@ -37,8 +39,8 @@ namespace util { namespace hash {
// ReflectOut: whether to reverse the bits of the digest at finish time
//
// Note that reflection isn't necessarily explicitly performed at update
// time. Instead we construct the lookup table appropriately to directly
// use the data values directly.
// time. Instead we construct the lookup table appropriately to use the
// data values directly.
template <
typename DigestT,
DigestT Generator,
@ -53,33 +55,23 @@ namespace util { namespace hash {
static constexpr auto generator = Generator;
crc () noexcept;
void reset (void) noexcept;
void update (const void *restrict data, size_t bytes) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
digest_t operator() (util::view<const uint8_t*>) const noexcept;
static constexpr
std::array<DigestT,256>
table (void);
private:
digest_t m_digest;
static const std::array<DigestT,256> s_table;
};
using crc32 = crc<uint32_t, 0x04c11db7, 0xffffffff, 0xffffffff, true, true>;
using crc32b = crc<uint32_t, 0x04c11db7, 0xffffffff, 0xffffffff, false, false>;
using crc32c = crc<uint32_t, 0x1edc6f41, 0xffffffff, 0xffffffff, true, true>;
using crc32d = crc<uint32_t, 0xa833982b, 0xffffffff, 0xffffffff, true, true>;
using crc64 = crc<uint64_t, 0x42f0e1eba9ea3693, 0, 0, false, false>;
} }
}
#endif

View File

@ -16,35 +16,26 @@
#include "fasthash.hpp"
///////////////////////////////////////////////////////////////////////////////
uint64_t
util::hash::fasthash::mix (uint64_t v)
{
v ^= v >> 23;
v *= 0x2127599bf4325c37;
v ^= v >> 47;
return v;
}
using util::hash::fasthash;
///////////////////////////////////////////////////////////////////////////////
template <>
uint64_t
util::hash::fasthash::hash64 (const void *restrict data, size_t len, uint64_t seed)
fasthash<uint64_t>::operator() (uint64_t seed, const util::view<const uint8_t*> data) const
{
static const uint64_t m = 0x880355f21e6d1965;
uint64_t result = seed ^ (len * m);
uint64_t result = seed ^ (data.size () * m);
auto cursor = reinterpret_cast<const uint64_t*> (data);
auto last = cursor + len / sizeof (*cursor);
auto cursor = reinterpret_cast<const uint64_t*> (data.begin ());
auto last = cursor + data.size () / sizeof (*cursor);
for (; cursor < last; ++cursor) {
result ^= mix (*cursor);
result *= m;
}
size_t remain = len % sizeof (*cursor);
size_t remain = data.size () % sizeof (*cursor);
if (remain) {
auto tail = reinterpret_cast<const uint8_t*> (cursor);
@ -61,10 +52,11 @@ util::hash::fasthash::hash64 (const void *restrict data, size_t len, uint64_t se
//-----------------------------------------------------------------------------
template <>
uint32_t
util::hash::fasthash::hash32 (const void *restrict data, size_t len, uint32_t seed)
fasthash<uint32_t>::operator() (uint64_t seed, const util::view<const uint8_t*> data) const
{
uint64_t h = hash64 (data, len, seed);
auto h = fasthash<uint64_t> {} (seed, data);
return (h & 0xffffffff) - (h >> 32);
}

View File

@ -17,17 +17,31 @@
#ifndef __UTIL_HASH_FASTHASH_HPP
#define __UTIL_HASH_FASTHASH_HPP
#include "../view.hpp"
#include <cstddef>
#include <cstdint>
// Zilong Tan's FastHash, via George Marsaglia's "Xorshift RNGs"
namespace util::hash::fasthash {
uint64_t mix (uint64_t);
uint32_t hash32 (const void *restrict data, size_t len, uint32_t seed);
uint64_t hash64 (const void *restrict data, size_t len, uint64_t seed);
// Zilong Tan's FastHash, via George Marsaglia's "Xorshift RNGs"
namespace util::hash {
template <typename ValueT>
struct fasthash {
using digest_t = ValueT;
static constexpr
uint64_t mix (uint64_t v)
{
v ^= v >> 23;
v *= 0x2127599bf4325c37;
v ^= v >> 47;
return v;
}
digest_t operator() (uint64_t seed, util::view<const uint8_t*>) const;
};
}
#endif

View File

@ -27,61 +27,24 @@ using util::hash::fletcher;
template <typename T>
fletcher<T>::fletcher (part_t _modulus, part_t _a, part_t _b):
m_modulus { _modulus },
m_initial { _a, _b },
m_state { m_initial }
m_initial { _a, _b }
{ ; }
//-----------------------------------------------------------------------------
template <typename T>
void
fletcher<T>::reset (void)
{
m_state = m_initial;
}
///////////////////////////////////////////////////////////////////////////////
template <typename T>
void
fletcher<T>::update (const void *restrict data, size_t size) noexcept
template <typename DigestT>
typename fletcher<DigestT>::digest_t
fletcher<DigestT>::operator() (util::view<const std::uint8_t*> data) const noexcept
{
CHECK (data);
state_t accum = m_initial;
auto first = static_cast<const uint8_t *restrict> (data);
update (first, first + size);
for (const auto i: data) {
accum.a = (accum.a + i) % m_modulus;
accum.b = (accum.a + accum.b) % m_modulus;
}
//-----------------------------------------------------------------------------
template <typename T>
void
fletcher<T>::update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept
{
CHECK (first);
CHECK (last);
CHECK_LE (first, last);
for (auto cursor = first; cursor < last; ++cursor) {
m_state.a = (m_state.a + *cursor ) % m_modulus;
m_state.b = (m_state.a + m_state.b) % m_modulus;
}
}
//-----------------------------------------------------------------------------
template <typename T>
void
fletcher<T>::finish (void)
{ ; }
///////////////////////////////////////////////////////////////////////////////
template <typename T>
typename fletcher<T>::digest_t
fletcher<T>::digest (void) const
{
return (m_state.b << (sizeof (part_t) * 8)) + m_state.a;
return accum.b << (sizeof(part_t) * 8u) | accum.a;
}

View File

@ -18,6 +18,7 @@
#define __UTIL_HASH_FLETCHER_HPP
#include "../types/bits.hpp"
#include "../view.hpp"
#include <cstdint>
#include <cstdlib>
@ -25,31 +26,24 @@
///////////////////////////////////////////////////////////////////////////////
namespace util::hash {
template <typename DIGEST>
template <typename DigestT>
class fletcher {
public:
using digest_t = DIGEST;
using digest_t = DigestT;
using part_t = typename bytes_type<sizeof (digest_t) / 2>::uint;
fletcher (part_t modulus, part_t a, part_t b);
void update (const void *restrict, size_t) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
void reset (void);
digest_t
operator() (util::view<const std::uint8_t*>) const noexcept;
private:
const digest_t m_modulus;
struct state_t {
part_t a, b;
};
const digest_t m_modulus;
const state_t m_initial;
state_t m_state;
};
}

View File

@ -16,6 +16,8 @@
#include "fnv1a.hpp"
using util::hash::fnv1a;
///////////////////////////////////////////////////////////////////////////////
// Prime is,
@ -28,48 +30,41 @@
//
// Bias is the FNV-0 hash of "chongo <Landon Curt Noll> /\\../\\"
template <size_t B>
template <typename DigestT>
struct constants { };
template <> struct constants<32> {
static constexpr uint32_t PRIME = 16777619u;
static constexpr uint32_t BIAS = 2166136261u;
};
template <> struct constants<64> {
static constexpr uint64_t PRIME = 1099511628211u;
static constexpr uint64_t BIAS = 14695981039346656037u;
//-----------------------------------------------------------------------------
template <>
struct constants<uint32_t> {
static constexpr uint32_t prime = 16777619u;
static constexpr uint32_t bias = 2166136261u;
};
//-----------------------------------------------------------------------------
template <typename T>
T
fnv1a (const void *restrict _data, size_t len)
{
auto *data = static_cast<const uint8_t *restrict> (_data);
T result = constants<sizeof(T)*8>::BIAS;
template <>
struct constants<uint64_t> {
static constexpr uint64_t prime = 1099511628211u;
static constexpr uint64_t bias = 14695981039346656037u;
};
for (size_t i = 0; i < len; ++i) {
result ^= data[i];
result *= constants<sizeof(T)*8>::PRIME;
///////////////////////////////////////////////////////////////////////////////
template <typename DigestT>
typename fnv1a<DigestT>::digest_t
fnv1a<DigestT>::operator() (const util::view<const uint8_t*> data) const noexcept
{
auto result = constants<DigestT>::bias;
for (auto i: data) {
result ^= i;
result *= constants<DigestT>::prime;
}
return result;
}
///////////////////////////////////////////////////////////////////////////////
uint32_t
util::hash::fnv1a32 (const void *data, size_t len)
{
return fnv1a<uint32_t> (data, len);
}
//-----------------------------------------------------------------------------
uint64_t
util::hash::fnv1a64 (const void *data, size_t len)
{
return fnv1a<uint64_t> (data, len);
}
template struct util::hash::fnv1a<uint32_t>;
template struct util::hash::fnv1a<uint64_t>;

View File

@ -17,13 +17,19 @@
#ifndef __UTIL_HASH_FNV1A_HPP
#define __UTIL_HASH_FNV1A_HPP
#include "view.hpp"
#include <cstdint>
#include <cstddef>
namespace util::hash {
// Fast and general hashing using FNV-1a
uint32_t fnv1a32 (const void *restrict, size_t);
uint64_t fnv1a64 (const void *restrict, size_t);
template <typename DigestT>
struct fnv1a {
using digest_t = DigestT;
digest_t operator() (util::view<const uint8_t*>) const noexcept;
};
}
#endif

View File

@ -37,18 +37,6 @@ namespace util::hash {
class crc;
class xxhash;
// hash adapters
class PBKDF1;
class PBKDF2;
// cryptographic hashes
class MD2;
class MD4;
class MD5;
class RIPEMD;
class SHA1;
class SHA256;
}
#endif

View File

@ -1,124 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 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;
//-----------------------------------------------------------------------------
template <class T>
HMAC<T>::HMAC (const uint8_t *restrict key, size_t len)
{
CHECK (key);
static_assert (sizeof (m_ikey) == sizeof (m_okey), "key padding must match");
// If the key is larger than the blocklength, use the hash of the key
if (len > T::BLOCK_SIZE) {
m_hash.update (key, len);
m_hash.finish ();
auto d = m_hash.digest ();
m_hash.reset ();
std::copy (d.begin (), d.end (), m_ikey.begin ());
len = d.size ();
// Use the key directly
} else {
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 ());
}
//-----------------------------------------------------------------------------
template <class T>
void
HMAC<T>::update (const void *restrict data, size_t len)
{
m_hash.update ((const uint8_t*)data, len);
}
//-----------------------------------------------------------------------------
template <class T>
void
HMAC<T>::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 ();
}
//-----------------------------------------------------------------------------
template <class T>
void
HMAC<T>::reset (void)
{
m_hash.reset ();
m_hash.update (m_ikey.data (), m_ikey.size ());
}
//-----------------------------------------------------------------------------
template <class T>
typename HMAC<T>::digest_t
HMAC<T>::digest (void)
{
return m_hash.digest ();
}
//-----------------------------------------------------------------------------
#include "md5.hpp"
#include "sha1.hpp"
namespace util::hash {
template class HMAC<MD5>;
template class HMAC<SHA1>;
}

View File

@ -1,47 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_HMAC_HPP
#define __UTIL_HASH_HMAC_HPP
#include <array>
#include <cstdint>
#include <cstdlib>
namespace util::hash {
template <class T>
/// RFC 2104 key-hashing for message authentication
class HMAC {
public:
using digest_t = typename T::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,T::BLOCK_SIZE> m_ikey;
std::array<uint8_t,T::BLOCK_SIZE> m_okey;
T m_hash;
};
}
#endif

View File

@ -1,72 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#include "hotp.hpp"
#include "../endian.hpp"
#include <cstring>
using util::hash::HOTP;
//-----------------------------------------------------------------------------
HOTP::HOTP (const char *_key, uint64_t _counter):
HOTP (_key, strlen (_key), _counter)
{ ; }
//-----------------------------------------------------------------------------
HOTP::HOTP (const void *_key, size_t _len, uint64_t _counter):
m_counter (_counter),
m_hash ((const uint8_t*)_key, _len)
{ ; }
//-----------------------------------------------------------------------------
unsigned
HOTP::value (void)
{
auto c = htob (m_counter);
m_hash.update (&c, sizeof (c));
m_hash.finish ();
auto h = m_hash.digest ();
auto t = truncate (h);
m_hash.reset ();
++m_counter;
return t % 1000000;
}
//-----------------------------------------------------------------------------
uint32_t
HOTP::truncate (SHA1::digest_t d)
{
// offset into the digest by the last 4 bits
size_t o= d[d.size () - 1] & 0x0F;
// mask the highest bit per the specification
uint32_t v = (d[o + 0] & 0x7f) << 24 |
(d[o + 1] & 0xff) << 16 |
(d[o + 2] & 0xff) << 8 |
(d[o + 3] & 0xff) << 0;
return v;
}

View File

@ -1,43 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_HOTP_HPP
#define __UTIL_HASH_HOTP_HPP
#include "hmac.hpp"
#include "sha1.hpp"
#include <cstdint>
namespace util::hash {
/// HMAC one-time password (RFC 4226)
class HOTP {
public:
HOTP (const char *key, uint64_t counter);
HOTP (const void *key, size_t len, uint64_t counter);
unsigned value (void);
uint64_t counter (void) const;
private:
uint32_t truncate (SHA1::digest_t);
uint64_t m_counter;
HMAC<SHA1> m_hash;
};
}
#endif

View File

@ -1,484 +0,0 @@
#include "keccak.hpp"
#include "../endian.hpp"
#include "../maths.hpp"
#include "../bitwise.hpp"
#include <cstdlib>
#include <cstdint>
#include <array>
#include <iostream>
#include <algorithm>
#if 0
#define FOR(i,n) for(i=0; i<n; ++i)
int LFSR86540(u8 *R) { (*R)=((*R)<<1)^(((*R)&0x80)?0x71:0); return ((*R)&2)>>1; }
#define ROL(a,o) ((((u64)a)<<o)^(((u64)a)>>(64-o)))
static u64 load64(const u8 *x) { ui i; u64 u=0; FOR(i,8) { u<<=8; u|=x[7-i]; } return u; }
static void store64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]=u; u>>=8; } }
static void xor64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]^=u; u>>=8; } }
#define rL(x,y) load64((u8*)s+8*(x+5*y))
#define wL(x,y,l) store64((u8*)s+8*(x+5*y),l)
#define XL(x,y,l) xor64((u8*)s+8*(x+5*y),l)
void KeccakF1600(void *s)
{
ui r,x,y,i,j,Y; u8 R=0x01; u64 C[5],D;
for(i=0; i<24; i++) {
/*θ*/ FOR(x,5) C[x]=rL(x,0)^rL(x,1)^rL(x,2)^rL(x,3)^rL(x,4); FOR(x,5) { D=C[(x+4)%5]^ROL(C[(x+1)%5],1); FOR(y,5) XL(x,y,D); }
/*ρπ*/ x=1; y=r=0; D=rL(x,y); FOR(j,24) { r+=j+1; Y=(2*x+3*y)%5; x=y; y=Y; C[0]=rL(x,y); wL(x,y,ROL(D,r%64)); D=C[0]; }
/*χ*/ FOR(y,5) { FOR(x,5) C[x]=rL(x,y); FOR(x,5) wL(x,y,C[x]^((~C[(x+1)%5])&C[(x+2)%5])); }
/*ι*/ FOR(j,7) if (LFSR86540(&R)) XL(0,0,(u64)1<<((1<<j)-1));
}
}
void Keccak(ui r, ui c, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen)
{
/*initialize*/ u8 s[200]; ui R=r/8; ui i,b=0; FOR(i,200) s[i]=0;
/*absorb*/ while(inLen>0) { b=(inLen<R)?inLen:R; FOR(i,b) s[i]^=in[i]; in+=b; inLen-=b; if (b==R) { KeccakF1600(s); b=0; } }
/*pad*/ s[b]^=sfx; if((sfx&0x80)&&(b==(R-1))) KeccakF1600(s); s[R-1]^=0x80; KeccakF1600(s);
/*squeeze*/ while(outLen>0) { b=(outLen<R)?outLen:R; FOR(i,b) out[i]=s[i]; out+=b; outLen-=b; if(outLen>0) KeccakF1600(s); }
}
#else
// derived from Keccak (KCP) readable-and-compact C implementation
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
/*
================================================================
The purpose of this source file is to demonstrate a readable and compact
implementation of all the Keccak instances approved in the FIPS 202 standard,
including the hash functions and the extendable-output functions (XOFs).
We focused on clarity and on source-code compactness,
rather than on the performance.
The advantages of this implementation are:
+ The source code is compact, after removing the comments, that is. :-)
+ There are no tables with arbitrary constants.
+ For clarity, the comments link the operations to the specifications using
the same notation as much as possible.
+ There is no restriction in cryptographic features. In particular,
the SHAKE128 and SHAKE256 XOFs can produce any output length.
+ The code does not use much RAM, as all operations are done in place.
The drawbacks of this implementation are:
- There is no message queue. The whole message must be ready in a buffer.
- It is not optimized for peformance.
The implementation is even simpler on a little endian platform. Just define the
LITTLE_ENDIAN symbol in that case.
For a more complete set of implementations, please refer to
the Keccak Code Package at https://github.com/gvanas/KeccakCodePackage
For more information, please refer to:
* [Keccak Reference] http://keccak.noekeon.org/Keccak-reference-3.0.pdf
* [Keccak Specifications Summary] http://keccak.noekeon.org/specs_summary.html
This file uses UTF-8 encoding, as some comments use Greek letters.
================================================================
*/
/**
* Function to compute the Keccak[r, c] sponge function over a given input.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param input Pointer to the input message.
* @param inputByteLen The number of input bytes provided in the input message.
* @param delimitedSuffix Bits that will be automatically appended to the end
* of the input message, as in domain separation.
* This is a byte containing from 0 to 7 bits
* These <i>n</i> bits must be in the least significant bit positions
* and must be delimited with a bit 1 at position <i>n</i>
* (counting from 0=LSB to 7=MSB) and followed by bits 0
* from position <i>n</i>+1 to position 7.
* Some examples:
* - If no bits are to be appended, then @a delimitedSuffix must be 0x01.
* - If the 2-bit sequence 0,1 is to be appended (as for SHA3-*), @a delimitedSuffix must be 0x06.
* - If the 4-bit sequence 1,1,1,1 is to be appended (as for SHAKE*), @a delimitedSuffix must be 0x1F.
* - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a delimitedSuffix must be 0x8B.
* @param output Pointer to the buffer where to store the output.
* @param outputByteLen The number of output bytes desired.
* @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.
*/
/**
* Function to compute SHAKE128 on the input message with any output length.
*/
void
FIPS202_SHAKE128(const uint8_t *input, size_t inputByteLen, uint8_t *output, size_t outputByteLen)
{
keccak k (1344, 256, 0x1f);
k.update (input, inputByteLen);
k.digest (output, outputByteLen);
}
/**
* Function to compute SHAKE256 on the input message with any output length.
*/
void FIPS202_SHAKE256(const uint8_t *input, size_t inputByteLen, uint8_t *output, size_t outputByteLen)
{
keccak k (1088, 512, 0x1f);
k.update (input, inputByteLen);
k.digest (output, outputByteLen);
}
/**
* Function to compute SHA3-224 on the input message. The output length is fixed to 28 bytes.
*/
void FIPS202_SHA3_224(const uint8_t *input, size_t inputByteLen, uint8_t *output)
{
keccak k (1152, 448, 0x06);
for (unsigned int i = 0; i < inputByteLen; ++i)
k.update (&input[i], 1);
//k.update (input, inputByteLen);
k.digest (output, 28);
}
/**
* Function to compute SHA3-256 on the input message. The output length is fixed to 32 bytes.
*/
void FIPS202_SHA3_256(const uint8_t *input, size_t inputByteLen, uint8_t *output)
{
keccak k (1088, 512, 0x06);
k.update (input, inputByteLen);
k.digest (output, 32);
}
/**
* Function to compute SHA3-384 on the input message. The output length is fixed to 48 bytes.
*/
void FIPS202_SHA3_384(const uint8_t *input, size_t inputByteLen, uint8_t *output)
{
keccak k (832, 768, 0x06);
k.update (input, inputByteLen);
k.digest (output, 48);
}
/**
* Function to compute SHA3-512 on the input message. The output length is fixed to 64 bytes.
*/
void FIPS202_SHA3_512(const uint8_t *input, size_t inputByteLen, uint8_t *output)
{
keccak k (576, 1024, 0x06);
k.update (input, inputByteLen);
k.digest (output, 64);
}
/*
================================================================
A readable and compact implementation of the Keccak-f[1600] permutation.
================================================================
*/
//static constexpr
//size_t
//i (size_t x, size_t y)
//{
// return x + 5 * y;
//}
/**
* Function that computes the linear feedback shift register (LFSR) used to
* define the round constants (see [Keccak Reference, Section 1.2]).
*/
class lfsr86540 {
public:
lfsr86540 ():
value (0x1)
{ ; }
bool
update (void)
{
bool result = value & 0x01;
if (value & 0x80)
// Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
value = (value << 1) ^ 0x71;
else
value <<= 1;
return result;
}
private:
uint8_t value;
};
// θ step, see [Keccak Reference, Section 2.3.2]
static void
permute_theta (uint64_t m_words[5][5])
{
uint64_t C[5], D;
// Compute the parity of the columns
for (unsigned x = 0; x < 5; ++x)
C[x] = m_words[0][x] ^ m_words[1][x] ^ m_words[2][x] ^ m_words[3][x] ^ m_words[4][x];
for (unsigned x = 0; x < 5; ++x) {
// Compute the θ effect for a given column
D = C[(x+4)%5] ^ util::rotatel (C[(x+1)%5], 1);
// Add the θ effect to the whole column
for (unsigned y = 0; y < 5; ++y)
m_words[y][x] ^= D;
}
}
void
permute_rho (uint64_t m_words[5][5])
{
m_words[0][1] = util::rotatel (m_words[0][1], 1);
m_words[0][2] = util::rotatel (m_words[0][2], 62);
m_words[0][3] = util::rotatel (m_words[0][3], 28);
m_words[0][4] = util::rotatel (m_words[0][4], 27);
m_words[1][0] = util::rotatel (m_words[1][0], 36);
m_words[1][1] = util::rotatel (m_words[1][1], 44);
m_words[1][2] = util::rotatel (m_words[1][2], 6);
m_words[1][3] = util::rotatel (m_words[1][3], 55);
m_words[1][4] = util::rotatel (m_words[1][4], 20);
m_words[2][0] = util::rotatel (m_words[2][0], 3);
m_words[2][1] = util::rotatel (m_words[2][1], 10);
m_words[2][2] = util::rotatel (m_words[2][2], 43);
m_words[2][3] = util::rotatel (m_words[2][3], 25);
m_words[2][4] = util::rotatel (m_words[2][4], 39);
m_words[3][0] = util::rotatel (m_words[3][0], 41);
m_words[3][1] = util::rotatel (m_words[3][1], 45);
m_words[3][2] = util::rotatel (m_words[3][2], 15);
m_words[3][3] = util::rotatel (m_words[3][3], 21);
m_words[3][4] = util::rotatel (m_words[3][4], 8);
m_words[4][0] = util::rotatel (m_words[4][0], 18);
m_words[4][1] = util::rotatel (m_words[4][1], 2);
m_words[4][2] = util::rotatel (m_words[4][2], 61);
m_words[4][3] = util::rotatel (m_words[4][3], 56);
m_words[4][4] = util::rotatel (m_words[4][4], 14);
return;
for (size_t i = 1; i < 25; ++i) {
//unsigned r = ((t+1)*(t+2)/2)%64;
unsigned r = ((i + 1) * (i + 2) / 2) % 64;
m_words[i/5][i%5] = util::rotatel (m_words[i/5][i%5], r);
}
}
void
permute_pi (uint64_t m_words[5][5])
{
//auto A = reinterpret_cast<uint64_t*> (m_words);
//uint64_t A1;
//A1 = A[1];
//A[ 1] = A[ 6];
//A[ 6] = A[ 9];
//A[ 9] = A[22];
//A[22] = A[14];
//A[14] = A[20];
//A[20] = A[ 2];
//A[ 2] = A[12];
//A[12] = A[13];
//A[13] = A[19];
//A[19] = A[23];
//A[23] = A[15];
//A[15] = A[ 4];
//A[ 4] = A[24];
//A[24] = A[21];
//A[21] = A[ 8];
//A[ 8] = A[16];
//A[16] = A[ 5];
//A[ 5] = A[ 3];
//A[ 3] = A[18];
//A[18] = A[17];
//A[17] = A[11];
//A[11] = A[ 7];
//A[ 7] = A[10];
//A[10] = A1;
//return;
unsigned x = 1, y = 0;
uint64_t current = m_words[y][x];
uint64_t temp;
// Iterate over ((0 1)(2 3))^t * (1 0) for 0 ≤ t ≤ 23
for (unsigned t = 0; t < 24; ++t) {
unsigned int Y = (2*x+3*y)%5;
x = y;
y = Y;
temp = m_words[y][x];
m_words[y][x] = current;
current = temp;
}
//for (unsigned int i = 0; i < 5; ++i)
// for (unsigned int j = 0; j < 5; ++j)
// m_words[j][(2*i+3*j)%5] = m_words[i][j];
}
/**
* Function that computes the Keccak-f[1600] permutation on the given state.
*/
void
keccak::permute (void)
{
for (size_t i = 0; i < m_bitrate/64; ++i)
m_words[i/5][i%5] = util::ltoh (m_words[i/5][i%5]);
lfsr86540 shift;
for (unsigned round = 0; round < 24; ++round) {
permute_theta (m_words);
permute_rho (m_words);
permute_pi (m_words);
if (0) { // === ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) ===
uint64_t current, temp;
// Start at coordinates (1 0)
unsigned x = 1, y = 0;
current = m_words[y][x];
// Iterate over ((0 1)(2 3))^t * (1 0) for 0 ≤ t ≤ 23
for (unsigned t = 0; t < 24; ++t) {
// Compute the rotation constant r = (t+1)(t+2)/2
unsigned int r = ((t+1)*(t+2)/2)%64;
// Compute ((0 1)(2 3)) * (x y)
unsigned int Y = (2*x+3*y)%5; x = y; y = Y;
// Swap current and state(x,y), and rotate
temp = m_words[y][x];
m_words[y][x] = util::rotatel (current, r);
current = temp;
}
}
{ // === χ step (see [Keccak Reference, Section 2.3.1]) ===
uint64_t temp[5];
for (unsigned y = 0; y < 5; ++y) {
// Take a copy of the plane
for (unsigned x = 0; x < 5; ++x)
temp[x] = m_words[y][x];
// Compute χ on the plane
for(unsigned x = 0; x < 5; ++x)
m_words[y][x] = temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5]);
}
}
{ // === ι step (see [Keccak Reference, Section 2.3.5]) ===
for (unsigned j = 0; j < 7; ++j) {
unsigned int bitPosition = (1 << j) - 1; //2^j-1
if (shift.update ())
m_words[0][0] ^= uint64_t{1} << bitPosition;
}
}
}
}
/*
================================================================
A readable and compact implementation of the Keccak sponge functions
that use the Keccak-f[1600] permutation.
================================================================
*/
void
keccak::update (
const uint8_t *input,
size_t len
) {
unsigned int byterate = m_bitrate / 8;
while (len) {
auto chunk = util::min (len, byterate - m_cursor);
for (unsigned i = 0; i < chunk; ++i)
m_bytes[m_cursor++] ^= *input++;
len -= chunk;
if (m_cursor == byterate) {
permute ();
m_cursor = 0;
}
}
}
void
keccak::digest (
uint8_t *output,
size_t len
) {
unsigned byterate = m_bitrate / 8u;
// === Do the padding and switch to the squeezing phase ===
// Absorb the last few bits and add the first bit of padding (which
// coincides with the delimiter in delimitedSuffix)
m_bytes[m_cursor] ^= m_suffix;
// If the first bit of padding is at position rate-1, we need a whole new
// block for the second bit of padding
if (m_suffix & 0x80 && m_cursor == byterate - 1)
permute ();
// Add the second bit of padding
m_bytes[byterate - 1] ^= 0x80;
// === Squeeze out all the output blocks ===
while (len) {
permute ();
auto chunk = util::min (len, byterate);
std::copy_n (m_bytes.begin (), chunk, output);
output += chunk;
len -= chunk;
}
}
keccak::keccak (unsigned _bitrate,
unsigned _capacity,
uint8_t _suffix):
m_bitrate (_bitrate),
m_capacity (_capacity),
m_suffix (_suffix),
m_cursor (0)
{
// we could support bitrates that are multiples of 8, but 64 simplifies
// some state handling, and the SHA-3 constants are all multiples of 64
// bits anyway.
if ((m_bitrate + m_capacity) / 8 != sizeof (m_bytes) || m_bitrate % 64 != 0)
throw "error";
std::fill (std::begin (m_bytes), std::end (m_bytes), 0);
}
#endif

View File

@ -1,53 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __HASH_KECCAK_HPP
#define __HASH_KECCAK_HPP
#include <array>
#include <cstdint>
class keccak {
public:
keccak (unsigned bitrate, unsigned capacity, uint8_t suffix);
void update (const uint8_t *input, size_t len);
void digest (uint8_t *output, size_t len);
private:
void permute (void);
const unsigned m_bitrate;
const unsigned m_capacity;
const uint8_t m_suffix;
size_t m_cursor;
union {
std::array<uint8_t, 200> m_bytes;
uint64_t m_words[5][5];
};
};
void FIPS202_SHAKE128(const uint8_t *input, size_t inputByteLen, uint8_t *output, size_t outputByteLen);
void FIPS202_SHAKE256(const uint8_t *input, size_t inputByteLen, uint8_t *output, size_t outputByteLen);
void FIPS202_SHA3_224(const uint8_t *input, size_t inputByteLen, uint8_t *output);
void FIPS202_SHA3_256(const uint8_t *input, size_t inputByteLen, uint8_t *output);
void FIPS202_SHA3_384(const uint8_t *input, size_t inputByteLen, uint8_t *output);
void FIPS202_SHA3_512(const uint8_t *input, size_t inputByteLen, uint8_t *output);
#endif

View File

@ -1,182 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#include "md2.hpp"
#include "../debug.hpp"
#include "../types.hpp"
#include <array>
#include <algorithm>
#include <cstring>
///////////////////////////////////////////////////////////////////////////////
using util::hash::MD2;
using std::array;
using std::begin;
using std::end;
using std::fill;
///////////////////////////////////////////////////////////////////////////////
static array<uint8_t,256> S = { {
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19,
98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202,
30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18,
190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122,
169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33,
128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3,
255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198,
79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241,
69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2,
27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38,
44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82,
106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74,
120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57,
242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20,
} };
///////////////////////////////////////////////////////////////////////////////
MD2::MD2 ()
{
reset ();
}
//-----------------------------------------------------------------------------
void
MD2::reset (void)
{
m_total = 0;
fill (begin (C), end (C), 0);
fill (begin (X), end (X), 0);
}
///////////////////////////////////////////////////////////////////////////////
void
MD2::update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept
{
CHECK_LE (first, last);
update (first, last - first);
}
//-----------------------------------------------------------------------------
static const size_t M_OFFSET = 16;
static const size_t M_LENGTH = 16;
//-----------------------------------------------------------------------------
void
MD2::update (const void *restrict _data, size_t size) noexcept
{
auto data = static_cast<const uint8_t *restrict> (_data);
uint8_t *M = X + M_OFFSET;
size_t offset = m_total % M_LENGTH;
size_t remain = M_LENGTH - offset;
if (size > remain) {
memcpy (M + offset, data, remain);
transform ();
m_total += remain;
size -= remain;
data += remain;
while (size >= M_LENGTH) {
memcpy (M, data, M_LENGTH);
transform ();
m_total += M_LENGTH;
size -= M_LENGTH;
data += M_LENGTH;
}
offset = 0;
}
memcpy (M + offset, data, size);
m_total += size;
}
///////////////////////////////////////////////////////////////////////////////
MD2::digest_t
MD2::digest (void) const
{
digest_t d;
memcpy (d.data (), X, sizeof (d));
return d;
}
///////////////////////////////////////////////////////////////////////////////
void
MD2::transform (void)
{
uint8_t *M = X + M_OFFSET;
// Update the checksum.
// XXX: I can't see why we need the xor-assign from the spec, but it's the
// only change keeping us from conforming to the test-cases. Pulled from a
// review of the reference implementation.
uint8_t L = C[15];
for (size_t i = 0; i < std::size (C); ++i)
L = C[i] ^= S[M[i] ^ L];
uint8_t t = 0;
// Setup the blocks
for (size_t i = 0; i < 16; ++i)
X[32 + i] = X[16 + i] ^ X[i];
// Perform the processing rounds
for (size_t i = 0; i < 18; ++i) {
for (size_t j = 0; j < 48; ++j)
t = X[j] = X[j] ^ S[t];
t = (t + i) % 256;
}
}
///////////////////////////////////////////////////////////////////////////////
void
MD2::finish (void)
{
uint8_t *M = X + M_OFFSET;
// Append the padding bytes
size_t offset = m_total % M_LENGTH;
size_t remain = M_LENGTH - offset;
for (size_t i = 0; i < remain; ++i)
M[offset + i] = remain;
transform ();
// Append the checksum
memcpy (M, C, sizeof (C));
transform ();
}

View File

@ -1,50 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_MD2_HPP
#define __UTIL_HASH_MD2_HPP
#include <array>
#include <cstdint>
///////////////////////////////////////////////////////////////////////////////
namespace util::hash {
class MD2 {
public:
typedef std::array<uint8_t,16> digest_t;
public:
MD2 ();
void update (const void *restrict data, size_t len) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
void reset (void);
private:
void transform (void);
uint64_t m_total;
uint8_t C[16];
uint8_t X[48];
};
}
#endif

View File

@ -1,269 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#include "md4.hpp"
#include "../bitwise.hpp"
#include "../debug.hpp"
#include <cstring>
using util::hash::MD4;
///////////////////////////////////////////////////////////////////////////////
// Auxiliary functions for each set of rounds
static constexpr
uint32_t
F (uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) | (~X & Z);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
G (uint32_t X, uint32_t Y, uint32_t Z)
{
return (X & Y) | (X & Z) | (Y & Z);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
H (uint32_t X, uint32_t Y, uint32_t Z)
{
return X ^ Y ^ Z;
}
//-----------------------------------------------------------------------------
static constexpr uint32_t DEFAULT_A = 0x67452301;
static constexpr uint32_t DEFAULT_B = 0xefcdab89;
static constexpr uint32_t DEFAULT_C = 0x98badcfe;
static constexpr uint32_t DEFAULT_D = 0x10325476;
///////////////////////////////////////////////////////////////////////////////
MD4::MD4 ()
{
reset ();
static_assert (sizeof (MD4::X) == sizeof (MD4::Xb),
"Byte and word buffer size must match exactly");
static_assert (sizeof (MD4::ABCD) == sizeof (MD4::digest_t),
"Internal state must match the size of the digest");
}
//-----------------------------------------------------------------------------
void
MD4::reset (void)
{
m_total = 0;
ABCD[0] = DEFAULT_A;
ABCD[1] = DEFAULT_B;
ABCD[2] = DEFAULT_C;
ABCD[3] = DEFAULT_D;
memset (Xb, 0, sizeof (Xb));
}
///////////////////////////////////////////////////////////////////////////////
void
MD4::update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept
{
CHECK_LE (first, last);
update (first, last - first);
}
//-----------------------------------------------------------------------------
void
MD4::update (const void *restrict _data, size_t size) noexcept
{
CHECK (_data);
auto data = static_cast<const uint8_t *restrict> (_data);
size_t offset = m_total % sizeof (Xb);
size_t remain = sizeof (Xb) - offset;
if (size > remain) {
memcpy (Xb + offset, data, remain);
transform ();
m_total += remain;
size -= remain;
data += remain;
while (size >= sizeof (Xb)) {
memcpy (Xb, data, sizeof (Xb));
transform ();
m_total += sizeof (Xb);
size -= sizeof (Xb);
data += sizeof (Xb);
}
offset = 0;
}
memcpy (Xb + offset, data, size);
m_total += size;
}
///////////////////////////////////////////////////////////////////////////////
MD4::digest_t
MD4::digest (void) const
{
digest_t d;
memcpy (d.data (), ABCD.data(), sizeof (ABCD));
return d;
}
///////////////////////////////////////////////////////////////////////////////
void
MD4::transform (void)
{
uint32_t A = ABCD[0],
B = ABCD[1],
C = ABCD[2],
D = ABCD[3];
#define ROUND1(a,b,c,d,k,s) do { \
(a) += F((b), (c), (d)) + X[k]; \
(a) = rotatel ((a), (s)); \
} while (0)
ROUND1(A,B,C,D, 0, 3);
ROUND1(D,A,B,C, 1, 7);
ROUND1(C,D,A,B, 2, 11);
ROUND1(B,C,D,A, 3, 19);
ROUND1(A,B,C,D, 4, 3);
ROUND1(D,A,B,C, 5, 7);
ROUND1(C,D,A,B, 6, 11);
ROUND1(B,C,D,A, 7, 19);
ROUND1(A,B,C,D, 8, 3);
ROUND1(D,A,B,C, 9, 7);
ROUND1(C,D,A,B, 10, 11);
ROUND1(B,C,D,A, 11, 19);
ROUND1(A,B,C,D, 12, 3);
ROUND1(D,A,B,C, 13, 7);
ROUND1(C,D,A,B, 14, 11);
ROUND1(B,C,D,A, 15, 19);
#define ROUND2(a,b,c,d,k,s) do { \
(a) += G((b),(c),(d)) + X[k] + 0x5A827999u; \
(a) = rotatel ((a), (s)); \
} while (0)
ROUND2(A,B,C,D, 0, 3);
ROUND2(D,A,B,C, 4, 5);
ROUND2(C,D,A,B, 8, 9);
ROUND2(B,C,D,A, 12, 13);
ROUND2(A,B,C,D, 1, 3);
ROUND2(D,A,B,C, 5, 5);
ROUND2(C,D,A,B, 9, 9);
ROUND2(B,C,D,A, 13, 13);
ROUND2(A,B,C,D, 2, 3);
ROUND2(D,A,B,C, 6, 5);
ROUND2(C,D,A,B, 10, 9);
ROUND2(B,C,D,A, 14, 13);
ROUND2(A,B,C,D, 3, 3);
ROUND2(D,A,B,C, 7, 5);
ROUND2(C,D,A,B, 11, 9);
ROUND2(B,C,D,A, 15, 13);
#define ROUND3(a,b,c,d,k,s) do { \
(a) += H((b),(c),(d)) + X[k] + 0x6ED9EBA1u; \
(a) = rotatel ((a), (s)); \
} while (0)
ROUND3(A,B,C,D, 0, 3);
ROUND3(D,A,B,C, 8, 9);
ROUND3(C,D,A,B, 4, 11);
ROUND3(B,C,D,A, 12, 15);
ROUND3(A,B,C,D, 2, 3);
ROUND3(D,A,B,C, 10, 9);
ROUND3(C,D,A,B, 6, 11);
ROUND3(B,C,D,A, 14, 15);
ROUND3(A,B,C,D, 1, 3);
ROUND3(D,A,B,C, 9, 9);
ROUND3(C,D,A,B, 5, 11);
ROUND3(B,C,D,A, 13, 15);
ROUND3(A,B,C,D, 3, 3);
ROUND3(D,A,B,C, 11, 9);
ROUND3(C,D,A,B, 7, 11);
ROUND3(B,C,D,A, 15, 15);
ABCD[0] += A;
ABCD[1] += B;
ABCD[2] += C;
ABCD[3] += D;
}
///////////////////////////////////////////////////////////////////////////////
void
MD4::finish (void)
{
uint64_t bits = m_total * 8;
{
// Pad with the mandatory 1 bit
size_t offset = m_total % sizeof (Xb);
Xb[offset] = 0x80;
}
{
// Pad the remainder with 0's, until 56 bytes
size_t offset = (m_total + 1) % sizeof (Xb);
size_t remain = (56 - offset % sizeof (Xb)) % sizeof (Xb);
if (offset > 56) {
memset (Xb + offset, 0, sizeof (Xb) - offset);
transform ();
remain -= sizeof (Xb) - offset;
offset = 0;
}
memset (Xb + offset, 0, remain);
// Put in the length (in bits) least significant first
for (size_t i = 0; i < sizeof (bits); ++i) {
Xb[56 + i] = bits & 0xFF;
bits >>= 8;
}
transform ();
}
}

View File

@ -1,53 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_MD4_HPP
#define __UTIL_HASH_MD4_HPP
#include <array>
#include <cstdint>
///////////////////////////////////////////////////////////////////////////////
namespace util::hash {
class MD4 {
public:
typedef std::array<uint8_t,16> digest_t;
public:
MD4();
void update (const void *restrict data, size_t len) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
void reset (void);
private:
void transform (void);
uint64_t m_total;
std::array<uint32_t,4> ABCD;
union {
uint32_t X [16];
uint8_t Xb[64];
};
};
}
#endif

View File

@ -1,322 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#include "md5.hpp"
#include "../bitwise.hpp"
#include "../debug.hpp"
#include <cstring>
using util::hash::MD5;
///////////////////////////////////////////////////////////////////////////////
// Per-round mixing functions
static constexpr
uint32_t
F (uint32_t x, uint32_t y, uint32_t z)
{
return z ^ (x & (y ^ z));
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
G (uint32_t x, uint32_t y, uint32_t z)
{
return F (z, x, y);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
H (uint32_t x, uint32_t y, uint32_t z)
{
return x ^ y ^ z;
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
I (uint32_t x, uint32_t y, uint32_t z)
{
return y ^ (x | ~z);
}
///////////////////////////////////////////////////////////////////////////////
// Mixing constants for all rounds. They are defined as 'abs(sin(i)) * max_uint32', but we use the
// literals to avoid any stupid maths issues during compilation.
const std::array<uint32_t, 65> T = { {
0x00000000,
// Round 1
0xd76aa478u, 0xe8c7b756u, 0x242070dbu, 0xc1bdceeeu,
0xf57c0fafu, 0x4787c62au, 0xa8304613u, 0xfd469501u,
0x698098d8u, 0x8b44f7afu, 0xffff5bb1u, 0x895cd7beu,
0x6b901122u, 0xfd987193u, 0xa679438eu, 0x49b40821u,
// Round 2
0xf61e2562u, 0xc040b340u, 0x265e5a51u, 0xe9b6c7aau,
0xd62f105du, 0x02441453u, 0xd8a1e681u, 0xe7d3fbc8u,
0x21e1cde6u, 0xc33707d6u, 0xf4d50d87u, 0x455a14edu,
0xa9e3e905u, 0xfcefa3f8u, 0x676f02d9u, 0x8d2a4c8au,
// Round 3
0xfffa3942u, 0x8771f681u, 0x6d9d6122u, 0xfde5380cu,
0xa4beea44u, 0x4bdecfa9u, 0xf6bb4b60u, 0xbebfbc70u,
0x289b7ec6u, 0xeaa127fau, 0xd4ef3085u, 0x04881d05u,
0xd9d4d039u, 0xe6db99e5u, 0x1fa27cf8u, 0xc4ac5665u,
// Round 4
0xf4292244u, 0x432aff97u, 0xab9423a7u, 0xfc93a039u,
0x655b59c3u, 0x8f0ccc92u, 0xffeff47du, 0x85845dd1u,
0x6fa87e4fu, 0xfe2ce6e0u, 0xa3014314u, 0x4e0811a1u,
0xf7537e82u, 0xbd3af235u, 0x2ad7d2bbu, 0xeb86d391u
} };
//-----------------------------------------------------------------------------
static const uint32_t DEFAULT_A = 0x67452301;
static const uint32_t DEFAULT_B = 0xefcdab89;
static const uint32_t DEFAULT_C = 0x98badcfe;
static const uint32_t DEFAULT_D = 0x10325476;
///////////////////////////////////////////////////////////////////////////////
MD5::MD5()
{
reset ();
}
//-----------------------------------------------------------------------------
void
MD5::reset (void)
{
m_total = 0;
ABCD[0] = DEFAULT_A;
ABCD[1] = DEFAULT_B;
ABCD[2] = DEFAULT_C;
ABCD[3] = DEFAULT_D;
}
///////////////////////////////////////////////////////////////////////////////
void
MD5::update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept
{
CHECK_LE (first, last);
update (first, last - first);
}
//-----------------------------------------------------------------------------
void
MD5::update (const void *restrict _data, size_t size) noexcept
{
CHECK (_data);
auto data = static_cast<const uint8_t *restrict> (_data);
size_t offset = m_total % sizeof (Xb);
size_t remain = sizeof (Xb) - offset;
if (size >= remain) {
memcpy (Xb + offset, data, remain);
transform ();
m_total += remain;
size -= remain;
data += remain;
while (size >= sizeof (Xb)) {
memcpy (Xb, data, sizeof (Xb));
transform ();
m_total += sizeof (Xb);
size -= sizeof (Xb);
data += sizeof (Xb);
}
offset = 0;
}
memcpy (Xb + offset, data, size);
m_total += size;
}
///////////////////////////////////////////////////////////////////////////////
MD5::digest_t
MD5::digest (void) const
{
static_assert (sizeof (ABCD) == sizeof (digest_t),
"Hash state must be the same size as the final digest");
digest_t d;
memcpy (d.data (), ABCD.data (), sizeof (ABCD));
return d;
}
///////////////////////////////////////////////////////////////////////////////
void
MD5::finish (void)
{
uint64_t bits = m_total * 8;
{
// Pad with the mandatory 1 bit
size_t offset = m_total % sizeof (Xb);
Xb[offset] = 0x80;
}
{
// Pad the remainder with 0's, until 56 bytes
size_t offset = (m_total + 1) % sizeof (Xb);
size_t remain = (56 - offset % sizeof (Xb)) % sizeof (Xb);
if (offset > 56) {
memset (Xb + offset, 0, sizeof (Xb) - offset);
transform ();
remain -= sizeof (Xb) - offset;
offset = 0;
}
memset (Xb + offset, 0, remain);
// Put in the length (in bits) least significant first
for (size_t i = 0; i < sizeof (bits); ++i) {
Xb[56 + i] = bits & 0xFF;
bits >>= 8;
}
transform ();
}
}
///////////////////////////////////////////////////////////////////////////////
void
MD5::transform (void)
{
uint32_t A = ABCD[0],
B = ABCD[1],
C = ABCD[2],
D = ABCD[3];
#define ROUNDx(a,b,c,d,k,s,i,f) do { \
(a) += (f)((b), (c), (d)) + X[k] + T[i]; \
(a) = rotatel ((a), (s)); \
(a) += (b); \
} while (0)
// Round 1
ROUNDx(A,B,C,D, 0, 7, 1, F);
ROUNDx(D,A,B,C, 1, 12, 2, F);
ROUNDx(C,D,A,B, 2, 17, 3, F);
ROUNDx(B,C,D,A, 3, 22, 4, F);
ROUNDx(A,B,C,D, 4, 7, 5, F);
ROUNDx(D,A,B,C, 5, 12, 6, F);
ROUNDx(C,D,A,B, 6, 17, 7, F);
ROUNDx(B,C,D,A, 7, 22, 8, F);
ROUNDx(A,B,C,D, 8, 7, 9, F);
ROUNDx(D,A,B,C, 9, 12, 10, F);
ROUNDx(C,D,A,B, 10, 17, 11, F);
ROUNDx(B,C,D,A, 11, 22, 12, F);
ROUNDx(A,B,C,D, 12, 7, 13, F);
ROUNDx(D,A,B,C, 13, 12, 14, F);
ROUNDx(C,D,A,B, 14, 17, 15, F);
ROUNDx(B,C,D,A, 15, 22, 16, F);
// Round 2
ROUNDx(A,B,C,D, 1, 5, 17, G);
ROUNDx(D,A,B,C, 6, 9, 18, G);
ROUNDx(C,D,A,B, 11, 14, 19, G);
ROUNDx(B,C,D,A, 0, 20, 20, G);
ROUNDx(A,B,C,D, 5, 5, 21, G);
ROUNDx(D,A,B,C, 10, 9, 22, G);
ROUNDx(C,D,A,B, 15, 14, 23, G);
ROUNDx(B,C,D,A, 4, 20, 24, G);
ROUNDx(A,B,C,D, 9, 5, 25, G);
ROUNDx(D,A,B,C, 14, 9, 26, G);
ROUNDx(C,D,A,B, 3, 14, 27, G);
ROUNDx(B,C,D,A, 8, 20, 28, G);
ROUNDx(A,B,C,D, 13, 5, 29, G);
ROUNDx(D,A,B,C, 2, 9, 30, G);
ROUNDx(C,D,A,B, 7, 14, 31, G);
ROUNDx(B,C,D,A, 12, 20, 32, G);
// Round 3
ROUNDx(A,B,C,D, 5, 4, 33, H);
ROUNDx(D,A,B,C, 8, 11, 34, H);
ROUNDx(C,D,A,B, 11, 16, 35, H);
ROUNDx(B,C,D,A, 14, 23, 36, H);
ROUNDx(A,B,C,D, 1, 4, 37, H);
ROUNDx(D,A,B,C, 4, 11, 38, H);
ROUNDx(C,D,A,B, 7, 16, 39, H);
ROUNDx(B,C,D,A, 10, 23, 40, H);
ROUNDx(A,B,C,D, 13, 4, 41, H);
ROUNDx(D,A,B,C, 0, 11, 42, H);
ROUNDx(C,D,A,B, 3, 16, 43, H);
ROUNDx(B,C,D,A, 6, 23, 44, H);
ROUNDx(A,B,C,D, 9, 4, 45, H);
ROUNDx(D,A,B,C, 12, 11, 46, H);
ROUNDx(C,D,A,B, 15, 16, 47, H);
ROUNDx(B,C,D,A, 2, 23, 48, H);
// Round 4
ROUNDx(A,B,C,D, 0, 6, 49, I);
ROUNDx(D,A,B,C, 7, 10, 50, I);
ROUNDx(C,D,A,B, 14, 15, 51, I);
ROUNDx(B,C,D,A, 5, 21, 52, I);
ROUNDx(A,B,C,D, 12, 6, 53, I);
ROUNDx(D,A,B,C, 3, 10, 54, I);
ROUNDx(C,D,A,B, 10, 15, 55, I);
ROUNDx(B,C,D,A, 1, 21, 56, I);
ROUNDx(A,B,C,D, 8, 6, 57, I);
ROUNDx(D,A,B,C, 15, 10, 58, I);
ROUNDx(C,D,A,B, 6, 15, 59, I);
ROUNDx(B,C,D,A, 13, 21, 60, I);
ROUNDx(A,B,C,D, 4, 6, 61, I);
ROUNDx(D,A,B,C, 11, 10, 62, I);
ROUNDx(C,D,A,B, 2, 15, 63, I);
ROUNDx(B,C,D,A, 9, 21, 64, I);
ABCD[0] += A;
ABCD[1] += B;
ABCD[2] += C;
ABCD[3] += D;
}

View File

@ -1,56 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_MD5_HPP
#define __UTIL_HASH_MD5_HPP
#include <array>
#include <cstdint>
#include <cstdlib>
///////////////////////////////////////////////////////////////////////////////
namespace util::hash {
class MD5 {
public:
typedef std::array<uint8_t,16> digest_t;
static const size_t BLOCK_SIZE = 64;
static const size_t DIGEST_SIZE = 16;
public:
MD5();
void update (const void *restrict data, size_t len) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
void reset (void);
private:
void transform (void);
uint64_t m_total;
std::array<uint32_t, 4> ABCD;
union {
uint32_t X [16];
uint8_t Xb[64];
};
};
}
#endif

View File

@ -19,40 +19,25 @@
#include "common.hpp"
#include "../../debug.hpp"
//-----------------------------------------------------------------------------
using util::hash::murmur1;
///////////////////////////////////////////////////////////////////////////////
uint32_t
util::hash::murmur1::mix (uint32_t h, uint32_t k)
murmur1::operator() (util::view<const uint8_t*> data) const noexcept
{
static const uint32_t m = 0xc6a4a793;
h += k;
h *= m;
h ^= h >> 16;
return h;
}
//-----------------------------------------------------------------------------
uint32_t
util::hash::murmur1::hash_32 (const void *restrict data,
size_t len,
uint32_t seed)
{
CHECK (data);
static const uint32_t m = 0xc6a4a793;
uint32_t h = seed ^ ((len & 0xffffffff) * m);
uint32_t h = m_seed ^ ((data.size () & 0xffffffff) * m);
// mix the body
auto cursor = reinterpret_cast<const uint32_t*> (data);
auto last = cursor + len / sizeof (uint32_t);
auto cursor = reinterpret_cast<const uint32_t*> (data.data ());
auto last = cursor + data.size () / sizeof (uint32_t);
for (; cursor < last; ++cursor)
h = mix (h, *cursor);
// mix the tail
if (len % sizeof (uint32_t))
h = mix (h, murmur::tail<uint32_t> (reinterpret_cast<const uint8_t*> (cursor), len));
if (data.size () % sizeof (uint32_t))
h = mix (h, murmur::tail<uint32_t> (reinterpret_cast<const uint8_t*> (cursor), data.size ()));
// finalise
h *= m; h ^= h >> 10;

View File

@ -17,13 +17,38 @@
#ifndef __UTIL_HASH_MURMUR_MURMUR1_HPP
#define __UTIL_HASH_MURMUR_MURMUR1_HPP
#include "../../view.hpp"
#include <cstdint>
#include <cstddef>
// Austin Appleby's MumurHash1
namespace util::hash::murmur1 {
uint32_t mix (uint32_t, uint32_t);
uint32_t hash_32 (const void *restrict data, size_t len, uint32_t seed);
namespace util::hash {
class murmur1 {
public:
using digest_t = uint32_t;
using seed_t = uint32_t;
murmur1 (seed_t _seed):
m_seed (_seed)
{ ; }
static constexpr uint32_t mix (uint32_t h, uint32_t k)
{
constexpr uint32_t m = 0xc6a4a793;
h += k;
h *= m;
h ^= h >> 16;
return h;
}
digest_t operator() (util::view<const uint8_t*> data) const noexcept;
private:
seed_t m_seed;
};
}
#endif

View File

@ -20,28 +20,28 @@
#include "../../debug.hpp"
#include "common.hpp"
using util::hash::murmur2;
///////////////////////////////////////////////////////////////////////////////
uint32_t
util::hash::murmur2::hash_32 (const void *restrict key,
static uint32_t
hash_32 (const void *restrict key,
size_t len,
uint32_t seed)
{
CHECK (key);
// setup
constexpr auto m = detail::constants<uint32_t>::m;
constexpr auto m = util::hash::detail::murmur2::constants<uint32_t>::m;
uint32_t h = seed ^ (len & 0xffffffff);
// body
auto cursor = reinterpret_cast<const uint32_t*> (key);
auto last = cursor + len / sizeof (uint32_t);
for (; cursor < last; ++cursor)
h = mix (h, *cursor);
h = util::hash::murmur2<uint32_t>::mix (h, *cursor);
// tail
if (len % sizeof (uint32_t)) {
h ^= murmur::tail<uint32_t> (reinterpret_cast<const uint8_t*> (cursor), len);
h ^= util::hash::murmur::tail<uint32_t> (reinterpret_cast<const uint8_t*> (cursor), len);
h *= m;
}
@ -55,14 +55,14 @@ util::hash::murmur2::hash_32 (const void *restrict key,
//-----------------------------------------------------------------------------
uint64_t
util::hash::murmur2::hash_64 (const void *restrict key,
static uint64_t
hash_64 (const void *restrict key,
size_t len,
uint64_t seed)
{
// setup
constexpr auto m = detail::constants<uint64_t>::m;
constexpr auto r = detail::constants<uint64_t>::r;
constexpr auto m = util::hash::detail::murmur2::constants<uint64_t>::m;
constexpr auto r = util::hash::detail::murmur2::constants<uint64_t>::r;
uint64_t h = seed ^ (len * m);
@ -70,11 +70,11 @@ util::hash::murmur2::hash_64 (const void *restrict key,
auto cursor = reinterpret_cast<const uint64_t*> (key);
auto last = cursor + len / sizeof (uint64_t);
for (; cursor < last; ++cursor)
h = mix (h, *cursor);
h = util::hash::murmur2<uint64_t>::mix (h, *cursor);
// tail
if (len % sizeof (uint64_t)) {
h ^= murmur::tail<uint64_t> (reinterpret_cast<const uint8_t*> (cursor), len);
h ^= util::hash::murmur::tail<uint64_t> (reinterpret_cast<const uint8_t*> (cursor), len);
h *= m;
}
@ -87,3 +87,23 @@ util::hash::murmur2::hash_64 (const void *restrict key,
}
///////////////////////////////////////////////////////////////////////////////
template <typename DigestT>
typename murmur2<DigestT>::digest_t
murmur2<DigestT>::operator() (util::view<const uint8_t*> data) const noexcept
{
static_assert (std::is_same_v<DigestT,uint32_t> || std::is_same_v<DigestT,uint64_t>);
if constexpr (std::is_same_v<DigestT,uint32_t>)
return hash_32 (data.data (), data.size (), m_seed);
if constexpr (std::is_same_v<DigestT,uint64_t>)
return hash_64 (data.data (), data.size (), m_seed);
unreachable ();
}
///////////////////////////////////////////////////////////////////////////////
template class util::hash::murmur2<uint32_t>;
template class util::hash::murmur2<uint64_t>;

View File

@ -17,21 +17,77 @@
#ifndef __UTIL_HASH_MURMUR_MURMUR2_HPP
#define __UTIL_HASH_MURMUR_MURMUR2_HPP
#include "../../view.hpp"
#include <cstddef>
#include <cstdint>
// Austin Appleby's MumurHash2, and MurmurHash64A. The exhaustive list of
// variants is deliberately not provided. You can damn well align your data or
// fix the algorithm.
namespace util::hash::murmur2 {
constexpr uint32_t mix (uint32_t, uint32_t);
constexpr uint64_t mix (uint64_t, uint64_t);
namespace util::hash {
namespace detail::murmur2 {
template <typename T> struct constants;
uint32_t hash_32 (const void *restrict data, size_t len, uint32_t seed);
uint64_t hash_64 (const void *restrict data, size_t len, uint64_t seed);
template <>
struct constants<uint32_t> {
static const uint32_t m = 0x5bd1e995;
static const int32_t r = 24;
};
template <>
struct constants<uint64_t> {
static const uint64_t m = 0xc6a4a7935bd1e995;
static const int64_t r = 47;
};
}
#include "murmur2.ipp"
template <typename DigestT>
class murmur2 {
public:
using digest_t = DigestT;
using seed_t = DigestT;
murmur2 (seed_t _seed):
m_seed (_seed)
{ ; }
static constexpr uint32_t mix (uint32_t h, uint32_t k)
{
constexpr uint32_t m = detail::murmur2::constants<uint32_t>::m;
constexpr uint32_t r = detail::murmur2::constants<uint32_t>::r;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
return h;
}
static constexpr uint64_t mix (uint64_t h, uint64_t k)
{
constexpr uint64_t m = detail::murmur2::constants<uint64_t>::m;
constexpr uint64_t r = detail::murmur2::constants<uint64_t>::r;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
return h;
}
digest_t operator() (util::view<const uint8_t*> data) const noexcept;
private:
seed_t m_seed;
};
}
#endif

View File

@ -1,78 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/
#if defined(__UTIL_HASH_MURMUR_MURMUR2_IPP)
#error
#endif
#define __UTIL_HASH_MURMUR_MURMUR2_IPP
///////////////////////////////////////////////////////////////////////////////
namespace util::hash::murmur2::detail {
template <typename T> struct constants;
template <>
struct constants<uint32_t> {
static const uint32_t m = 0x5bd1e995;
static const int32_t r = 24;
};
template <>
struct constants<uint64_t> {
static const uint64_t m = 0xc6a4a7935bd1e995;
static const int64_t r = 47;
};
}
/////////////////////////////////////////////////////////////////////
constexpr uint32_t
util::hash::murmur2::mix (uint32_t h, uint32_t k)
{
constexpr uint32_t m = detail::constants<uint32_t>::m;
constexpr uint32_t r = detail::constants<uint32_t>::r;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
return h;
}
//-----------------------------------------------------------------------------
// 64 bit murmur2 mixing function. Note the last two lines are swapped
// compared with 32 bit murmur2_mix. It's not clear if this is deliberate
// in the canonical implementation, so we just leave it to help compatibility.
constexpr uint64_t
util::hash::murmur2::mix (uint64_t h, uint64_t k)
{
constexpr uint64_t m = detail::constants<uint64_t>::m;
constexpr uint64_t r = detail::constants<uint64_t>::r;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
return h;
}

View File

@ -21,6 +21,8 @@
#include <algorithm>
using util::hash::murmur3;
///////////////////////////////////////////////////////////////////////////////
static
@ -36,8 +38,9 @@ read_u32 (const uint8_t *bytes)
///////////////////////////////////////////////////////////////////////////////
// Finalization mix - force all bits of a hash block to avalanche
template <size_t DigestBits, size_t ArchBits>
uint32_t
util::hash::murmur3::mix (uint32_t h)
murmur3<DigestBits,ArchBits>::mix (uint32_t h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
@ -50,8 +53,9 @@ util::hash::murmur3::mix (uint32_t h)
//-----------------------------------------------------------------------------
template <size_t DigestBits, size_t ArchBits>
uint64_t
util::hash::murmur3::mix (uint64_t k)
murmur3<DigestBits,ArchBits>::mix (uint64_t k)
{
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
@ -63,14 +67,17 @@ util::hash::murmur3::mix (uint64_t k)
}
///////////////////////////////////////////////////////////////////////////////
template <size_t DigestBits, size_t ArchBits>
struct hash { };
//-----------------------------------------------------------------------------
uint32_t
util::hash::murmur3::hash_32(const void *restrict key,
size_t len,
uint32_t seed)
template <size_t ArchBits>
struct hash<32,ArchBits> {
static auto eval (util::view<const uint8_t*> data, uint32_t seed)
{
auto data = reinterpret_cast<const uint8_t*> (key);
auto nblocks = len / sizeof (uint32_t);
auto nblocks = data.size () / sizeof (uint32_t);
uint32_t h1 = seed;
@ -79,7 +86,7 @@ util::hash::murmur3::hash_32(const void *restrict key,
//----------
// body
auto cursor = data;
auto cursor = data.begin ();
auto last = cursor + nblocks * sizeof (uint32_t);
for (; cursor < last; cursor += sizeof (uint32_t)) {
uint32_t k1 = read_u32 (cursor);
@ -96,8 +103,8 @@ util::hash::murmur3::hash_32(const void *restrict key,
//----------
// tail
if (len % sizeof (uint32_t)) {
uint32_t k1 = 0 ^ murmur::tail<uint32_t> (cursor, len);
if (data.size () % sizeof (uint32_t)) {
uint32_t k1 = 0 ^ util::hash::murmur::tail<uint32_t> (cursor, data.size ());
k1 *= c1;
k1 = util::rotatel (k1, 15);
@ -108,11 +115,12 @@ util::hash::murmur3::hash_32(const void *restrict key,
//----------
// finalization
h1 ^= len;
h1 = mix (h1);
h1 ^= data.size ();
h1 = util::hash::murmur3<32,ArchBits>::mix (h1);
return h1;
}
};
///////////////////////////////////////////////////////////////////////////////
@ -237,7 +245,7 @@ hash_128 (const void *restrict key,
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i) h[i] += h[0];
for (auto &v: h)
v = util::hash::murmur3::mix (v);
v = util::hash::murmur3<128,sizeof(T)*8>::mix (v);
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i) h[0] += h[i];
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i) h[i] += h[0];
@ -246,21 +254,33 @@ hash_128 (const void *restrict key,
}
///////////////////////////////////////////////////////////////////////////////
std::array<uint32_t,4>
util::hash::murmur3::hash_128_x86 (const void *restrict key,
const size_t len,
const uint32_t seed)
template <>
struct hash<128,32> {
static auto eval (util::view<const uint8_t*> data, uint32_t seed)
{
return ::hash_128<uint32_t> (key, len, seed);
return ::hash_128<uint32_t> (data.data (), data.size (), seed);
}
};
template <>
struct hash<128,64> {
static auto eval (util::view<const uint8_t*> data, uint32_t seed)
{
return ::hash_128<uint64_t> (data.data (), data.size (), seed);
}
};
//-----------------------------------------------------------------------------
std::array<uint64_t,2>
util::hash::murmur3::hash_128_x64 (const void *restrict key,
size_t len,
const uint32_t seed)
template <size_t DigestBits, size_t ArchBits>
typename murmur3<DigestBits,ArchBits>::digest_t
murmur3<DigestBits,ArchBits>::operator() (util::view<const uint8_t*> data) const noexcept
{
return ::hash_128<uint64_t> (key, len, seed);
return ::hash<DigestBits,ArchBits>::eval (data, m_seed);
}
///////////////////////////////////////////////////////////////////////////////
template class util::hash::murmur3<32, 32>;
template class util::hash::murmur3<128,32>;
template class util::hash::murmur3<128,64>;

View File

@ -17,18 +17,47 @@
#ifndef __UTIL_HASH_MURMUR_MURMUR3_HPP
#define __UTIL_HASH_MURMUR_MURMUR3_HPP
#include "../../view.hpp"
#include <array>
#include <cstddef>
#include <cstdint>
// Austin Appleby's MurmurHash3
namespace util::hash::murmur3 {
uint32_t mix (uint32_t);
uint64_t mix (uint64_t);
namespace util::hash {
namespace detail::murmur3 {
template <size_t DigestBits, size_t ArchBits>
struct digest_type { };
uint32_t hash_32 (const void *restrict data, size_t len, uint32_t seed);
std::array<uint32_t,4> hash_128_x86 (const void *restrict data, size_t len, uint32_t seed);
std::array<uint64_t,2> hash_128_x64 (const void *restrict data, size_t len, uint32_t seed);
template <> struct digest_type< 32,32> { using type = uint32_t; };
template <> struct digest_type<128,32> { using type = std::array<uint32_t,4>; };
template <> struct digest_type<128,64> { using type = std::array<uint64_t,2>; };
};
template <size_t DigestBits, size_t ArchBits>
class murmur3 {
public:
murmur3 (uint32_t _seed):
m_seed (_seed)
{ ; }
static_assert (DigestBits % 8 == 0);
using digest_t = typename detail::murmur3::digest_type<DigestBits,ArchBits>::type;
static uint32_t mix (uint32_t);
static uint64_t mix (uint64_t);
digest_t
operator() (util::view<const uint8_t*> data) const noexcept;
private:
uint32_t m_seed;
};
using murmur3_32 = murmur3< 32,32>;
using murmur3_128_x86 = murmur3<128,32>;
using murmur3_128_x64 = murmur3<128,64>;
}
#endif

View File

@ -1,17 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#include "pbkdf1.hpp"

View File

@ -1,28 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_PBKDF1_HPP
#define __UTIL_HASH_PBKDF1_HPP
namespace util {
namespace hash {
class PBKDF1 {
};
}
}
#endif

View File

@ -1,17 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#include "pbkdf2.hpp"

View File

@ -1,28 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_PBKDF2_HPP
#define __UTIL_HASH_PBKDF2_HPP
namespace util {
namespace hash {
class PBKDF2 {
};
}
}
#endif

View File

@ -1,417 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright:
* 2014, Danny Robson <danny@nerdcruft.net>
*/
#include "ripemd.hpp"
#include "../debug.hpp"
#include "../bitwise.hpp"
#include <cstring>
using util::hash::RIPEMD;
///////////////////////////////////////////////////////////////////////////////
RIPEMD::RIPEMD()
{
reset ();
}
//-----------------------------------------------------------------------------
void
RIPEMD::reset (void)
{
m_state[0] = 0x67452301u;
m_state[1] = 0xEFCDAB89u;
m_state[2] = 0x98BADCFEu;
m_state[3] = 0x10325476u;
m_state[4] = 0xC3D2E1F0u;
m_length = 0;
m_buffer.size = 0;
}
///////////////////////////////////////////////////////////////////////////////
void
RIPEMD::update (
const uint8_t *restrict first,
const uint8_t *restrict last) noexcept
{
CHECK_LE (first, last);
update (first, last - first);
}
//-----------------------------------------------------------------------------
void
RIPEMD::update (const void *restrict _data, size_t len) noexcept
{
CHECK (_data);
auto data = static_cast<const uint8_t *restrict> (_data);
size_t cursor = 0;
while (cursor < len) {
size_t width = sizeof (m_buffer.d08) - m_buffer.size;
size_t chunk = min (width, len - cursor);
memcpy (m_buffer.d08 + m_buffer.size, data + cursor, chunk);
m_length += chunk;
m_buffer.size += chunk;
if (m_buffer.size == sizeof (m_buffer.d08))
transform ();
cursor += chunk;
}
if (m_length >> sizeof (m_length) * 8 - 3 != 0)
panic ("exceeded maximum message length");
}
///////////////////////////////////////////////////////////////////////////////
static constexpr
uint32_t
f1 (uint32_t x, uint32_t y, uint32_t z)
{
return x ^ y ^ z;
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
f2 (uint32_t x, uint32_t y, uint32_t z)
{
return (x & y) | (~x & z);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
f3 (uint32_t x, uint32_t y, uint32_t z)
{
return (x | ~y) ^ z;
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
f4 (uint32_t x, uint32_t y, uint32_t z)
{
return (x & z) | (y & ~z);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
f5 (uint32_t x, uint32_t y, uint32_t z)
{
return x ^ (y | ~z);
}
///////////////////////////////////////////////////////////////////////////////
void
RIPEMD::transform (void)
{
CHECK_EQ (m_buffer.size, sizeof (m_buffer.d32));
// Use: boolean function f
// state parameters a, b, c, d, e
// offset value o
// input data value x
// shift length s
#define ROUND(f,a,b,c,d,e,o,x,s) { \
a += f(b, c, d); \
a += m_buffer.d32[x] + o; \
a = rotatel (a, s); \
a += e; \
c = rotatel (c, 10); \
}
#define R1a(a,b,c,d,e,x,s) ROUND(f1,a,b,c,d,e,0x00000000u,x,s)
#define R2a(a,b,c,d,e,x,s) ROUND(f2,a,b,c,d,e,0x5A827999u,x,s)
#define R3a(a,b,c,d,e,x,s) ROUND(f3,a,b,c,d,e,0x6ED9EBA1u,x,s)
#define R4a(a,b,c,d,e,x,s) ROUND(f4,a,b,c,d,e,0x8F1BBCDCu,x,s)
#define R5a(a,b,c,d,e,x,s) ROUND(f5,a,b,c,d,e,0xA953FD4Eu,x,s)
#define R1b(a,b,c,d,e,x,s) ROUND(f5,a,b,c,d,e,0x50A28BE6u,x,s)
#define R2b(a,b,c,d,e,x,s) ROUND(f4,a,b,c,d,e,0x5C4DD124u,x,s)
#define R3b(a,b,c,d,e,x,s) ROUND(f3,a,b,c,d,e,0x6D703EF3u,x,s)
#define R4b(a,b,c,d,e,x,s) ROUND(f2,a,b,c,d,e,0x7A6D76E9u,x,s)
#define R5b(a,b,c,d,e,x,s) ROUND(f1,a,b,c,d,e,0x00000000u,x,s)
uint32_t a1, b1, c1, d1, e1;
uint32_t a2, b2, c2, d2, e2;
a1 = a2 = m_state[0];
b1 = b2 = m_state[1];
c1 = c2 = m_state[2];
d1 = d2 = m_state[3];
e1 = e2 = m_state[4];
// Left round 1
R1a(a1, b1, c1, d1, e1, 0, 11);
R1a(e1, a1, b1, c1, d1, 1, 14);
R1a(d1, e1, a1, b1, c1, 2, 15);
R1a(c1, d1, e1, a1, b1, 3, 12);
R1a(b1, c1, d1, e1, a1, 4, 5);
R1a(a1, b1, c1, d1, e1, 5, 8);
R1a(e1, a1, b1, c1, d1, 6, 7);
R1a(d1, e1, a1, b1, c1, 7, 9);
R1a(c1, d1, e1, a1, b1, 8, 11);
R1a(b1, c1, d1, e1, a1, 9, 13);
R1a(a1, b1, c1, d1, e1, 10, 14);
R1a(e1, a1, b1, c1, d1, 11, 15);
R1a(d1, e1, a1, b1, c1, 12, 6);
R1a(c1, d1, e1, a1, b1, 13, 7);
R1a(b1, c1, d1, e1, a1, 14, 9);
R1a(a1, b1, c1, d1, e1, 15, 8);
// Left round 2
R2a(e1, a1, b1, c1, d1, 7, 7);
R2a(d1, e1, a1, b1, c1, 4, 6);
R2a(c1, d1, e1, a1, b1, 13, 8);
R2a(b1, c1, d1, e1, a1, 1, 13);
R2a(a1, b1, c1, d1, e1, 10, 11);
R2a(e1, a1, b1, c1, d1, 6, 9);
R2a(d1, e1, a1, b1, c1, 15, 7);
R2a(c1, d1, e1, a1, b1, 3, 15);
R2a(b1, c1, d1, e1, a1, 12, 7);
R2a(a1, b1, c1, d1, e1, 0, 12);
R2a(e1, a1, b1, c1, d1, 9, 15);
R2a(d1, e1, a1, b1, c1, 5, 9);
R2a(c1, d1, e1, a1, b1, 2, 11);
R2a(b1, c1, d1, e1, a1, 14, 7);
R2a(a1, b1, c1, d1, e1, 11, 13);
R2a(e1, a1, b1, c1, d1, 8, 12);
// Left round 3
R3a(d1, e1, a1, b1, c1, 3, 11);
R3a(c1, d1, e1, a1, b1, 10, 13);
R3a(b1, c1, d1, e1, a1, 14, 6);
R3a(a1, b1, c1, d1, e1, 4, 7);
R3a(e1, a1, b1, c1, d1, 9, 14);
R3a(d1, e1, a1, b1, c1, 15, 9);
R3a(c1, d1, e1, a1, b1, 8, 13);
R3a(b1, c1, d1, e1, a1, 1, 15);
R3a(a1, b1, c1, d1, e1, 2, 14);
R3a(e1, a1, b1, c1, d1, 7, 8);
R3a(d1, e1, a1, b1, c1, 0, 13);
R3a(c1, d1, e1, a1, b1, 6, 6);
R3a(b1, c1, d1, e1, a1, 13, 5);
R3a(a1, b1, c1, d1, e1, 11, 12);
R3a(e1, a1, b1, c1, d1, 5, 7);
R3a(d1, e1, a1, b1, c1, 12, 5);
// Left round 4
R4a(c1, d1, e1, a1, b1, 1, 11);
R4a(b1, c1, d1, e1, a1, 9, 12);
R4a(a1, b1, c1, d1, e1, 11, 14);
R4a(e1, a1, b1, c1, d1, 10, 15);
R4a(d1, e1, a1, b1, c1, 0, 14);
R4a(c1, d1, e1, a1, b1, 8, 15);
R4a(b1, c1, d1, e1, a1, 12, 9);
R4a(a1, b1, c1, d1, e1, 4, 8);
R4a(e1, a1, b1, c1, d1, 13, 9);
R4a(d1, e1, a1, b1, c1, 3, 14);
R4a(c1, d1, e1, a1, b1, 7, 5);
R4a(b1, c1, d1, e1, a1, 15, 6);
R4a(a1, b1, c1, d1, e1, 14, 8);
R4a(e1, a1, b1, c1, d1, 5, 6);
R4a(d1, e1, a1, b1, c1, 6, 5);
R4a(c1, d1, e1, a1, b1, 2, 12);
// Left round 5
R5a(b1, c1, d1, e1, a1, 4, 9);
R5a(a1, b1, c1, d1, e1, 0, 15);
R5a(e1, a1, b1, c1, d1, 5, 5);
R5a(d1, e1, a1, b1, c1, 9, 11);
R5a(c1, d1, e1, a1, b1, 7, 6);
R5a(b1, c1, d1, e1, a1, 12, 8);
R5a(a1, b1, c1, d1, e1, 2, 13);
R5a(e1, a1, b1, c1, d1, 10, 12);
R5a(d1, e1, a1, b1, c1, 14, 5);
R5a(c1, d1, e1, a1, b1, 1, 12);
R5a(b1, c1, d1, e1, a1, 3, 13);
R5a(a1, b1, c1, d1, e1, 8, 14);
R5a(e1, a1, b1, c1, d1, 11, 11);
R5a(d1, e1, a1, b1, c1, 6, 8);
R5a(c1, d1, e1, a1, b1, 15, 5);
R5a(b1, c1, d1, e1, a1, 13, 6);
// Right round 1
R1b(a2, b2, c2, d2, e2, 5, 8);
R1b(e2, a2, b2, c2, d2, 14, 9);
R1b(d2, e2, a2, b2, c2, 7, 9);
R1b(c2, d2, e2, a2, b2, 0, 11);
R1b(b2, c2, d2, e2, a2, 9, 13);
R1b(a2, b2, c2, d2, e2, 2, 15);
R1b(e2, a2, b2, c2, d2, 11, 15);
R1b(d2, e2, a2, b2, c2, 4, 5);
R1b(c2, d2, e2, a2, b2, 13, 7);
R1b(b2, c2, d2, e2, a2, 6, 7);
R1b(a2, b2, c2, d2, e2, 15, 8);
R1b(e2, a2, b2, c2, d2, 8, 11);
R1b(d2, e2, a2, b2, c2, 1, 14);
R1b(c2, d2, e2, a2, b2, 10, 14);
R1b(b2, c2, d2, e2, a2, 3, 12);
R1b(a2, b2, c2, d2, e2, 12, 6);
// Right round 2
R2b(e2, a2, b2, c2, d2, 6, 9);
R2b(d2, e2, a2, b2, c2, 11, 13);
R2b(c2, d2, e2, a2, b2, 3, 15);
R2b(b2, c2, d2, e2, a2, 7, 7);
R2b(a2, b2, c2, d2, e2, 0, 12);
R2b(e2, a2, b2, c2, d2, 13, 8);
R2b(d2, e2, a2, b2, c2, 5, 9);
R2b(c2, d2, e2, a2, b2, 10, 11);
R2b(b2, c2, d2, e2, a2, 14, 7);
R2b(a2, b2, c2, d2, e2, 15, 7);
R2b(e2, a2, b2, c2, d2, 8, 12);
R2b(d2, e2, a2, b2, c2, 12, 7);
R2b(c2, d2, e2, a2, b2, 4, 6);
R2b(b2, c2, d2, e2, a2, 9, 15);
R2b(a2, b2, c2, d2, e2, 1, 13);
R2b(e2, a2, b2, c2, d2, 2, 11);
// Right round 3
R3b(d2, e2, a2, b2, c2, 15, 9);
R3b(c2, d2, e2, a2, b2, 5, 7);
R3b(b2, c2, d2, e2, a2, 1, 15);
R3b(a2, b2, c2, d2, e2, 3, 11);
R3b(e2, a2, b2, c2, d2, 7, 8);
R3b(d2, e2, a2, b2, c2, 14, 6);
R3b(c2, d2, e2, a2, b2, 6, 6);
R3b(b2, c2, d2, e2, a2, 9, 14);
R3b(a2, b2, c2, d2, e2, 11, 12);
R3b(e2, a2, b2, c2, d2, 8, 13);
R3b(d2, e2, a2, b2, c2, 12, 5);
R3b(c2, d2, e2, a2, b2, 2, 14);
R3b(b2, c2, d2, e2, a2, 10, 13);
R3b(a2, b2, c2, d2, e2, 0, 13);
R3b(e2, a2, b2, c2, d2, 4, 7);
R3b(d2, e2, a2, b2, c2, 13, 5);
// Right round 4
R4b(c2, d2, e2, a2, b2, 8, 15);
R4b(b2, c2, d2, e2, a2, 6, 5);
R4b(a2, b2, c2, d2, e2, 4, 8);
R4b(e2, a2, b2, c2, d2, 1, 11);
R4b(d2, e2, a2, b2, c2, 3, 14);
R4b(c2, d2, e2, a2, b2, 11, 14);
R4b(b2, c2, d2, e2, a2, 15, 6);
R4b(a2, b2, c2, d2, e2, 0, 14);
R4b(e2, a2, b2, c2, d2, 5, 6);
R4b(d2, e2, a2, b2, c2, 12, 9);
R4b(c2, d2, e2, a2, b2, 2, 12);
R4b(b2, c2, d2, e2, a2, 13, 9);
R4b(a2, b2, c2, d2, e2, 9, 12);
R4b(e2, a2, b2, c2, d2, 7, 5);
R4b(d2, e2, a2, b2, c2, 10, 15);
R4b(c2, d2, e2, a2, b2, 14, 8);
// Right round 5
R5b(b2, c2, d2, e2, a2, 12 , 8);
R5b(a2, b2, c2, d2, e2, 15 , 5);
R5b(e2, a2, b2, c2, d2, 10 , 12);
R5b(d2, e2, a2, b2, c2, 4 , 9);
R5b(c2, d2, e2, a2, b2, 1 , 12);
R5b(b2, c2, d2, e2, a2, 5 , 5);
R5b(a2, b2, c2, d2, e2, 8 , 14);
R5b(e2, a2, b2, c2, d2, 7 , 6);
R5b(d2, e2, a2, b2, c2, 6 , 8);
R5b(c2, d2, e2, a2, b2, 2 , 13);
R5b(b2, c2, d2, e2, a2, 13 , 6);
R5b(a2, b2, c2, d2, e2, 14 , 5);
R5b(e2, a2, b2, c2, d2, 0 , 15);
R5b(d2, e2, a2, b2, c2, 3 , 13);
R5b(c2, d2, e2, a2, b2, 9 , 11);
R5b(b2, c2, d2, e2, a2, 11 , 11);
// Finalise state
d2 = m_state[1] + c1 + d2;
m_state[1] = m_state[2] + d1 + e2;
m_state[2] = m_state[3] + e1 + a2;
m_state[3] = m_state[4] + a1 + b2;
m_state[4] = m_state[0] + b1 + c2;
m_state[0] = d2;
m_buffer.size = 0;
}
///////////////////////////////////////////////////////////////////////////////
void
RIPEMD::finish (void)
{
// Ensure the length wouldn't overflow if converted to bits. We need to
// grab this before there's a chance it gets overwritten.
CHECK_EQ (m_length >> sizeof(m_length) * 8 - 3, 0u);
uint64_t length = m_length * 8;
// Push a padding byte into the buffer
uint8_t padding = 0x80;
update (&padding, 1);
// Pad out the line if we couldn't fit a length at the end
size_t remaining = sizeof (m_buffer.d32) - m_buffer.size;
if (remaining < 8) {
static const uint8_t ZEROES[8] = { 0 };
update (ZEROES, remaining);
CHECK_EQ (m_buffer.size, 0u);
remaining = sizeof (m_buffer.d08);
}
// Write the length to the end of the buffer
union {
uint32_t d32[16];
uint8_t d08[64];
};
memset (d32, 0, sizeof (d32));
d32[14] = length & 0xFFFFFFFF;
d32[15] = length >> 32u;
// Do the final update
size_t offset = sizeof(d08) - remaining;
update (d08 + offset, remaining);
}
///////////////////////////////////////////////////////////////////////////////
RIPEMD::digest_t
RIPEMD::digest (void) const
{
digest_t d;
memcpy (d.data (), m_state, sizeof (m_state));
return d;
}

View File

@ -1,58 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright:
* 2014, Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_RIPEMD_HPP
#define __UTIL_HASH_RIPEMD_HPP
#include <array>
///////////////////////////////////////////////////////////////////////////////
namespace util::hash {
class RIPEMD {
public:
typedef std::array<uint8_t,20> digest_t;
public:
RIPEMD();
void update (const void *restrict, size_t) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
digest_t digest (void) const;
void finish (void);
void reset (void);
protected:
void transform ();
bool m_finished;
uint32_t m_state[5];
uint64_t m_length;
struct {
union {
uint32_t d32[16];
uint8_t d08[64];
};
size_t size;
} m_buffer;
};
}
#endif

View File

@ -1,281 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#include "sha1.hpp"
#include "../bitwise.hpp"
#include "../debug.hpp"
#include "../endian.hpp"
#include "../cast.hpp"
#include <algorithm>
#include <cstdint>
#include <limits>
#include <ostream>
using util::hash::SHA1;
///////////////////////////////////////////////////////////////////////////////
std::ostream&
operator<< (std::ostream &os, SHA1::state_t t)
{
switch (t) {
case SHA1::READY: return os << "READY";
case SHA1::FINISHED: return os << "FINISHED";
}
unreachable ();
}
///////////////////////////////////////////////////////////////////////////////
// Logical function for sequence of rounds
static constexpr
uint32_t
f_00 (uint32_t B, uint32_t C, uint32_t D)
{
return (B & C) | (~B & D);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
f_20 (uint32_t B, uint32_t C, uint32_t D)
{
return B ^ C ^ D;
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
f_40 (uint32_t B, uint32_t C, uint32_t D)
{
return (B & C) | (B & D) | (C & D);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
f_60 (uint32_t B, uint32_t C, uint32_t D)
{
return B ^ C ^ D;
}
///////////////////////////////////////////////////////////////////////////////
// Constant words for sequence of rounds
static constexpr uint32_t K_00 = 0x5A827999;
static constexpr uint32_t K_20 = 0x6ED9EBA1;
static constexpr uint32_t K_40 = 0x8F1BBCDC;
static constexpr uint32_t K_60 = 0xCA62C1D6;
static
constexpr uint32_t DEFAULT_H[] = {
0x67452301,
0xEFCDAB89,
0x98BADCFE,
0x10325476,
0xC3D2E1F0
};
static constexpr size_t BLOCK_WORDS = 16;
static constexpr size_t BLOCK_BYTES = BLOCK_WORDS * sizeof (uint32_t);
///////////////////////////////////////////////////////////////////////////////
SHA1::SHA1()
{
reset ();
}
//-----------------------------------------------------------------------------
void
SHA1::reset (void)
{
total = 0;
state = READY;
std::copy (std::begin (DEFAULT_H), std::end (DEFAULT_H), H);
}
///////////////////////////////////////////////////////////////////////////////
void
SHA1::update (
const uint8_t *restrict first,
const uint8_t *restrict last) noexcept
{
CHECK_LE (first, last);
update (first, last - first);
}
//-----------------------------------------------------------------------------
void
SHA1::update (const void *restrict _data, size_t size) noexcept
{
CHECK (_data);
CHECK_EQ (+state, +READY);
CHECK_GE (std::numeric_limits<decltype(total)>::max () - total, size);
auto data = static_cast<const uint8_t *restrict> (_data);
while (size > 0) {
// Copy the data into the remaining available buffer slots
const size_t offset = total % BLOCK_BYTES;
const size_t chunk = std::min (BLOCK_BYTES - offset, size);
std::copy (data, data + chunk, c + offset);
total += chunk;
// Attempt to process if full
if (total % BLOCK_BYTES == 0)
process ();
size -= chunk;
data += chunk;
}
}
///////////////////////////////////////////////////////////////////////////////
void
SHA1::process (void)
{
CHECK_EQ (total % BLOCK_BYTES, 0u);
// Byteswap the raw input we have buffered ready for arithmetic
std::transform (std::begin (W),
std::end (W),
std::begin (W),
[] (uint32_t x) {
return ntoh (x);
});
// Initialise the work buffer and the state variables
for (size_t t = 16; t < 80; ++t)
W[t] = rotatel (W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
uint32_t A = H[0],
B = H[1],
C = H[2],
D = H[3],
E = H[4];
// Perform each of the four rounds
#define ROTATE_STATE(i) do { \
uint32_t temp = rotatel (A, 5) + f_##i (B, C, D) + E + W[t] + K_##i; \
E = D; \
D = C; \
C = rotatel (B, 30); \
B = A; \
A = temp; \
} while (0)
for (size_t t = 0; t < 20; ++t) ROTATE_STATE(00);
for (size_t t = 20; t < 40; ++t) ROTATE_STATE(20);
for (size_t t = 40; t < 60; ++t) ROTATE_STATE(40);
for (size_t t = 60; t < 80; ++t) ROTATE_STATE(60);
// Update the resulting hash state
H[0] += A;
H[1] += B;
H[2] += C;
H[3] += D;
H[4] += E;
}
///////////////////////////////////////////////////////////////////////////////
void
SHA1::finish (void)
{
size_t offset = total % BLOCK_BYTES;
size_t used = total * 8;
// Append a single one bit
c[offset++] = 0x80;
total += 1;
// Zero fill if we can't append length
size_t chunk = BLOCK_BYTES - offset;
if (chunk < sizeof (total)) {
std::fill_n (c + offset, chunk, 0);
total += chunk;
process ();
chunk = BLOCK_BYTES;
offset = 0;
}
// Zero fill and append total length
std::fill_n (c + offset, chunk - sizeof (total), 0);
c[BLOCK_BYTES - 1] = used & 0xFF; used >>= 8;
c[BLOCK_BYTES - 2] = used & 0xFF; used >>= 8;
c[BLOCK_BYTES - 3] = used & 0xFF; used >>= 8;
c[BLOCK_BYTES - 4] = used & 0xFF; used >>= 8;
c[BLOCK_BYTES - 5] = used & 0xFF; used >>= 8;
c[BLOCK_BYTES - 6] = used & 0xFF; used >>= 8;
c[BLOCK_BYTES - 7] = used & 0xFF; used >>= 8;
c[BLOCK_BYTES - 8] = used & 0xFF;
total += chunk;
process ();
state = FINISHED;
}
///////////////////////////////////////////////////////////////////////////////
SHA1::digest_t
SHA1::digest (void) const
{
CHECK_EQ (+state, +FINISHED);
return { {
util::cast::lossless<uint8_t> ((H[0] >> 24u) & 0xFF),
util::cast::lossless<uint8_t> ((H[0] >> 16u) & 0xFF),
util::cast::lossless<uint8_t> ((H[0] >> 8u) & 0xFF),
util::cast::lossless<uint8_t> ((H[0] ) & 0xFF),
util::cast::lossless<uint8_t> ((H[1] >> 24u) & 0xFF),
util::cast::lossless<uint8_t> ((H[1] >> 16u) & 0xFF),
util::cast::lossless<uint8_t> ((H[1] >> 8u) & 0xFF),
util::cast::lossless<uint8_t> ((H[1] ) & 0xFF),
util::cast::lossless<uint8_t> ((H[2] >> 24u) & 0xFF),
util::cast::lossless<uint8_t> ((H[2] >> 16u) & 0xFF),
util::cast::lossless<uint8_t> ((H[2] >> 8u) & 0xFF),
util::cast::lossless<uint8_t> ((H[2] ) & 0xFF),
util::cast::lossless<uint8_t> ((H[3] >> 24u) & 0xFF),
util::cast::lossless<uint8_t> ((H[3] >> 16u) & 0xFF),
util::cast::lossless<uint8_t> ((H[3] >> 8u) & 0xFF),
util::cast::lossless<uint8_t> ((H[3] ) & 0xFF),
util::cast::lossless<uint8_t> ((H[4] >> 24u) & 0xFF),
util::cast::lossless<uint8_t> ((H[4] >> 16u) & 0xFF),
util::cast::lossless<uint8_t> ((H[4] >> 8u) & 0xFF),
util::cast::lossless<uint8_t> ((H[4] ) & 0xFF)
} };
}

View File

@ -1,64 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2013 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_SHA1_HPP
#define __UTIL_HASH_SHA1_HPP
#include <cstdint>
#include <cstdlib>
#include <array>
///////////////////////////////////////////////////////////////////////////////
namespace util::hash {
class SHA1 {
public:
typedef std::array<uint8_t,20> digest_t;
static const size_t BLOCK_SIZE = 64;
static const size_t DIGEST_SIZE = 20;
public:
SHA1();
void update (const void *restrict, size_t) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
void reset (void);
enum state_t {
READY,
FINISHED
};
protected:
void process (void);
state_t state;
uint64_t total;
uint32_t H[5];
union {
uint8_t c[16*4+64*4];
uint32_t W[16 +64 ];
};
};
}
#endif

View File

@ -1,332 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright:
* 2014, Danny Robson <danny@nerdcruft.net>
*/
#include "sha2.hpp"
#include "../bitwise.hpp"
#include "../debug.hpp"
#include "../endian.hpp"
#include <algorithm>
using namespace util::hash;
// First 32 bits of the fractional parts
// of the cube roots
// of the first 64 prime numbers
static constexpr
uint32_t K_64[] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
};
// First 64 bits of the fractional parts
// of the cube roots
// of the first 80 prime numbers
static constexpr
uint64_t K_80[] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
};
///////////////////////////////////////////////////////////////////////////////
static constexpr
uint32_t
Ch (uint32_t x, uint32_t y, uint32_t z)
{
return (x & y) ^ (~x & z);
}
//-----------------------------------------------------------------------------
static constexpr
uint32_t
Maj (uint32_t x, uint32_t y, uint32_t z)
{
return (x & y) ^ (x & z) ^ (y & z);
}
///////////////////////////////////////////////////////////////////////////////
#define FUNC(NAME,r0,r1,r2) \
static constexpr \
uint32_t \
NAME (uint32_t x) \
{ \
return util::rotater (x, (r0)) ^ \
util::rotater (x, (r1)) ^ \
util::rotater (x, (r2)); \
}
FUNC(S0, 2, 13, 22)
FUNC(S1, 6, 11, 25)
#undef FUNC
///////////////////////////////////////////////////////////////////////////////
#define FUNC(NAME,r0,r1,s) \
static constexpr \
uint32_t \
NAME (uint32_t x) \
{ \
return util::rotater (x, (r0)) ^ \
util::rotater (x, (r1)) ^ \
(x >> (s)); \
}
FUNC(s0, 7, 18, 3)
FUNC(s1, 17, 19, 10)
#undef FUNC
///////////////////////////////////////////////////////////////////////////////
static constexpr
uint32_t
H_224[] = {
0xc1059ed8,
0x367cd507,
0x3070dd17,
0xf70e5939,
0xffc00b31,
0x68581511,
0x64f98fa7,
0xbefa4fa4,
};
//-----------------------------------------------------------------------------
static constexpr
uint32_t
H_256[] = {
0x6a09e667,
0xbb67ae85,
0x3c6ef372,
0xa54ff53a,
0x510e527f,
0x9b05688c,
0x1f83d9ab,
0x5be0cd19,
};
//-----------------------------------------------------------------------------
static constexpr
uint64_t
H_384[] = {
0xcbbb9d5dc1059ed8,
0x629a292a367cd507,
0x9159015a3070dd17,
0x152fecd8f70e5939,
0x67332667ffc00b31,
0x8eb44a8768581511,
0xdb0c2e0d64f98fa7,
0x47b5481dbefa4fa4,
};
//-----------------------------------------------------------------------------
static constexpr
uint64_t
H_512[] = {
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179,
};
///////////////////////////////////////////////////////////////////////////////
SHA256::SHA256 ():
m_total (0)
{
(void)K_80;
(void)H_224;
(void)H_384;
(void)H_512;
std::copy (std::begin (H_256), std::end (H_256), std::begin (H));
}
//-----------------------------------------------------------------------------
void
SHA256::update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept
{
CHECK_LE (first, last);
update (first, last - first);
}
//-----------------------------------------------------------------------------
void
SHA256::update (const void *restrict _data, size_t length) noexcept
{
CHECK (_data);
auto data = static_cast<const uint8_t *restrict> (_data);
while (length) {
size_t buffered = m_total % sizeof (M);
size_t chunk = std::min (sizeof (M) - buffered, length);
std::copy (data, data + chunk, C.begin () + buffered);
length -= chunk;
m_total += chunk;
if (m_total % sizeof (M) == 0)
process ();
}
}
///////////////////////////////////////////////////////////////////////////////
void
SHA256::finish (void)
{
// Append a single 1 bit followed by 0s.
auto buffered = m_total % sizeof (M);
auto used = m_total * 8u;
C[buffered++] = 0x80;
++m_total;
// Pad out to 56 byte length
if (buffered > 56) {
size_t chunk = sizeof (M) - buffered;
std::fill_n (C.begin () + buffered, chunk, 0);
m_total += chunk;
process ();
buffered = 0;
}
size_t chunk = sizeof (M) - sizeof (uint64_t) - buffered;
std::fill_n (C.begin () + buffered, chunk, 0);
m_total += chunk;
// Finish with the m_total size
C[56] = (used >> 56) & 0xFF;
C[57] = (used >> 48) & 0xFF;
C[58] = (used >> 40) & 0xFF;
C[59] = (used >> 32) & 0xFF;
C[60] = (used >> 24) & 0xFF;
C[61] = (used >> 16) & 0xFF;
C[62] = (used >> 8) & 0xFF;
C[63] = (used >> 0) & 0xFF;
m_total += 8;
// Reprocess
process ();
}
///////////////////////////////////////////////////////////////////////////////
void
SHA256::process (void)
{
CHECK_EQ (m_total % sizeof (M), 0u);
// Initialise the message schedule, W
uint32_t W[64];
std::transform (M.begin (), M.end (), std::begin (W), [] (uint32_t x) { return ntoh (x); });
for (size_t i = 16; i < 64; ++i)
W[i] = s1(W[i - 2]) + W[i - 7] + s0 (W[i - 15]) + W[i - 16];
// Working variables
uint32_t a = H[0],
b = H[1],
c = H[2],
d = H[3],
e = H[4],
f = H[5],
g = H[6],
h = H[7];
for (unsigned i = 0; i < 64; ++i) {
uint32_t t1 = h + S1 (e) + Ch (e, f, g) + K_64[i] + W[i];
uint32_t t2 = S0 (a) + Maj (a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
H[0] += a;
H[1] += b;
H[2] += c;
H[3] += d;
H[4] += e;
H[5] += f;
H[6] += g;
H[7] += h;
}
///////////////////////////////////////////////////////////////////////////////
SHA256::digest_t
SHA256::digest (void) const
{
digest_t out;
auto cursor = out.begin ();
for (auto i: H) {
*cursor++ = (i >> 24) & 0xFF;
*cursor++ = (i >> 16) & 0xFF;
*cursor++ = (i >> 8) & 0xFF;
*cursor++ = (i >> 0) & 0xFF;
}
return out;
}

View File

@ -1,55 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright:
* 2014, Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_SHA2_HPP
#define __UTIL_HASH_SHA2_HPP
#include <array>
#include <cstdint>
///////////////////////////////////////////////////////////////////////////////
namespace util::hash {
class SHA256 {
public:
typedef std::array<uint8_t,32> digest_t;
public:
SHA256();
void update (const void *restrict, size_t) noexcept;
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
void finish (void);
digest_t digest (void) const;
void reset (void);
private:
void process (void);
uint64_t m_total;
std::array<uint32_t, 8> H;
union {
std::array<uint32_t, 16> M;
std::array<uint8_t, 64> C;
};
};
}
#endif

View File

@ -1,17 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016, Danny Robson <danny@nerdcruft.net>
*/
#include "simple.hpp"

View File

@ -1,43 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016, Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_HASH_SIMPLE_HPP
#define __UTIL_HASH_SIMPLE_HPP
#include <cstdint>
#include <utility>
///////////////////////////////////////////////////////////////////////////////
namespace util { namespace hash {
//template <class H, class InputT>
template <class H, typename ...Args>
typename H::digest_t
simple (const void *restrict first, const void *restrict last, Args&&...args) noexcept
{
H h (std::forward<Args> (args)...);
h.update (
static_cast<const uint8_t*restrict> (first),
static_cast<const uint8_t*restrict> (last)
);
h.finish ();
return h.digest ();
}
} }
#endif

View File

@ -21,10 +21,37 @@
namespace util::hash {
// Thomas Wang's integer mixing functions, ca 2007
constexpr uint32_t wang (uint32_t);
constexpr uint64_t wang (uint64_t);
//-------------------------------------------------------------------------
constexpr uint32_t
wang (uint32_t key)
{
// a prime or an odd constant
constexpr uint32_t c2 = 0x27d4eb2d;
key = (key ^ 61) ^ (key >> 16);
key = key + (key << 3);
key = key ^ (key >> 4);
key = key * c2;
key = key ^ (key >> 15);
return key;
}
#include "wang.ipp"
//-------------------------------------------------------------------------
constexpr uint64_t
wang (uint64_t key)
{
key = ~key + (key << 21); // key = (key << 21) - key - 1;
key = key ^ (key >> 24);
key = (key + (key << 3)) + (key << 8); // key * 265
key = key ^ (key >> 14);
key = (key + (key << 2)) + (key << 4); // key * 21
key = key ^ (key >> 28);
key = key + (key << 31);
return key;
}
}
#endif

View File

@ -1,51 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2010-2015 Danny Robson <danny@nerdcruft.net>
*/
#ifdef __UTIL_HASH_WANG_IPP
#error
#endif
#define __UTIL_HASH_WANG_IPP
//-----------------------------------------------------------------------------
constexpr uint32_t
util::hash::wang (uint32_t key) {
// a prime or an odd constant
constexpr uint32_t c2 = 0x27d4eb2d;
key = (key ^ 61) ^ (key >> 16);
key = key + (key << 3);
key = key ^ (key >> 4);
key = key * c2;
key = key ^ (key >> 15);
return key;
}
//-----------------------------------------------------------------------------
constexpr uint64_t
util::hash::wang (uint64_t key) {
key = ~key + (key << 21); // key = (key << 21) - key - 1;
key = key ^ (key >> 24);
key = (key + (key << 3)) + (key << 8); // key * 265
key = key ^ (key >> 14);
key = (key + (key << 2)) + (key << 4); // key * 21
key = key ^ (key >> 28);
key = key + (key << 31);
return key;
}

View File

@ -78,40 +78,6 @@ const uint64_t
constants<uint64_t>::round_rotl = 31;
///////////////////////////////////////////////////////////////////////////////
constexpr uint32_t DEFAULT_SEED = 0;
//-----------------------------------------------------------------------------
template <typename T>
xxhash<T>::xxhash (void):
xxhash (DEFAULT_SEED)
{ ; }
//-----------------------------------------------------------------------------
template <typename T>
xxhash<T>::xxhash (uint32_t _seed):
m_seed (_seed)
{
reset ();
}
//-----------------------------------------------------------------------------
template <typename T>
void
xxhash<T>::reset (void)
{
memset (&m_state, 0, sizeof (m_state));
m_state.v1 = m_seed + constants<T>::prime[0] + constants<T>::prime[1];
m_state.v2 = m_seed + constants<T>::prime[1];
m_state.v3 = m_seed;
m_state.v4 = m_seed - constants<T>::prime[0];
}
///////////////////////////////////////////////////////////////////////////////
template <typename T>
static
@ -128,9 +94,46 @@ round (T seed, T input)
///////////////////////////////////////////////////////////////////////////////
template <typename T>
void
xxhash<T>::update (const uint8_t *restrict first, const uint8_t *restrict last)
xxhash<T>::xxhash (uint32_t _seed):
m_seed (_seed)
{ ; }
///////////////////////////////////////////////////////////////////////////////
template <typename T>
typename xxhash<T>::digest_t
xxhash<T>::operator() (const util::view<const uint8_t*> data)
{
struct {
uint32_t total_len_32;
uint32_t large_len;
T v1, v2, v3, v4;
uint32_t mem32[4];
uint32_t memsize;
uint32_t reserved;
//uint64_t length;
//T v[4];
//T mem[4];
//unsigned memsize;
} m_state;
/* RESET */
memset (&m_state, 0, sizeof (m_state));
m_state.v1 = m_seed + constants<T>::prime[0] + constants<T>::prime[1];
m_state.v2 = m_seed + constants<T>::prime[1];
m_state.v3 = m_seed;
m_state.v4 = m_seed - constants<T>::prime[0];
/* UPDATE */
do {
auto first = data.begin ();
auto last = data.end ();
if (first == last)
break;
CHECK (first);
CHECK (last);
CHECK_LE (first, last);
@ -150,7 +153,7 @@ xxhash<T>::update (const uint8_t *restrict first, const uint8_t *restrict last)
if (m_state.memsize + len < CHUNK) { /* fill in tmp buffer */
memcpy ((uint8_t*)(m_state.mem32) + m_state.memsize, input, len);
m_state.memsize += (unsigned)len;
return;
break;
}
if (m_state.memsize) { /* some data left from previous update */
@ -189,22 +192,9 @@ xxhash<T>::update (const uint8_t *restrict first, const uint8_t *restrict last)
memcpy (m_state.mem32, p, (size_t)(bEnd-p));
m_state.memsize = (unsigned)(bEnd-p);
}
}
} while (0);
///////////////////////////////////////////////////////////////////////////////
template <typename T>
void
xxhash<T>::finish (void)
{
;
}
///////////////////////////////////////////////////////////////////////////////
template <typename T>
typename xxhash<T>::digest_t
xxhash<T>::digest (void) const
/* DIGEST */
{
auto p = reinterpret_cast<const uint8_t*> (m_state.mem32);
auto last = p + m_state.memsize;
@ -240,6 +230,7 @@ xxhash<T>::digest (void) const
return h;
}
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -17,6 +17,8 @@
#ifndef CRUFT_UTIL_HASH_XXHASH_HPP
#define CRUFT_UTIL_HASH_XXHASH_HPP
#include "../view.hpp"
#include <cstdint>
#include <type_traits>
@ -27,33 +29,14 @@ namespace util::hash {
static_assert (std::is_same<T,uint32_t>::value || std::is_same<T,uint64_t>::value);
using digest_t = T;
xxhash (void);
xxhash (uint32_t seed);
static constexpr uint32_t DEFAULT_SEED = 0;
void update (const uint8_t *restrict first, const uint8_t *restrict last);
void finish (void);
xxhash (uint32_t seed = DEFAULT_SEED);
digest_t digest (void) const;
void reset (void);
digest_t operator() (const util::view<const uint8_t*> data);
private:
uint32_t m_seed;
struct {
uint32_t total_len_32;
uint32_t large_len;
T v1, v2, v3, v4;
uint32_t mem32[4];
uint32_t memsize;
uint32_t reserved;
//uint64_t length;
//T v[4];
//T mem[4];
//unsigned memsize;
} m_state;
};
using xxhash32 = xxhash<uint32_t>;

2
io.hpp
View File

@ -90,7 +90,7 @@ namespace util {
{
auto remain = src;
while (!remain.empty ())
remain = src - dst.write (remain);
remain = remain.consume (dst.write (remain));
return src;
}

View File

@ -31,6 +31,14 @@ namespace util {
namespace detail::posix {
class mapped_file {
public:
using value_type = uint8_t;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = value_type*;
using const_iterator = const value_type*;
using difference_type = std::iterator_traits<iterator>::difference_type;
using size_type = size_t;
mapped_file (const std::experimental::filesystem::path&,
int fflags = O_RDONLY | O_BINARY,
int mflags = PROT_READ);
@ -50,27 +58,19 @@ namespace util {
/// often use this in conjunction with sizeof and packed structure.
/// it is greatly simpler to cast to signed where it's actually
/// required rather than the other way around.
size_t size (void) const;
size_type size (void) const;
const uint8_t* data (void) const &;
uint8_t* data (void) &;
const_iterator data (void) const &;
iterator data (void) &;
uint8_t* begin (void) &;
uint8_t* end (void) &;
iterator begin (void) &;
iterator end (void) &;
const uint8_t* begin (void) const &;
const uint8_t* end (void) const &;
const_iterator begin (void) const &;
const_iterator end (void) const &;
const uint8_t* cbegin (void) const &;
const uint8_t* cend (void) const &;
template <typename T>
util::view<std::add_const_t<T>*>
as_view () const &;
template <typename T>
util::view<T*>
as_view () &;
const_iterator cbegin (void) const &;
const_iterator cend (void) const &;
private:
uint8_t *m_data;

View File

@ -21,27 +21,3 @@
#define __UTIL_IO_POSIX_IPP
#include "pointer.hpp"
///////////////////////////////////////////////////////////////////////////////
template <typename T>
util::view<std::add_const_t<T>*>
util::detail::posix::mapped_file::as_view (void) const&
{
return {
reinterpret_cast<const T*> (cbegin ()),
reinterpret_cast<const T*> (align (cend (), alignof (T)))
};
}
//-----------------------------------------------------------------------------
template <typename T>
util::view<T*>
util::detail::posix::mapped_file::as_view (void) &
{
return {
reinterpret_cast<T *> (begin ()),
reinterpret_cast<T *> (align (end (), alignof(T)))
};
}

View File

@ -516,6 +516,75 @@ namespace util {
) {
return false;
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIt, typename FunctionT>
OutputIt
_transform_by_block (
const util::view<OutputIt> &,
OutputIt cursor,
FunctionT &&
) {
return cursor;
}
//-------------------------------------------------------------------------
template <typename OutputIt, typename FunctionT, typename InputT, typename ...TailT>
OutputIt
_transform_by_block (
const util::view<OutputIt> &dst,
OutputIt cursor,
FunctionT &&func,
const InputT &_src,
TailT &&...tail
) {
auto remain = _src;
if (cursor != dst.begin ()) {
auto infill = std::distance (cursor, dst.end ());
if (remain.size () < static_cast<size_t> (infill)) {
return _transform_by_block (
dst,
std::copy_n (remain.begin (), remain.size (), cursor),
std::forward<FunctionT> (func),
std::forward<TailT> (tail)...
);
}
std::copy_n (remain.begin (), infill, cursor);
func (dst);
cursor = dst.begin ();
remain = { remain.begin () + infill, remain.end () };
}
while (remain.size () >= dst.size ()) {
std::copy_n (remain.begin (), dst.size (), dst.begin ());
func (dst);
remain = { remain.begin () + dst.size (), remain.end () };
}
return _transform_by_block (
dst,
std::copy (remain.begin (), remain.end (), cursor),
std::forward<FunctionT> (func),
std::forward<TailT> (tail)...
);
}
//-------------------------------------------------------------------------
template <typename OutputIt, typename FunctionT, typename ...Args>
OutputIt
transform_by_block (const util::view<OutputIt> &dst, FunctionT &&func, Args &&...src)
{
return _transform_by_block (
dst,
dst.begin (),
std::forward<FunctionT> (func),
std::forward<Args> (src)...
);
}
};
#endif

View File

@ -52,7 +52,8 @@ namespace json::flat {
};
template <typename T>
std::vector<item<T>> parse (util::view<T> data);
std::vector<item<T>>
parse (util::view<T> data);
std::ostream& operator<< (std::ostream&, type);
}

View File

@ -535,6 +535,6 @@ json::schema::validate (json::tree::node &data,
const std::experimental::filesystem::path &schema_path)
{
const util::mapped_file schema_data (schema_path);
auto schema_object = json::tree::parse (schema_data.as_view<char> ());
auto schema_object = json::tree::parse (util::view{schema_data}.cast<const char> ());
validate (data, schema_object->as_object ());
}

View File

@ -210,7 +210,7 @@ parse (typename std::vector<json::flat::item<T>>::const_iterator first,
///////////////////////////////////////////////////////////////////////////////
template <typename T>
std::unique_ptr<json::tree::node>
json::tree::parse (const util::view<T> src)
json::tree::parse (const util::view<T> &src)
{
std::unique_ptr<json::tree::node> output;
auto data = json::flat::parse (src);
@ -225,7 +225,7 @@ json::tree::parse (const util::view<T> src)
#define INSTANTIATE(KLASS) \
template \
std::unique_ptr<json::tree::node> \
json::tree::parse (util::view<KLASS>);
json::tree::parse (const util::view<KLASS>&);
MAP0(INSTANTIATE,
std::string::iterator,
@ -244,7 +244,7 @@ std::unique_ptr<json::tree::node>
json::tree::parse (const std::experimental::filesystem::path &src)
{
const util::mapped_file data (src);
return parse (data.as_view<char> ());
return parse (util::view{data}.cast<const char> ());
}
@ -443,6 +443,15 @@ namespace json::tree {
{
return static_cast<int64_t> (as_sint ());
}
//-------------------------------------------------------------------------
template <>
const std::string&
json::tree::node::as (void) const
{
return as_string ().native ();
}
#if defined(__clang__)
#elif defined(__GNUC__)
#pragma GCC diagnostic pop

View File

@ -46,7 +46,7 @@ namespace json::tree {
/// Parse an encoded form of JSON into a tree structure
template <typename T>
std::unique_ptr<node>
parse (util::view<T> data);
parse (const util::view<T> &data);
std::unique_ptr<node>
parse (const std::experimental::filesystem::path &);

View File

@ -225,7 +225,7 @@ namespace util {
typename BaseT,
typename ExponentT,
typename = std::enable_if_t<
std::is_unsigned_v<ExponentT>,
std::is_integral_v<ExponentT>,
void
>
>

View File

@ -11,11 +11,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2014 Danny Robson <danny@nerdcruft.net>
* Copyright 2014-2018 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_STRINGID_HPP
#define __UTIL_STRINGID_HPP
#ifndef CRUFT_UTIL_STRINGID_HPP
#define CRUFT_UTIL_STRINGID_HPP
#include "view.hpp"
#include <map>
#include <string>
@ -25,11 +27,45 @@ namespace util {
public:
typedef size_t id_t;
///////////////////////////////////////////////////////////////////////
id_t add (std::string);
//---------------------------------------------------------------------
template <typename T>
id_t add (util::view<T> key)
{
return add (
std::string{
std::cbegin (key),
std::cend (key)
}
);
}
///////////////////////////////////////////////////////////////////////
id_t find (const std::string&) const;
//---------------------------------------------------------------------
template <typename T>
id_t find (util::view<T> key) const
{
return find (
std::string {
std::cbegin (key),
std::cend (key)
}
);
}
///////////////////////////////////////////////////////////////////////
void clear (void);
private:
std::map<const std::string, id_t> m_map;
};

View File

@ -1,395 +0,0 @@
#include "crypto/arc4.hpp"
#include "debug.hpp"
#include "tap.hpp"
#include "types.hpp"
#include <vector>
int
main ()
{
util::TAP::logger tap;
// Test vectors from RFC 6229.
static const size_t OFFSETS[] = {
0, 16, 240, 256, 496, 512, 752, 768, 1008, 1024, 1520, 1536, 2032, 2048, 3056, 3072, 4080, 4096
};
struct {
std::vector<uint8_t> key;
const uint64_t data[std::size (OFFSETS)][16];
} TESTS[] = {
{
{ 1, 2, 3, 4, 5 },
{
{ 0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27, 0xcc, 0xc3, 0x52, 0x4a, 0x0a, 0x11, 0x18, 0xa8 },
{ 0x69, 0x82, 0x94, 0x4f, 0x18, 0xfc, 0x82, 0xd5, 0x89, 0xc4, 0x03, 0xa4, 0x7a, 0x0d, 0x09, 0x19 },
{ 0x28, 0xcb, 0x11, 0x32, 0xc9, 0x6c, 0xe2, 0x86, 0x42, 0x1d, 0xca, 0xad, 0xb8, 0xb6, 0x9e, 0xae },
{ 0x1c, 0xfc, 0xf6, 0x2b, 0x03, 0xed, 0xdb, 0x64, 0x1d, 0x77, 0xdf, 0xcf, 0x7f, 0x8d, 0x8c, 0x93 },
{ 0x42, 0xb7, 0xd0, 0xcd, 0xd9, 0x18, 0xa8, 0xa3, 0x3d, 0xd5, 0x17, 0x81, 0xc8, 0x1f, 0x40, 0x41 },
{ 0x64, 0x59, 0x84, 0x44, 0x32, 0xa7, 0xda, 0x92, 0x3c, 0xfb, 0x3e, 0xb4, 0x98, 0x06, 0x61, 0xf6 },
{ 0xec, 0x10, 0x32, 0x7b, 0xde, 0x2b, 0xee, 0xfd, 0x18, 0xf9, 0x27, 0x76, 0x80, 0x45, 0x7e, 0x22 },
{ 0xeb, 0x62, 0x63, 0x8d, 0x4f, 0x0b, 0xa1, 0xfe, 0x9f, 0xca, 0x20, 0xe0, 0x5b, 0xf8, 0xff, 0x2b },
{ 0x45, 0x12, 0x90, 0x48, 0xe6, 0xa0, 0xed, 0x0b, 0x56, 0xb4, 0x90, 0x33, 0x8f, 0x07, 0x8d, 0xa5 },
{ 0x30, 0xab, 0xbc, 0xc7, 0xc2, 0x0b, 0x01, 0x60, 0x9f, 0x23, 0xee, 0x2d, 0x5f, 0x6b, 0xb7, 0xdf },
{ 0x32, 0x94, 0xf7, 0x44, 0xd8, 0xf9, 0x79, 0x05, 0x07, 0xe7, 0x0f, 0x62, 0xe5, 0xbb, 0xce, 0xea },
{ 0xd8, 0x72, 0x9d, 0xb4, 0x18, 0x82, 0x25, 0x9b, 0xee, 0x4f, 0x82, 0x53, 0x25, 0xf5, 0xa1, 0x30 },
{ 0x1e, 0xb1, 0x4a, 0x0c, 0x13, 0xb3, 0xbf, 0x47, 0xfa, 0x2a, 0x0b, 0xa9, 0x3a, 0xd4, 0x5b, 0x8b },
{ 0xcc, 0x58, 0x2f, 0x8b, 0xa9, 0xf2, 0x65, 0xe2, 0xb1, 0xbe, 0x91, 0x12, 0xe9, 0x75, 0xd2, 0xd7 },
{ 0xf2, 0xe3, 0x0f, 0x9b, 0xd1, 0x02, 0xec, 0xbf, 0x75, 0xaa, 0xad, 0xe9, 0xbc, 0x35, 0xc4, 0x3c },
{ 0xec, 0x0e, 0x11, 0xc4, 0x79, 0xdc, 0x32, 0x9d, 0xc8, 0xda, 0x79, 0x68, 0xfe, 0x96, 0x56, 0x81 },
{ 0x06, 0x83, 0x26, 0xa2, 0x11, 0x84, 0x16, 0xd2, 0x1f, 0x9d, 0x04, 0xb2, 0xcd, 0x1c, 0xa0, 0x50 },
{ 0xff, 0x25, 0xb5, 0x89, 0x95, 0x99, 0x67, 0x07, 0xe5, 0x1f, 0xbd, 0xf0, 0x8b, 0x34, 0xd8, 0x75 },
}
},
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
{
{ 0x29, 0x3f, 0x02, 0xd4, 0x7f, 0x37, 0xc9, 0xb6, 0x33, 0xf2, 0xaf, 0x52, 0x85, 0xfe, 0xb4, 0x6b },
{ 0xe6, 0x20, 0xf1, 0x39, 0x0d, 0x19, 0xbd, 0x84, 0xe2, 0xe0, 0xfd, 0x75, 0x20, 0x31, 0xaf, 0xc1 },
{ 0x91, 0x4f, 0x02, 0x53, 0x1c, 0x92, 0x18, 0x81, 0x0d, 0xf6, 0x0f, 0x67, 0xe3, 0x38, 0x15, 0x4c },
{ 0xd0, 0xfd, 0xb5, 0x83, 0x07, 0x3c, 0xe8, 0x5a, 0xb8, 0x39, 0x17, 0x74, 0x0e, 0xc0, 0x11, 0xd5 },
{ 0x75, 0xf8, 0x14, 0x11, 0xe8, 0x71, 0xcf, 0xfa, 0x70, 0xb9, 0x0c, 0x74, 0xc5, 0x92, 0xe4, 0x54 },
{ 0x0b, 0xb8, 0x72, 0x02, 0x93, 0x8d, 0xad, 0x60, 0x9e, 0x87, 0xa5, 0xa1, 0xb0, 0x79, 0xe5, 0xe4 },
{ 0xc2, 0x91, 0x12, 0x46, 0xb6, 0x12, 0xe7, 0xe7, 0xb9, 0x03, 0xdf, 0xed, 0xa1, 0xda, 0xd8, 0x66 },
{ 0x32, 0x82, 0x8f, 0x91, 0x50, 0x2b, 0x62, 0x91, 0x36, 0x8d, 0xe8, 0x08, 0x1d, 0xe3, 0x6f, 0xc2 },
{ 0xf3, 0xb9, 0xa7, 0xe3, 0xb2, 0x97, 0xbf, 0x9a, 0xd8, 0x04, 0x51, 0x2f, 0x90, 0x63, 0xef, 0xf1 },
{ 0x8e, 0xcb, 0x67, 0xa9, 0xba, 0x1f, 0x55, 0xa5, 0xa0, 0x67, 0xe2, 0xb0, 0x26, 0xa3, 0x67, 0x6f },
{ 0xd2, 0xaa, 0x90, 0x2b, 0xd4, 0x2d, 0x0d, 0x7c, 0xfd, 0x34, 0x0c, 0xd4, 0x58, 0x10, 0x52, 0x9f },
{ 0x78, 0xb2, 0x72, 0xc9, 0x6e, 0x42, 0xea, 0xb4, 0xc6, 0x0b, 0xd9, 0x14, 0xe3, 0x9d, 0x06, 0xe3 },
{ 0xf4, 0x33, 0x2f, 0xd3, 0x1a, 0x07, 0x93, 0x96, 0xee, 0x3c, 0xee, 0x3f, 0x2a, 0x4f, 0xf0, 0x49 },
{ 0x05, 0x45, 0x97, 0x81, 0xd4, 0x1f, 0xda, 0x7f, 0x30, 0xc1, 0xbe, 0x7e, 0x12, 0x46, 0xc6, 0x23 },
{ 0xad, 0xfd, 0x38, 0x68, 0xb8, 0xe5, 0x14, 0x85, 0xd5, 0xe6, 0x10, 0x01, 0x7e, 0x3d, 0xd6, 0x09 },
{ 0xad, 0x26, 0x58, 0x1c, 0x0c, 0x5b, 0xe4, 0x5f, 0x4c, 0xea, 0x01, 0xdb, 0x2f, 0x38, 0x05, 0xd5 },
{ 0xf3, 0x17, 0x2c, 0xef, 0xfc, 0x3b, 0x3d, 0x99, 0x7c, 0x85, 0xcc, 0xd5, 0xaf, 0x1a, 0x95, 0x0c },
{ 0xe7, 0x4b, 0x0b, 0x97, 0x31, 0x22, 0x7f, 0xd3, 0x7c, 0x0e, 0xc0, 0x8a, 0x47, 0xdd, 0xd8, 0xb8 },
}
},
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
{
{ 0x97, 0xab, 0x8a, 0x1b, 0xf0, 0xaf, 0xb9, 0x61, 0x32, 0xf2, 0xf6, 0x72, 0x58, 0xda, 0x15, 0xa8 },
{ 0x82, 0x63, 0xef, 0xdb, 0x45, 0xc4, 0xa1, 0x86, 0x84, 0xef, 0x87, 0xe6, 0xb1, 0x9e, 0x5b, 0x09 },
{ 0x96, 0x36, 0xeb, 0xc9, 0x84, 0x19, 0x26, 0xf4, 0xf7, 0xd1, 0xf3, 0x62, 0xbd, 0xdf, 0x6e, 0x18 },
{ 0xd0, 0xa9, 0x90, 0xff, 0x2c, 0x05, 0xfe, 0xf5, 0xb9, 0x03, 0x73, 0xc9, 0xff, 0x4b, 0x87, 0x0a },
{ 0x73, 0x23, 0x9f, 0x1d, 0xb7, 0xf4, 0x1d, 0x80, 0xb6, 0x43, 0xc0, 0xc5, 0x25, 0x18, 0xec, 0x63 },
{ 0x16, 0x3b, 0x31, 0x99, 0x23, 0xa6, 0xbd, 0xb4, 0x52, 0x7c, 0x62, 0x61, 0x26, 0x70, 0x3c, 0x0f },
{ 0x49, 0xd6, 0xc8, 0xaf, 0x0f, 0x97, 0x14, 0x4a, 0x87, 0xdf, 0x21, 0xd9, 0x14, 0x72, 0xf9, 0x66 },
{ 0x44, 0x17, 0x3a, 0x10, 0x3b, 0x66, 0x16, 0xc5, 0xd5, 0xad, 0x1c, 0xee, 0x40, 0xc8, 0x63, 0xd0 },
{ 0x27, 0x3c, 0x9c, 0x4b, 0x27, 0xf3, 0x22, 0xe4, 0xe7, 0x16, 0xef, 0x53, 0xa4, 0x7d, 0xe7, 0xa4 },
{ 0xc6, 0xd0, 0xe7, 0xb2, 0x26, 0x25, 0x9f, 0xa9, 0x02, 0x34, 0x90, 0xb2, 0x61, 0x67, 0xad, 0x1d },
{ 0x1f, 0xe8, 0x98, 0x67, 0x13, 0xf0, 0x7c, 0x3d, 0x9a, 0xe1, 0xc1, 0x63, 0xff, 0x8c, 0xf9, 0xd3 },
{ 0x83, 0x69, 0xe1, 0xa9, 0x65, 0x61, 0x0b, 0xe8, 0x87, 0xfb, 0xd0, 0xc7, 0x91, 0x62, 0xaa, 0xfb },
{ 0x0a, 0x01, 0x27, 0xab, 0xb4, 0x44, 0x84, 0xb9, 0xfb, 0xef, 0x5a, 0xbc, 0xae, 0x1b, 0x57, 0x9f },
{ 0xc2, 0xcd, 0xad, 0xc6, 0x40, 0x2e, 0x8e, 0xe8, 0x66, 0xe1, 0xf3, 0x7b, 0xdb, 0x47, 0xe4, 0x2c },
{ 0x26, 0xb5, 0x1e, 0xa3, 0x7d, 0xf8, 0xe1, 0xd6, 0xf7, 0x6f, 0xc3, 0xb6, 0x6a, 0x74, 0x29, 0xb3 },
{ 0xbc, 0x76, 0x83, 0x20, 0x5d, 0x4f, 0x44, 0x3d, 0xc1, 0xf2, 0x9d, 0xda, 0x33, 0x15, 0xc8, 0x7b },
{ 0xd5, 0xfa, 0x5a, 0x34, 0x69, 0xd2, 0x9a, 0xaa, 0xf8, 0x3d, 0x23, 0x58, 0x9d, 0xb8, 0xc8, 0x5b },
{ 0x3f, 0xb4, 0x6e, 0x2c, 0x8f, 0x0f, 0x06, 0x8e, 0xdc, 0xe8, 0xcd, 0xcd, 0x7d, 0xfc, 0x58, 0x62 },
}
},
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a },
{
{ 0xed, 0xe3, 0xb0, 0x46, 0x43, 0xe5, 0x86, 0xcc, 0x90, 0x7d, 0xc2, 0x18, 0x51, 0x70, 0x99, 0x02, },
{ 0x03, 0x51, 0x6b, 0xa7, 0x8f, 0x41, 0x3b, 0xeb, 0x22, 0x3a, 0xa5, 0xd4, 0xd2, 0xdf, 0x67, 0x11, },
{ 0x3c, 0xfd, 0x6c, 0xb5, 0x8e, 0xe0, 0xfd, 0xde, 0x64, 0x01, 0x76, 0xad, 0x00, 0x00, 0x04, 0x4d, },
{ 0x48, 0x53, 0x2b, 0x21, 0xfb, 0x60, 0x79, 0xc9, 0x11, 0x4c, 0x0f, 0xfd, 0x9c, 0x04, 0xa1, 0xad, },
{ 0x3e, 0x8c, 0xea, 0x98, 0x01, 0x71, 0x09, 0x97, 0x90, 0x84, 0xb1, 0xef, 0x92, 0xf9, 0x9d, 0x86, },
{ 0xe2, 0x0f, 0xb4, 0x9b, 0xdb, 0x33, 0x7e, 0xe4, 0x8b, 0x8d, 0x8d, 0xc0, 0xf4, 0xaf, 0xef, 0xfe, },
{ 0x5c, 0x25, 0x21, 0xea, 0xcd, 0x79, 0x66, 0xf1, 0x5e, 0x05, 0x65, 0x44, 0xbe, 0xa0, 0xd3, 0x15, },
{ 0xe0, 0x67, 0xa7, 0x03, 0x19, 0x31, 0xa2, 0x46, 0xa6, 0xc3, 0x87, 0x5d, 0x2f, 0x67, 0x8a, 0xcb, },
{ 0xa6, 0x4f, 0x70, 0xaf, 0x88, 0xae, 0x56, 0xb6, 0xf8, 0x75, 0x81, 0xc0, 0xe2, 0x3e, 0x6b, 0x08, },
{ 0xf4, 0x49, 0x03, 0x1d, 0xe3, 0x12, 0x81, 0x4e, 0xc6, 0xf3, 0x19, 0x29, 0x1f, 0x4a, 0x05, 0x16, },
{ 0xbd, 0xae, 0x85, 0x92, 0x4b, 0x3c, 0xb1, 0xd0, 0xa2, 0xe3, 0x3a, 0x30, 0xc6, 0xd7, 0x95, 0x99, },
{ 0x8a, 0x0f, 0xed, 0xdb, 0xac, 0x86, 0x5a, 0x09, 0xbc, 0xd1, 0x27, 0xfb, 0x56, 0x2e, 0xd6, 0x0a, },
{ 0xb5, 0x5a, 0x0a, 0x5b, 0x51, 0xa1, 0x2a, 0x8b, 0xe3, 0x48, 0x99, 0xc3, 0xe0, 0x47, 0x51, 0x1a, },
{ 0xd9, 0xa0, 0x9c, 0xea, 0x3c, 0xe7, 0x5f, 0xe3, 0x96, 0x98, 0x07, 0x03, 0x17, 0xa7, 0x13, 0x39, },
{ 0x55, 0x22, 0x25, 0xed, 0x11, 0x77, 0xf4, 0x45, 0x84, 0xac, 0x8c, 0xfa, 0x6c, 0x4e, 0xb5, 0xfc, },
{ 0x7e, 0x82, 0xcb, 0xab, 0xfc, 0x95, 0x38, 0x1b, 0x08, 0x09, 0x98, 0x44, 0x21, 0x29, 0xc2, 0xf8, },
{ 0x1f, 0x13, 0x5e, 0xd1, 0x4c, 0xe6, 0x0a, 0x91, 0x36, 0x9d, 0x23, 0x22, 0xbe, 0xf2, 0x5e, 0x3c, },
{ 0x08, 0xb6, 0xbe, 0x45, 0x12, 0x4a, 0x43, 0xe2, 0xeb, 0x77, 0x95, 0x3f, 0x84, 0xdc, 0x85, 0x53, },
}
},
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
{
{ 0x9a, 0xc7, 0xcc, 0x9a, 0x60, 0x9d, 0x1e, 0xf7, 0xb2, 0x93, 0x28, 0x99, 0xcd, 0xe4, 0x1b, 0x97, },
{ 0x52, 0x48, 0xc4, 0x95, 0x90, 0x14, 0x12, 0x6a, 0x6e, 0x8a, 0x84, 0xf1, 0x1d, 0x1a, 0x9e, 0x1c, },
{ 0x06, 0x59, 0x02, 0xe4, 0xb6, 0x20, 0xf6, 0xcc, 0x36, 0xc8, 0x58, 0x9f, 0x66, 0x43, 0x2f, 0x2b, },
{ 0xd3, 0x9d, 0x56, 0x6b, 0xc6, 0xbc, 0xe3, 0x01, 0x07, 0x68, 0x15, 0x15, 0x49, 0xf3, 0x87, 0x3f, },
{ 0xb6, 0xd1, 0xe6, 0xc4, 0xa5, 0xe4, 0x77, 0x1c, 0xad, 0x79, 0x53, 0x8d, 0xf2, 0x95, 0xfb, 0x11, },
{ 0xc6, 0x8c, 0x1d, 0x5c, 0x55, 0x9a, 0x97, 0x41, 0x23, 0xdf, 0x1d, 0xbc, 0x52, 0xa4, 0x3b, 0x89, },
{ 0xc5, 0xec, 0xf8, 0x8d, 0xe8, 0x97, 0xfd, 0x57, 0xfe, 0xd3, 0x01, 0x70, 0x1b, 0x82, 0xa2, 0x59, },
{ 0xec, 0xcb, 0xe1, 0x3d, 0xe1, 0xfc, 0xc9, 0x1c, 0x11, 0xa0, 0xb2, 0x6c, 0x0b, 0xc8, 0xfa, 0x4d, },
{ 0xe7, 0xa7, 0x25, 0x74, 0xf8, 0x78, 0x2a, 0xe2, 0x6a, 0xab, 0xcf, 0x9e, 0xbc, 0xd6, 0x60, 0x65, },
{ 0xbd, 0xf0, 0x32, 0x4e, 0x60, 0x83, 0xdc, 0xc6, 0xd3, 0xce, 0xdd, 0x3c, 0xa8, 0xc5, 0x3c, 0x16, },
{ 0xb4, 0x01, 0x10, 0xc4, 0x19, 0x0b, 0x56, 0x22, 0xa9, 0x61, 0x16, 0xb0, 0x01, 0x7e, 0xd2, 0x97, },
{ 0xff, 0xa0, 0xb5, 0x14, 0x64, 0x7e, 0xc0, 0x4f, 0x63, 0x06, 0xb8, 0x92, 0xae, 0x66, 0x11, 0x81, },
{ 0xd0, 0x3d, 0x1b, 0xc0, 0x3c, 0xd3, 0x3d, 0x70, 0xdf, 0xf9, 0xfa, 0x5d, 0x71, 0x96, 0x3e, 0xbd, },
{ 0x8a, 0x44, 0x12, 0x64, 0x11, 0xea, 0xa7, 0x8b, 0xd5, 0x1e, 0x8d, 0x87, 0xa8, 0x87, 0x9b, 0xf5, },
{ 0xfa, 0xbe, 0xb7, 0x60, 0x28, 0xad, 0xe2, 0xd0, 0xe4, 0x87, 0x22, 0xe4, 0x6c, 0x46, 0x15, 0xa3, },
{ 0xc0, 0x5d, 0x88, 0xab, 0xd5, 0x03, 0x57, 0xf9, 0x35, 0xa6, 0x3c, 0x59, 0xee, 0x53, 0x76, 0x23, },
{ 0xff, 0x38, 0x26, 0x5c, 0x16, 0x42, 0xc1, 0xab, 0xe8, 0xd3, 0xc2, 0xfe, 0x5e, 0x57, 0x2b, 0xf8, },
{ 0xa3, 0x6a, 0x4c, 0x30, 0x1a, 0xe8, 0xac, 0x13, 0x61, 0x0c, 0xcb, 0xc1, 0x22, 0x56, 0xca, 0xcc, },
}
},
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 },
{
{ 0x05, 0x95, 0xe5, 0x7f, 0xe5, 0xf0, 0xbb, 0x3c, 0x70, 0x6e, 0xda, 0xc8, 0xa4, 0xb2, 0xdb, 0x11, },
{ 0xdf, 0xde, 0x31, 0x34, 0x4a, 0x1a, 0xf7, 0x69, 0xc7, 0x4f, 0x07, 0x0a, 0xee, 0x9e, 0x23, 0x26, },
{ 0xb0, 0x6b, 0x9b, 0x1e, 0x19, 0x5d, 0x13, 0xd8, 0xf4, 0xa7, 0x99, 0x5c, 0x45, 0x53, 0xac, 0x05, },
{ 0x6b, 0xd2, 0x37, 0x8e, 0xc3, 0x41, 0xc9, 0xa4, 0x2f, 0x37, 0xba, 0x79, 0xf8, 0x8a, 0x32, 0xff, },
{ 0xe7, 0x0b, 0xce, 0x1d, 0xf7, 0x64, 0x5a, 0xdb, 0x5d, 0x2c, 0x41, 0x30, 0x21, 0x5c, 0x35, 0x22, },
{ 0x9a, 0x57, 0x30, 0xc7, 0xfc, 0xb4, 0xc9, 0xaf, 0x51, 0xff, 0xda, 0x89, 0xc7, 0xf1, 0xad, 0x22, },
{ 0x04, 0x85, 0x05, 0x5f, 0xd4, 0xf6, 0xf0, 0xd9, 0x63, 0xef, 0x5a, 0xb9, 0xa5, 0x47, 0x69, 0x82, },
{ 0x59, 0x1f, 0xc6, 0x6b, 0xcd, 0xa1, 0x0e, 0x45, 0x2b, 0x03, 0xd4, 0x55, 0x1f, 0x6b, 0x62, 0xac, },
{ 0x27, 0x53, 0xcc, 0x83, 0x98, 0x8a, 0xfa, 0x3e, 0x16, 0x88, 0xa1, 0xd3, 0xb4, 0x2c, 0x9a, 0x02, },
{ 0x93, 0x61, 0x0d, 0x52, 0x3d, 0x1d, 0x3f, 0x00, 0x62, 0xb3, 0xc2, 0xa3, 0xbb, 0xc7, 0xc7, 0xf0, },
{ 0x96, 0xc2, 0x48, 0x61, 0x0a, 0xad, 0xed, 0xfe, 0xaf, 0x89, 0x78, 0xc0, 0x3d, 0xe8, 0x20, 0x5a, },
{ 0x0e, 0x31, 0x7b, 0x3d, 0x1c, 0x73, 0xb9, 0xe9, 0xa4, 0x68, 0x8f, 0x29, 0x6d, 0x13, 0x3a, 0x19, },
{ 0xbd, 0xf0, 0xe6, 0xc3, 0xcc, 0xa5, 0xb5, 0xb9, 0xd5, 0x33, 0xb6, 0x9c, 0x56, 0xad, 0xa1, 0x20, },
{ 0x88, 0xa2, 0x18, 0xb6, 0xe2, 0xec, 0xe1, 0xe6, 0x24, 0x6d, 0x44, 0xc7, 0x59, 0xd1, 0x9b, 0x10, },
{ 0x68, 0x66, 0x39, 0x7e, 0x95, 0xc1, 0x40, 0x53, 0x4f, 0x94, 0x26, 0x34, 0x21, 0x00, 0x6e, 0x40, },
{ 0x32, 0xcb, 0x0a, 0x1e, 0x95, 0x42, 0xc6, 0xb3, 0xb8, 0xb3, 0x98, 0xab, 0xc3, 0xb0, 0xf1, 0xd5, },
{ 0x29, 0xa0, 0xb8, 0xae, 0xd5, 0x4a, 0x13, 0x23, 0x24, 0xc6, 0x2e, 0x42, 0x3f, 0x54, 0xb4, 0xc8, },
{ 0x3c, 0xb0, 0xf3, 0xb5, 0x02, 0x0a, 0x98, 0xb8, 0x2a, 0xf9, 0xfe, 0x15, 0x44, 0x84, 0xa1, 0x68, },
}
},
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 },
{
{ 0xea, 0xa6, 0xbd, 0x25, 0x88, 0x0b, 0xf9, 0x3d, 0x3f, 0x5d, 0x1e, 0x4c, 0xa2, 0x61, 0x1d, 0x91, },
{ 0xcf, 0xa4, 0x5c, 0x9f, 0x7e, 0x71, 0x4b, 0x54, 0xbd, 0xfa, 0x80, 0x02, 0x7c, 0xb1, 0x43, 0x80, },
{ 0x11, 0x4a, 0xe3, 0x44, 0xde, 0xd7, 0x1b, 0x35, 0xf2, 0xe6, 0x0f, 0xeb, 0xad, 0x72, 0x7f, 0xd8, },
{ 0x02, 0xe1, 0xe7, 0x05, 0x6b, 0x0f, 0x62, 0x39, 0x00, 0x49, 0x64, 0x22, 0x94, 0x3e, 0x97, 0xb6, },
{ 0x91, 0xcb, 0x93, 0xc7, 0x87, 0x96, 0x4e, 0x10, 0xd9, 0x52, 0x7d, 0x99, 0x9c, 0x6f, 0x93, 0x6b, },
{ 0x49, 0xb1, 0x8b, 0x42, 0xf8, 0xe8, 0x36, 0x7c, 0xbe, 0xb5, 0xef, 0x10, 0x4b, 0xa1, 0xc7, 0xcd, },
{ 0x87, 0x08, 0x4b, 0x3b, 0xa7, 0x00, 0xba, 0xde, 0x95, 0x56, 0x10, 0x67, 0x27, 0x45, 0xb3, 0x74, },
{ 0xe7, 0xa7, 0xb9, 0xe9, 0xec, 0x54, 0x0d, 0x5f, 0xf4, 0x3b, 0xdb, 0x12, 0x79, 0x2d, 0x1b, 0x35, },
{ 0xc7, 0x99, 0xb5, 0x96, 0x73, 0x8f, 0x6b, 0x01, 0x8c, 0x76, 0xc7, 0x4b, 0x17, 0x59, 0xbd, 0x90, },
{ 0x7f, 0xec, 0x5b, 0xfd, 0x9f, 0x9b, 0x89, 0xce, 0x65, 0x48, 0x30, 0x90, 0x92, 0xd7, 0xe9, 0x58, },
{ 0x40, 0xf2, 0x50, 0xb2, 0x6d, 0x1f, 0x09, 0x6a, 0x4a, 0xfd, 0x4c, 0x34, 0x0a, 0x58, 0x88, 0x15, },
{ 0x3e, 0x34, 0x13, 0x5c, 0x79, 0xdb, 0x01, 0x02, 0x00, 0x76, 0x76, 0x51, 0xcf, 0x26, 0x30, 0x73, },
{ 0xf6, 0x56, 0xab, 0xcc, 0xf8, 0x8d, 0xd8, 0x27, 0x02, 0x7b, 0x2c, 0xe9, 0x17, 0xd4, 0x64, 0xec, },
{ 0x18, 0xb6, 0x25, 0x03, 0xbf, 0xbc, 0x07, 0x7f, 0xba, 0xbb, 0x98, 0xf2, 0x0d, 0x98, 0xab, 0x34, },
{ 0x8a, 0xed, 0x95, 0xee, 0x5b, 0x0d, 0xcb, 0xfb, 0xef, 0x4e, 0xb2, 0x1d, 0x3a, 0x3f, 0x52, 0xf9, },
{ 0x62, 0x5a, 0x1a, 0xb0, 0x0e, 0xe3, 0x9a, 0x53, 0x27, 0x34, 0x6b, 0xdd, 0xb0, 0x1a, 0x9c, 0x18, },
{ 0xa1, 0x3a, 0x7c, 0x79, 0xc7, 0xe1, 0x19, 0xb5, 0xab, 0x02, 0x96, 0xab, 0x28, 0xc3, 0x00, 0xb9, },
{ 0xf3, 0xe4, 0xc0, 0xa2, 0xe0, 0x2d, 0x1d, 0x01, 0xf7, 0xf0, 0xa7, 0x46, 0x18, 0xaf, 0x2b, 0x48, },
}
},
{
{ 0x83, 0x32, 0x22, 0x77, 0x2a },
{
{ 0x80, 0xad, 0x97, 0xbd, 0xc9, 0x73, 0xdf, 0x8a, 0x2e, 0x87, 0x9e, 0x92, 0xa4, 0x97, 0xef, 0xda, },
{ 0x20, 0xf0, 0x60, 0xc2, 0xf2, 0xe5, 0x12, 0x65, 0x01, 0xd3, 0xd4, 0xfe, 0xa1, 0x0d, 0x5f, 0xc0, },
{ 0xfa, 0xa1, 0x48, 0xe9, 0x90, 0x46, 0x18, 0x1f, 0xec, 0x6b, 0x20, 0x85, 0xf3, 0xb2, 0x0e, 0xd9, },
{ 0xf0, 0xda, 0xf5, 0xba, 0xb3, 0xd5, 0x96, 0x83, 0x98, 0x57, 0x84, 0x6f, 0x73, 0xfb, 0xfe, 0x5a, },
{ 0x1c, 0x7e, 0x2f, 0xc4, 0x63, 0x92, 0x32, 0xfe, 0x29, 0x75, 0x84, 0xb2, 0x96, 0x99, 0x6b, 0xc8, },
{ 0x3d, 0xb9, 0xb2, 0x49, 0x40, 0x6c, 0xc8, 0xed, 0xff, 0xac, 0x55, 0xcc, 0xd3, 0x22, 0xba, 0x12, },
{ 0xe4, 0xf9, 0xf7, 0xe0, 0x06, 0x61, 0x54, 0xbb, 0xd1, 0x25, 0xb7, 0x45, 0x56, 0x9b, 0xc8, 0x97, },
{ 0x75, 0xd5, 0xef, 0x26, 0x2b, 0x44, 0xc4, 0x1a, 0x9c, 0xf6, 0x3a, 0xe1, 0x45, 0x68, 0xe1, 0xb9, },
{ 0x6d, 0xa4, 0x53, 0xdb, 0xf8, 0x1e, 0x82, 0x33, 0x4a, 0x3d, 0x88, 0x66, 0xcb, 0x50, 0xa1, 0xe3, },
{ 0x78, 0x28, 0xd0, 0x74, 0x11, 0x9c, 0xab, 0x5c, 0x22, 0xb2, 0x94, 0xd7, 0xa9, 0xbf, 0xa0, 0xbb, },
{ 0xad, 0xb8, 0x9c, 0xea, 0x9a, 0x15, 0xfb, 0xe6, 0x17, 0x29, 0x5b, 0xd0, 0x4b, 0x8c, 0xa0, 0x5c, },
{ 0x62, 0x51, 0xd8, 0x7f, 0xd4, 0xaa, 0xae, 0x9a, 0x7e, 0x4a, 0xd5, 0xc2, 0x17, 0xd3, 0xf3, 0x00, },
{ 0xe7, 0x11, 0x9b, 0xd6, 0xdd, 0x9b, 0x22, 0xaf, 0xe8, 0xf8, 0x95, 0x85, 0x43, 0x28, 0x81, 0xe2, },
{ 0x78, 0x5b, 0x60, 0xfd, 0x7e, 0xc4, 0xe9, 0xfc, 0xb6, 0x54, 0x5f, 0x35, 0x0d, 0x66, 0x0f, 0xab, },
{ 0xaf, 0xec, 0xc0, 0x37, 0xfd, 0xb7, 0xb0, 0x83, 0x8e, 0xb3, 0xd7, 0x0b, 0xcd, 0x26, 0x83, 0x82, },
{ 0xdb, 0xc1, 0xa7, 0xb4, 0x9d, 0x57, 0x35, 0x8c, 0xc9, 0xfa, 0x6d, 0x61, 0xd7, 0x3b, 0x7c, 0xf0, },
{ 0x63, 0x49, 0xd1, 0x26, 0xa3, 0x7a, 0xfc, 0xba, 0x89, 0x79, 0x4f, 0x98, 0x04, 0x91, 0x4f, 0xdc, },
{ 0xbf, 0x42, 0xc3, 0x01, 0x8c, 0x2f, 0x7c, 0x66, 0xbf, 0xde, 0x52, 0x49, 0x75, 0x76, 0x81, 0x15, },
}
},
{
{ 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a },
{
{ 0xbc, 0x92, 0x22, 0xdb, 0xd3, 0x27, 0x4d, 0x8f, 0xc6, 0x6d, 0x14, 0xcc, 0xbd, 0xa6, 0x69, 0x0b, },
{ 0x7a, 0xe6, 0x27, 0x41, 0x0c, 0x9a, 0x2b, 0xe6, 0x93, 0xdf, 0x5b, 0xb7, 0x48, 0x5a, 0x63, 0xe3, },
{ 0x3f, 0x09, 0x31, 0xaa, 0x03, 0xde, 0xfb, 0x30, 0x0f, 0x06, 0x01, 0x03, 0x82, 0x6f, 0x2a, 0x64, },
{ 0xbe, 0xaa, 0x9e, 0xc8, 0xd5, 0x9b, 0xb6, 0x81, 0x29, 0xf3, 0x02, 0x7c, 0x96, 0x36, 0x11, 0x81, },
{ 0x74, 0xe0, 0x4d, 0xb4, 0x6d, 0x28, 0x64, 0x8d, 0x7d, 0xee, 0x8a, 0x00, 0x64, 0xb0, 0x6c, 0xfe, },
{ 0x9b, 0x5e, 0x81, 0xc6, 0x2f, 0xe0, 0x23, 0xc5, 0x5b, 0xe4, 0x2f, 0x87, 0xbb, 0xf9, 0x32, 0xb8, },
{ 0xce, 0x17, 0x8f, 0xc1, 0x82, 0x6e, 0xfe, 0xcb, 0xc1, 0x82, 0xf5, 0x79, 0x99, 0xa4, 0x61, 0x40, },
{ 0x8b, 0xdf, 0x55, 0xcd, 0x55, 0x06, 0x1c, 0x06, 0xdb, 0xa6, 0xbe, 0x11, 0xde, 0x4a, 0x57, 0x8a, },
{ 0x62, 0x6f, 0x5f, 0x4d, 0xce, 0x65, 0x25, 0x01, 0xf3, 0x08, 0x7d, 0x39, 0xc9, 0x2c, 0xc3, 0x49, },
{ 0x42, 0xda, 0xac, 0x6a, 0x8f, 0x9a, 0xb9, 0xa7, 0xfd, 0x13, 0x7c, 0x60, 0x37, 0x82, 0x56, 0x82, },
{ 0xcc, 0x03, 0xfd, 0xb7, 0x91, 0x92, 0xa2, 0x07, 0x31, 0x2f, 0x53, 0xf5, 0xd4, 0xdc, 0x33, 0xd9, },
{ 0xf7, 0x0f, 0x14, 0x12, 0x2a, 0x1c, 0x98, 0xa3, 0x15, 0x5d, 0x28, 0xb8, 0xa0, 0xa8, 0xa4, 0x1d, },
{ 0x2a, 0x3a, 0x30, 0x7a, 0xb2, 0x70, 0x8a, 0x9c, 0x00, 0xfe, 0x0b, 0x42, 0xf9, 0xc2, 0xd6, 0xa1, },
{ 0x86, 0x26, 0x17, 0x62, 0x7d, 0x22, 0x61, 0xea, 0xb0, 0xb1, 0x24, 0x65, 0x97, 0xca, 0x0a, 0xe9, },
{ 0x55, 0xf8, 0x77, 0xce, 0x4f, 0x2e, 0x1d, 0xdb, 0xbf, 0x8e, 0x13, 0xe2, 0xcd, 0xe0, 0xfd, 0xc8, },
{ 0x1b, 0x15, 0x56, 0xcb, 0x93, 0x5f, 0x17, 0x33, 0x37, 0x70, 0x5f, 0xbb, 0x5d, 0x50, 0x1f, 0xc1, },
{ 0xec, 0xd0, 0xe9, 0x66, 0x02, 0xbe, 0x7f, 0x8d, 0x50, 0x92, 0x81, 0x6c, 0xcc, 0xf2, 0xc2, 0xe9, },
{ 0x02, 0x78, 0x81, 0xfa, 0xb4, 0x99, 0x3a, 0x1c, 0x26, 0x20, 0x24, 0xa9, 0x4f, 0xff, 0x3f, 0x61, },
}
},
{
{ 0x64, 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a },
{
{ 0xbb, 0xf6, 0x09, 0xde, 0x94, 0x13, 0x17, 0x2d, 0x07, 0x66, 0x0c, 0xb6, 0x80, 0x71, 0x69, 0x26, },
{ 0x46, 0x10, 0x1a, 0x6d, 0xab, 0x43, 0x11, 0x5d, 0x6c, 0x52, 0x2b, 0x4f, 0xe9, 0x36, 0x04, 0xa9, },
{ 0xcb, 0xe1, 0xff, 0xf2, 0x1c, 0x96, 0xf3, 0xee, 0xf6, 0x1e, 0x8f, 0xe0, 0x54, 0x2c, 0xbd, 0xf0, },
{ 0x34, 0x79, 0x38, 0xbf, 0xfa, 0x40, 0x09, 0xc5, 0x12, 0xcf, 0xb4, 0x03, 0x4b, 0x0d, 0xd1, 0xa7, },
{ 0x78, 0x67, 0xa7, 0x86, 0xd0, 0x0a, 0x71, 0x47, 0x90, 0x4d, 0x76, 0xdd, 0xf1, 0xe5, 0x20, 0xe3, },
{ 0x8d, 0x3e, 0x9e, 0x1c, 0xae, 0xfc, 0xcc, 0xb3, 0xfb, 0xf8, 0xd1, 0x8f, 0x64, 0x12, 0x0b, 0x32, },
{ 0x94, 0x23, 0x37, 0xf8, 0xfd, 0x76, 0xf0, 0xfa, 0xe8, 0xc5, 0x2d, 0x79, 0x54, 0x81, 0x06, 0x72, },
{ 0xb8, 0x54, 0x8c, 0x10, 0xf5, 0x16, 0x67, 0xf6, 0xe6, 0x0e, 0x18, 0x2f, 0xa1, 0x9b, 0x30, 0xf7, },
{ 0x02, 0x11, 0xc7, 0xc6, 0x19, 0x0c, 0x9e, 0xfd, 0x12, 0x37, 0xc3, 0x4c, 0x8f, 0x2e, 0x06, 0xc4, },
{ 0xbd, 0xa6, 0x4f, 0x65, 0x27, 0x6d, 0x2a, 0xac, 0xb8, 0xf9, 0x02, 0x12, 0x20, 0x3a, 0x80, 0x8e, },
{ 0xbd, 0x38, 0x20, 0xf7, 0x32, 0xff, 0xb5, 0x3e, 0xc1, 0x93, 0xe7, 0x9d, 0x33, 0xe2, 0x7c, 0x73, },
{ 0xd0, 0x16, 0x86, 0x16, 0x86, 0x19, 0x07, 0xd4, 0x82, 0xe3, 0x6c, 0xda, 0xc8, 0xcf, 0x57, 0x49, },
{ 0x97, 0xb0, 0xf0, 0xf2, 0x24, 0xb2, 0xd2, 0x31, 0x71, 0x14, 0x80, 0x8f, 0xb0, 0x3a, 0xf7, 0xa0, },
{ 0xe5, 0x96, 0x16, 0xe4, 0x69, 0x78, 0x79, 0x39, 0xa0, 0x63, 0xce, 0xea, 0x9a, 0xf9, 0x56, 0xd1, },
{ 0xc4, 0x7e, 0x0d, 0xc1, 0x66, 0x09, 0x19, 0xc1, 0x11, 0x01, 0x20, 0x8f, 0x9e, 0x69, 0xaa, 0x1f, },
{ 0x5a, 0xe4, 0xf1, 0x28, 0x96, 0xb8, 0x37, 0x9a, 0x2a, 0xad, 0x89, 0xb5, 0xb5, 0x53, 0xd6, 0xb0, },
{ 0x6b, 0x6b, 0x09, 0x8d, 0x0c, 0x29, 0x3b, 0xc2, 0x99, 0x3d, 0x80, 0xbf, 0x05, 0x18, 0xb6, 0xd9, },
{ 0x81, 0x70, 0xcc, 0x3c, 0xcd, 0x92, 0xa6, 0x98, 0x62, 0x1b, 0x93, 0x9d, 0xd3, 0x8f, 0xe7, 0xb9, },
}
},
{
{ 0x8b, 0x37, 0x64, 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a },
{
{ 0xab, 0x65, 0xc2, 0x6e, 0xdd, 0xb2, 0x87, 0x60, 0x0d, 0xb2, 0xfd, 0xa1, 0x0d, 0x1e, 0x60, 0x5c, },
{ 0xbb, 0x75, 0x90, 0x10, 0xc2, 0x96, 0x58, 0xf2, 0xc7, 0x2d, 0x93, 0xa2, 0xd1, 0x6d, 0x29, 0x30, },
{ 0xb9, 0x01, 0xe8, 0x03, 0x6e, 0xd1, 0xc3, 0x83, 0xcd, 0x3c, 0x4c, 0x4d, 0xd0, 0xa6, 0xab, 0x05, },
{ 0x3d, 0x25, 0xce, 0x49, 0x22, 0x92, 0x4c, 0x55, 0xf0, 0x64, 0x94, 0x33, 0x53, 0xd7, 0x8a, 0x6c, },
{ 0x12, 0xc1, 0xaa, 0x44, 0xbb, 0xf8, 0x7e, 0x75, 0xe6, 0x11, 0xf6, 0x9b, 0x2c, 0x38, 0xf4, 0x9b, },
{ 0x28, 0xf2, 0xb3, 0x43, 0x4b, 0x65, 0xc0, 0x98, 0x77, 0x47, 0x00, 0x44, 0xc6, 0xea, 0x17, 0x0d, },
{ 0xbd, 0x9e, 0xf8, 0x22, 0xde, 0x52, 0x88, 0x19, 0x61, 0x34, 0xcf, 0x8a, 0xf7, 0x83, 0x93, 0x04, },
{ 0x67, 0x55, 0x9c, 0x23, 0xf0, 0x52, 0x15, 0x84, 0x70, 0xa2, 0x96, 0xf7, 0x25, 0x73, 0x5a, 0x32, },
{ 0x8b, 0xab, 0x26, 0xfb, 0xc2, 0xc1, 0x2b, 0x0f, 0x13, 0xe2, 0xab, 0x18, 0x5e, 0xab, 0xf2, 0x41, },
{ 0x31, 0x18, 0x5a, 0x6d, 0x69, 0x6f, 0x0c, 0xfa, 0x9b, 0x42, 0x80, 0x8b, 0x38, 0xe1, 0x32, 0xa2, },
{ 0x56, 0x4d, 0x3d, 0xae, 0x18, 0x3c, 0x52, 0x34, 0xc8, 0xaf, 0x1e, 0x51, 0x06, 0x1c, 0x44, 0xb5, },
{ 0x3c, 0x07, 0x78, 0xa7, 0xb5, 0xf7, 0x2d, 0x3c, 0x23, 0xa3, 0x13, 0x5c, 0x7d, 0x67, 0xb9, 0xf4, },
{ 0xf3, 0x43, 0x69, 0x89, 0x0f, 0xcf, 0x16, 0xfb, 0x51, 0x7d, 0xca, 0xae, 0x44, 0x63, 0xb2, 0xdd, },
{ 0x02, 0xf3, 0x1c, 0x81, 0xe8, 0x20, 0x07, 0x31, 0xb8, 0x99, 0xb0, 0x28, 0xe7, 0x91, 0xbf, 0xa7, },
{ 0x72, 0xda, 0x64, 0x62, 0x83, 0x22, 0x8c, 0x14, 0x30, 0x08, 0x53, 0x70, 0x17, 0x95, 0x61, 0x6f, },
{ 0x4e, 0x0a, 0x8c, 0x6f, 0x79, 0x34, 0xa7, 0x88, 0xe2, 0x26, 0x5e, 0x81, 0xd6, 0xd0, 0xc8, 0xf4, },
{ 0x43, 0x8d, 0xd5, 0xea, 0xfe, 0xa0, 0x11, 0x1b, 0x6f, 0x36, 0xb4, 0xb9, 0x38, 0xda, 0x2a, 0x68, },
{ 0x5f, 0x6b, 0xfc, 0x73, 0x81, 0x58, 0x74, 0xd9, 0x71, 0x00, 0xf0, 0x86, 0x97, 0x93, 0x57, 0xd8, },
}
},
{
{ 0xeb, 0xb4, 0x62, 0x27, 0xc6, 0xcc, 0x8b, 0x37, 0x64, 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a },
{
{ 0x72, 0x0c, 0x94, 0xb6, 0x3e, 0xdf, 0x44, 0xe1, 0x31, 0xd9, 0x50, 0xca, 0x21, 0x1a, 0x5a, 0x30, },
{ 0xc3, 0x66, 0xfd, 0xea, 0xcf, 0x9c, 0xa8, 0x04, 0x36, 0xbe, 0x7c, 0x35, 0x84, 0x24, 0xd2, 0x0b, },
{ 0xb3, 0x39, 0x4a, 0x40, 0xaa, 0xbf, 0x75, 0xcb, 0xa4, 0x22, 0x82, 0xef, 0x25, 0xa0, 0x05, 0x9f, },
{ 0x48, 0x47, 0xd8, 0x1d, 0xa4, 0x94, 0x2d, 0xbc, 0x24, 0x9d, 0xef, 0xc4, 0x8c, 0x92, 0x2b, 0x9f, },
{ 0x08, 0x12, 0x8c, 0x46, 0x9f, 0x27, 0x53, 0x42, 0xad, 0xda, 0x20, 0x2b, 0x2b, 0x58, 0xda, 0x95, },
{ 0x97, 0x0d, 0xac, 0xef, 0x40, 0xad, 0x98, 0x72, 0x3b, 0xac, 0x5d, 0x69, 0x55, 0xb8, 0x17, 0x61, },
{ 0x3c, 0xb8, 0x99, 0x93, 0xb0, 0x7b, 0x0c, 0xed, 0x93, 0xde, 0x13, 0xd2, 0xa1, 0x10, 0x13, 0xac, },
{ 0xef, 0x2d, 0x67, 0x6f, 0x15, 0x45, 0xc2, 0xc1, 0x3d, 0xc6, 0x80, 0xa0, 0x2f, 0x4a, 0xdb, 0xfe, },
{ 0xb6, 0x05, 0x95, 0x51, 0x4f, 0x24, 0xbc, 0x9f, 0xe5, 0x22, 0xa6, 0xca, 0xd7, 0x39, 0x36, 0x44, },
{ 0xb5, 0x15, 0xa8, 0xc5, 0x01, 0x17, 0x54, 0xf5, 0x90, 0x03, 0x05, 0x8b, 0xdb, 0x81, 0x51, 0x4e, },
{ 0x3c, 0x70, 0x04, 0x7e, 0x8c, 0xbc, 0x03, 0x8e, 0x3b, 0x98, 0x20, 0xdb, 0x60, 0x1d, 0xa4, 0x95, },
{ 0x11, 0x75, 0xda, 0x6e, 0xe7, 0x56, 0xde, 0x46, 0xa5, 0x3e, 0x2b, 0x07, 0x56, 0x60, 0xb7, 0x70, },
{ 0x00, 0xa5, 0x42, 0xbb, 0xa0, 0x21, 0x11, 0xcc, 0x2c, 0x65, 0xb3, 0x8e, 0xbd, 0xba, 0x58, 0x7e, },
{ 0x58, 0x65, 0xfd, 0xbb, 0x5b, 0x48, 0x06, 0x41, 0x04, 0xe8, 0x30, 0xb3, 0x80, 0xf2, 0xae, 0xde, },
{ 0x34, 0xb2, 0x1a, 0xd2, 0xad, 0x44, 0xe9, 0x99, 0xdb, 0x2d, 0x7f, 0x08, 0x63, 0xf0, 0xd9, 0xb6, },
{ 0x84, 0xa9, 0x21, 0x8f, 0xc3, 0x6e, 0x8a, 0x5f, 0x2c, 0xcf, 0xbe, 0xae, 0x53, 0xa2, 0x7d, 0x25, },
{ 0xa2, 0x22, 0x1a, 0x11, 0xb8, 0x33, 0xcc, 0xb4, 0x98, 0xa5, 0x95, 0x40, 0xf0, 0x54, 0x5f, 0x4a, },
{ 0x5b, 0xbe, 0xb4, 0x78, 0x7d, 0x59, 0xe5, 0x37, 0x3f, 0xdb, 0xea, 0x6c, 0x6f, 0x75, 0xc2, 0x9b, },
}
},
{
{ 0xc1, 0x09, 0x16, 0x39, 0x08, 0xeb, 0xe5, 0x1d, 0xeb, 0xb4, 0x62, 0x27, 0xc6, 0xcc, 0x8b, 0x37, 0x64, 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a },
{
{ 0x54, 0xb6, 0x4e, 0x6b, 0x5a, 0x20, 0xb5, 0xe2, 0xec, 0x84, 0x59, 0x3d, 0xc7, 0x98, 0x9d, 0xa7, },
{ 0xc1, 0x35, 0xee, 0xe2, 0x37, 0xa8, 0x54, 0x65, 0xff, 0x97, 0xdc, 0x03, 0x92, 0x4f, 0x45, 0xce, },
{ 0xcf, 0xcc, 0x92, 0x2f, 0xb4, 0xa1, 0x4a, 0xb4, 0x5d, 0x61, 0x75, 0xaa, 0xbb, 0xf2, 0xd2, 0x01, },
{ 0x83, 0x7b, 0x87, 0xe2, 0xa4, 0x46, 0xad, 0x0e, 0xf7, 0x98, 0xac, 0xd0, 0x2b, 0x94, 0x12, 0x4f, },
{ 0x17, 0xa6, 0xdb, 0xd6, 0x64, 0x92, 0x6a, 0x06, 0x36, 0xb3, 0xf4, 0xc3, 0x7a, 0x4f, 0x46, 0x94, },
{ 0x4a, 0x5f, 0x9f, 0x26, 0xae, 0xee, 0xd4, 0xd4, 0xa2, 0x5f, 0x63, 0x2d, 0x30, 0x52, 0x33, 0xd9, },
{ 0x80, 0xa3, 0xd0, 0x1e, 0xf0, 0x0c, 0x8e, 0x9a, 0x42, 0x09, 0xc1, 0x7f, 0x4e, 0xeb, 0x35, 0x8c, },
{ 0xd1, 0x5e, 0x7d, 0x5f, 0xfa, 0xaa, 0xbc, 0x02, 0x07, 0xbf, 0x20, 0x0a, 0x11, 0x77, 0x93, 0xa2, },
{ 0x34, 0x96, 0x82, 0xbf, 0x58, 0x8e, 0xaa, 0x52, 0xd0, 0xaa, 0x15, 0x60, 0x34, 0x6a, 0xea, 0xfa, },
{ 0xf5, 0x85, 0x4c, 0xdb, 0x76, 0xc8, 0x89, 0xe3, 0xad, 0x63, 0x35, 0x4e, 0x5f, 0x72, 0x75, 0xe3, },
{ 0x53, 0x2c, 0x7c, 0xec, 0xcb, 0x39, 0xdf, 0x32, 0x36, 0x31, 0x84, 0x05, 0xa4, 0xb1, 0x27, 0x9c, },
{ 0xba, 0xef, 0xe6, 0xd9, 0xce, 0xb6, 0x51, 0x84, 0x22, 0x60, 0xe0, 0xd1, 0xe0, 0x5e, 0x3b, 0x90, },
{ 0xe8, 0x2d, 0x8c, 0x6d, 0xb5, 0x4e, 0x3c, 0x63, 0x3f, 0x58, 0x1c, 0x95, 0x2b, 0xa0, 0x42, 0x07, },
{ 0x4b, 0x16, 0xe5, 0x0a, 0xbd, 0x38, 0x1b, 0xd7, 0x09, 0x00, 0xa9, 0xcd, 0x9a, 0x62, 0xcb, 0x23, },
{ 0x36, 0x82, 0xee, 0x33, 0xbd, 0x14, 0x8b, 0xd9, 0xf5, 0x86, 0x56, 0xcd, 0x8f, 0x30, 0xd9, 0xfb, },
{ 0x1e, 0x5a, 0x0b, 0x84, 0x75, 0x04, 0x5d, 0x9b, 0x20, 0xb2, 0x62, 0x86, 0x24, 0xed, 0xfd, 0x9e, },
{ 0x63, 0xed, 0xd6, 0x84, 0xfb, 0x82, 0x62, 0x82, 0xfe, 0x52, 0x8f, 0x9c, 0x0e, 0x92, 0x37, 0xbc, },
{ 0xe4, 0xdd, 0x2e, 0x98, 0xd6, 0x96, 0x0f, 0xae, 0x0b, 0x43, 0x54, 0x54, 0x56, 0x74, 0x33, 0x91, },
}
},
{
{ 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21, 0xc1, 0x09, 0x16, 0x39, 0x08, 0xeb, 0xe5, 0x1d, 0xeb, 0xb4, 0x62, 0x27, 0xc6, 0xcc, 0x8b, 0x37, 0x64, 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a },
{
{ 0xdd, 0x5b, 0xcb, 0x00, 0x18, 0xe9, 0x22, 0xd4, 0x94, 0x75, 0x9d, 0x7c, 0x39, 0x5d, 0x02, 0xd3, },
{ 0xc8, 0x44, 0x6f, 0x8f, 0x77, 0xab, 0xf7, 0x37, 0x68, 0x53, 0x53, 0xeb, 0x89, 0xa1, 0xc9, 0xeb, },
{ 0xaf, 0x3e, 0x30, 0xf9, 0xc0, 0x95, 0x04, 0x59, 0x38, 0x15, 0x15, 0x75, 0xc3, 0xfb, 0x90, 0x98, },
{ 0xf8, 0xcb, 0x62, 0x74, 0xdb, 0x99, 0xb8, 0x0b, 0x1d, 0x20, 0x12, 0xa9, 0x8e, 0xd4, 0x8f, 0x0e, },
{ 0x25, 0xc3, 0x00, 0x5a, 0x1c, 0xb8, 0x5d, 0xe0, 0x76, 0x25, 0x98, 0x39, 0xab, 0x71, 0x98, 0xab, },
{ 0x9d, 0xcb, 0xc1, 0x83, 0xe8, 0xcb, 0x99, 0x4b, 0x72, 0x7b, 0x75, 0xbe, 0x31, 0x80, 0x76, 0x9c, },
{ 0xa1, 0xd3, 0x07, 0x8d, 0xfa, 0x91, 0x69, 0x50, 0x3e, 0xd9, 0xd4, 0x49, 0x1d, 0xee, 0x4e, 0xb2, },
{ 0x85, 0x14, 0xa5, 0x49, 0x58, 0x58, 0x09, 0x6f, 0x59, 0x6e, 0x4b, 0xcd, 0x66, 0xb1, 0x06, 0x65, },
{ 0x5f, 0x40, 0xd5, 0x9e, 0xc1, 0xb0, 0x3b, 0x33, 0x73, 0x8e, 0xfa, 0x60, 0xb2, 0x25, 0x5d, 0x31, },
{ 0x34, 0x77, 0xc7, 0xf7, 0x64, 0xa4, 0x1b, 0xac, 0xef, 0xf9, 0x0b, 0xf1, 0x4f, 0x92, 0xb7, 0xcc, },
{ 0xac, 0x4e, 0x95, 0x36, 0x8d, 0x99, 0xb9, 0xeb, 0x78, 0xb8, 0xda, 0x8f, 0x81, 0xff, 0xa7, 0x95, },
{ 0x8c, 0x3c, 0x13, 0xf8, 0xc2, 0x38, 0x8b, 0xb7, 0x3f, 0x38, 0x57, 0x6e, 0x65, 0xb7, 0xc4, 0x46, },
{ 0x13, 0xc4, 0xb9, 0xc1, 0xdf, 0xb6, 0x65, 0x79, 0xed, 0xdd, 0x8a, 0x28, 0x0b, 0x9f, 0x73, 0x16, },
{ 0xdd, 0xd2, 0x78, 0x20, 0x55, 0x01, 0x26, 0x69, 0x8e, 0xfa, 0xad, 0xc6, 0x4b, 0x64, 0xf6, 0x6e, },
{ 0xf0, 0x8f, 0x2e, 0x66, 0xd2, 0x8e, 0xd1, 0x43, 0xf3, 0xa2, 0x37, 0xcf, 0x9d, 0xe7, 0x35, 0x59, },
{ 0x9e, 0xa3, 0x6c, 0x52, 0x55, 0x31, 0xb8, 0x80, 0xba, 0x12, 0x43, 0x34, 0xf5, 0x7b, 0x0b, 0x70, },
{ 0xd5, 0xa3, 0x9e, 0x3d, 0xfc, 0xc5, 0x02, 0x80, 0xba, 0xc4, 0xa6, 0xb5, 0xaa, 0x0d, 0xca, 0x7d, },
{ 0x37, 0x0b, 0x1c, 0x1f, 0xe6, 0x55, 0x91, 0x6d, 0x97, 0xfd, 0x0d, 0x47, 0xca, 0x1d, 0x72, 0xb8, },
}
},
};
for (size_t i = 0; i < std::size (TESTS); ++i) {
const auto &t = TESTS[i];
util::crypto::ARC4 gen (t.key.data (), t.key.size ());
uint8_t data[16];
size_t consumed = 0;
bool success = true;
for (size_t j = 0; j < std::size (OFFSETS); ++j) {
CHECK_GE (OFFSETS[j], consumed);
size_t diff = OFFSETS[j] - consumed;
gen.discard (diff);
consumed += diff;
gen.generate (data, 16);
consumed += 16;
success = success && std::equal (std::begin (data), std::end (data), std::begin (t.data[j]));
};
tap.expect (success, "ARC4 %zu", i);
}
return tap.status ();
}

View File

@ -1,43 +0,0 @@
#include "crypto/ice.hpp"
#include "tap.hpp"
#include "iterator.hpp"
#include "stream.hpp"
#include "endian.hpp"
#include <iostream>
#include <iomanip>
#include <array>
#include <algorithm>
int
main (int, char**)
{
const uint64_t data = 0xfedcba9876543210;
struct {
unsigned level;
uint64_t crypt;
std::vector<uint64_t> key;
} TESTS[] = {
{ 0, 0xde240d83a00a9cc0, { 0xdeadbeef01234567 } },
{ 1, 0x7d6ef1ef30d47a96, { 0xdeadbeef01234567 } },
{ 2, 0xf94840d86972f21c, { 0x0011223344556677, 0x8899aabbccddeeff } },
};
util::TAP::logger tap;
for (const auto &t: TESTS) {
std::vector<uint64_t> k (t.key.cbegin (), t.key.cend ());
std::transform (k.cbegin (), k.cend (), k.begin (), util::hton<uint64_t>);
ice key (t.level, k.data (), k.data () + k.size ());
auto crypt = key.encrypt (data);
auto plain = key.decrypt (t.crypt);
tap.expect_eq (crypt, t.crypt, "ICE level %u certification, encrypt", t.level);
tap.expect_eq (plain, data, "ICE level %u certification, decrypt", t.level);
}
return tap.status ();
}

View File

@ -1,229 +0,0 @@
#include "crypto/salsa.hpp"
#include "tap.hpp"
///////////////////////////////////////////////////////////////////////////////
void
test_quarter (util::TAP::logger &tap)
{
static const struct {
std::array<uint32_t, 4> a, b;
} TESTS[] = {
{ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
{ { 0x00000001, 0x00000000, 0x00000000, 0x00000000 },
{ 0x08008145, 0x00000080, 0x00010200, 0x20500000 } },
{ { 0x00000000, 0x00000001, 0x00000000, 0x00000000 },
{ 0x88000100, 0x00000001, 0x00000200, 0x00402000 } },
{ { 0x00000000, 0x00000000, 0x00000001, 0x00000000 },
{ 0x80040000, 0x00000000, 0x00000001, 0x00002000 } },
{ { 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00048044, 0x00000080, 0x00010000, 0x20100001 } },
{ { 0xe7e8c006, 0xc4f9417d, 0x6479b4b2, 0x68c67137 },
{ 0xe876d72b, 0x9361dfd5, 0xf1460244, 0x948541a3 } },
{ { 0xd3917c5b, 0x55f1c407, 0x52a58a7a, 0x8f887a3b },
{ 0x3e2f308c, 0xd90a8f36, 0x6ab2a923, 0x2883524c } },
};
for (size_t i = 0; i < std::size (TESTS); ++i)
tap.expect_eq (util::crypto::salsa::quarter (TESTS[i].a), TESTS[i].b, "quarter %zu", i);
}
///////////////////////////////////////////////////////////////////////////////
void
test_row (util::TAP::logger &tap)
{
static const struct {
std::array<uint32_t, 16> a, b;
} TESTS[] = {
{ { 0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000001, 0x00000000, 0x00000000, 0x00000000, },
{ 0x08008145, 0x00000080, 0x00010200, 0x20500000,
0x20100001, 0x00048044, 0x00000080, 0x00010000,
0x00000001, 0x00002000, 0x80040000, 0x00000000,
0x00000001, 0x00000200, 0x00402000, 0x88000100, }
},
{ { 0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365,
0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6,
0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e,
0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a, },
{ 0xa890d39d, 0x65d71596, 0xe9487daa, 0xc8ca6a86,
0x949d2192, 0x764b7754, 0xe408d9b9, 0x7a41b4d1,
0x3402e183, 0x3c3af432, 0x50669f96, 0xd89ef0a8,
0x0040ede5, 0xb545fbce, 0xd257ed4f, 0x1818882d, },
}
};
for (size_t i = 0; i < std::size (TESTS); ++i)
tap.expect_eq (util::crypto::salsa::row (TESTS[i].a), TESTS[i].b, "row %zu", i);
}
///////////////////////////////////////////////////////////////////////////////
void
test_col (util::TAP::logger &tap)
{
static const struct {
std::array<uint32_t,16> a, b;
} TESTS[] = {
{ { 0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000001, 0x00000000, 0x00000000, 0x00000000, },
{ 0x10090288, 0x00000000, 0x00000000, 0x00000000,
0x00000101, 0x00000000, 0x00000000, 0x00000000,
0x00020401, 0x00000000, 0x00000000, 0x00000000,
0x40a04001, 0x00000000, 0x00000000, 0x00000000, } },
{ { 0x08521bd6, 0x1fe88837, 0xbb2aa576, 0x3aa26365,
0xc54c6a5b, 0x2fc74c2f, 0x6dd39cc3, 0xda0a64f6,
0x90a2f23d, 0x067f95a6, 0x06b35f61, 0x41e4732e,
0xe859c100, 0xea4d84b7, 0x0f619bff, 0xbc6e965a, },
{ 0x8c9d190a, 0xce8e4c90, 0x1ef8e9d3, 0x1326a71a,
0x90a20123, 0xead3c4f3, 0x63a091a0, 0xf0708d69,
0x789b010c, 0xd195a681, 0xeb7d5504, 0xa774135c,
0x481c2027, 0x53a8e4b5, 0x4c1f89c5, 0x3f78c9c8, } },
};
for (size_t i = 0; i < std::size (TESTS); ++i)
tap.expect_eq (util::crypto::salsa::col (TESTS[i].a), TESTS[i].b, "col %zu", i);
}
///////////////////////////////////////////////////////////////////////////////
void
test_doubleround (util::TAP::logger &tap)
{
static const struct {
std::array<uint32_t,16> a, b;
} TESTS[] = {
{ { 0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, },
{ 0x8186a22d, 0x0040a284, 0x82479210, 0x06929051,
0x08000090, 0x02402200, 0x00004000, 0x00800000,
0x00010200, 0x20400000, 0x08008104, 0x00000000,
0x20500000, 0xa0000040, 0x0008180a, 0x612a8020, } },
{ { 0xde501066, 0x6f9eb8f7, 0xe4fbbd9b, 0x454e3f57,
0xb75540d3, 0x43e93a4c, 0x3a6f2aa0, 0x726d6b36,
0x9243f484, 0x9145d1e8, 0x4fa9d247, 0xdc8dee11,
0x054bf545, 0x254dd653, 0xd9421b6d, 0x67b276c1, },
{ 0xccaaf672, 0x23d960f7, 0x9153e63a, 0xcd9a60d0,
0x50440492, 0xf07cad19, 0xae344aa0, 0xdf4cfdfc,
0xca531c29, 0x8e7943db, 0xac1680cd, 0xd503ca00,
0xa74b2ad6, 0xbc331c5c, 0x1dda24c7, 0xee928277, } }
};
for (size_t i = 0; i < std::size (TESTS); ++i)
tap.expect_eq (util::crypto::salsa::doubleround (TESTS[i].a), TESTS[i].b, "doubleround %zu", i);
}
///////////////////////////////////////////////////////////////////////////////
void
test_salsa20 (util::TAP::logger &tap)
{
static const struct {
std::array<uint8_t,64> a, b;
} TESTS[] = {
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ { 0xd3, 0x9f, 0x0d, 0x73, 0x4c, 0x37, 0x52, 0xb7,
0x03, 0x75, 0xde, 0x25, 0xbf, 0xbb, 0xea, 0x88,
0x31, 0xed, 0xb3, 0x30, 0x01, 0x6a, 0xb2, 0xdb,
0xaf, 0xc7, 0xa6, 0x30, 0x56, 0x10, 0xb3, 0xcf,
0x1f, 0xf0, 0x20, 0x3f, 0x0f, 0x53, 0x5d, 0xa1,
0x74, 0x93, 0x30, 0x71, 0xee, 0x37, 0xcc, 0x24,
0x4f, 0xc9, 0xeb, 0x4f, 0x03, 0x51, 0x9c, 0x2f,
0xcb, 0x1a, 0xf4, 0xf3, 0x58, 0x76, 0x68, 0x36 },
{ 0x6d, 0x2a, 0xb2, 0xa8, 0x9c, 0xf0, 0xf8, 0xee,
0xa8, 0xc4, 0xbe, 0xcb, 0x1a, 0x6e, 0xaa, 0x9a,
0x1d, 0x1d, 0x96, 0x1a, 0x96, 0x1e, 0xeb, 0xf9,
0xbe, 0xa3, 0xfb, 0x30, 0x45, 0x90, 0x33, 0x39,
0x76, 0x28, 0x98, 0x9d, 0xb4, 0x39, 0x1b, 0x5e,
0x6b, 0x2a, 0xec, 0x23, 0x1b, 0x6f, 0x72, 0x72,
0xdb, 0xec, 0xe8, 0x87, 0x6f, 0x9b, 0x6e, 0x12,
0x18, 0xe8, 0x5f, 0x9e, 0xb3, 0x13, 0x30, 0xca } },
{ { 0x58, 0x76, 0x68, 0x36, 0x4f, 0xc9, 0xeb, 0x4f,
0x03, 0x51, 0x9c, 0x2f, 0xcb, 0x1a, 0xf4, 0xf3,
0xbf, 0xbb, 0xea, 0x88, 0xd3, 0x9f, 0x0d, 0x73,
0x4c, 0x37, 0x52, 0xb7, 0x03, 0x75, 0xde, 0x25,
0x56, 0x10, 0xb3, 0xcf, 0x31, 0xed, 0xb3, 0x30,
0x01, 0x6a, 0xb2, 0xdb, 0xaf, 0xc7, 0xa6, 0x30,
0xee, 0x37, 0xcc, 0x24, 0x1f, 0xf0, 0x20, 0x3f,
0x0f, 0x53, 0x5d, 0xa1, 0x74, 0x93, 0x30, 0x71 },
{ 0xb3, 0x13, 0x30, 0xca, 0xdb, 0xec, 0xe8, 0x87,
0x6f, 0x9b, 0x6e, 0x12, 0x18, 0xe8, 0x5f, 0x9e,
0x1a, 0x6e, 0xaa, 0x9a, 0x6d, 0x2a, 0xb2, 0xa8,
0x9c, 0xf0, 0xf8, 0xee, 0xa8, 0xc4, 0xbe, 0xcb,
0x45, 0x90, 0x33, 0x39, 0x1d, 0x1d, 0x96, 0x1a,
0x96, 0x1e, 0xeb, 0xf9, 0xbe, 0xa3, 0xfb, 0x30,
0x1b, 0x6f, 0x72, 0x72, 0x76, 0x28, 0x98, 0x9d,
0xb4, 0x39, 0x1b, 0x5e, 0x6b, 0x2a, 0xec, 0x23 } }
};
for (size_t i = 0; i < std::size (TESTS); ++i)
tap.expect_eq (util::crypto::salsa20 (TESTS[i].a), TESTS[i].b, "salsa20 %zu", i);
struct {
std::array<uint8_t,64> a, b;
} million = {
{ 0x06, 0x7c, 0x53, 0x92, 0x26, 0xbf, 0x09, 0x32,
0x04, 0xa1, 0x2f, 0xde, 0x7a, 0xb6, 0xdf, 0xb9,
0x4b, 0x1b, 0x00, 0xd8, 0x10, 0x7a, 0x07, 0x59,
0xa2, 0x68, 0x65, 0x93, 0xd5, 0x15, 0x36, 0x5f,
0xe1, 0xfd, 0x8b, 0xb0, 0x69, 0x84, 0x17, 0x74,
0x4c, 0x29, 0xb0, 0xcf, 0xdd, 0x22, 0x9d, 0x6c,
0x5e, 0x5e, 0x63, 0x34, 0x5a, 0x75, 0x5b, 0xdc,
0x92, 0xbe, 0xef, 0x8f, 0xc4, 0xb0, 0x82, 0xba },
{ 0x08, 0x12, 0x26, 0xc7, 0x77, 0x4c, 0xd7, 0x43,
0xad, 0x7f, 0x90, 0xa2, 0x67, 0xd4, 0xb0, 0xd9,
0xc0, 0x13, 0xe9, 0x21, 0x9f, 0xc5, 0x9a, 0xa0,
0x80, 0xf3, 0xdb, 0x41, 0xab, 0x88, 0x87, 0xe1,
0x7b, 0x0b, 0x44, 0x56, 0xed, 0x52, 0x14, 0x9b,
0x85, 0xbd, 0x09, 0x53, 0xa7, 0x74, 0xc2, 0x4e,
0x7a, 0x7f, 0xc3, 0xb9, 0xb9, 0xcc, 0xbc, 0x5a,
0xf5, 0x09, 0xb7, 0xf8, 0xe2, 0x55, 0xf5, 0x68 }
};
for (int i = 0; i < 1'000'000; ++i)
million.a = util::crypto::salsa20 (million.a);
tap.expect_eq (million.a, million.b, "salsa20 million");
}
///////////////////////////////////////////////////////////////////////////////
int
main (void)
{
util::TAP::logger tap;
test_quarter (tap);
test_row (tap);
test_col (tap);
test_doubleround (tap);
test_salsa20 (tap);
return 0;
}

View File

@ -1,58 +0,0 @@
#include "tap.hpp"
#include "types.hpp"
#include "crypto/tea.hpp"
int
main ()
{
// test vectors from 'TeaCrypt', by Logan J. Drews.
static const struct {
std::array<uint32_t,4> key;
std::array<uint32_t,2> dec;
std::array<uint32_t,2> enc;
} TESTS[] = {
{
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x00000000, 0x00000000 },
{ 0x41EA3A0A, 0x94BAA940 },
},
{
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x01020304, 0x05060708 },
{ 0x6A2F9CF3, 0xFCCF3C55 },
},
{
{ 0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF },
{ 0x01020304, 0x05060708 },
{ 0xDEB1C0A2, 0x7E745DB3 },
},
{
{ 0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF },
{ 0x01234567, 0x89ABCDEF },
{ 0x126C6B92, 0xC0653A3E },
},
};
util::TAP::logger tap;
for (size_t i = 0; i < std::size (TESTS); ++i) {
const auto &t = TESTS[i];
util::crypto::TEA gen (t.key);
std::array<uint32_t,2> enc (t.dec);
gen.encrypt (enc.data (), enc.size ());
std::array<uint32_t,2> dec (t.enc);
gen.decrypt (dec.data (), dec.size ());
tap.expect (enc == t.enc, "TEA_enc %zu", i);
tap.expect (dec == t.dec, "TEA_dec %zu", i);
}
return tap.status ();
}

View File

@ -1,57 +0,0 @@
#include "tap.hpp"
#include "crypto/xtea.hpp"
#include "types.hpp"
int
main ()
{
// test vectors from 'TeaCrypt', by Logan J. Drews.
static const struct {
std::array<uint32_t,4> key;
std::array<uint32_t,2> dec;
std::array<uint32_t,2> enc;
} TESTS[] = {
{
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00000000, 0x00000000},
{0xDEE9D4D8, 0xF7131ED9},
},
{
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x01020304, 0x05060708},
{0x065C1B89, 0x75C6A816},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x01020304, 0x05060708},
{0xDCDD7ACD, 0xC1584B79},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x01234567, 0x89ABCDEF},
{0xB8BF2821, 0x622B5B30},
},
};
util::TAP::logger tap;
for (size_t i = 0; i < std::size (TESTS); ++i) {
const auto &t = TESTS[i];
util::crypto::XTEA gen (t.key);
std::array<uint32_t,2> enc (t.dec);
gen.encrypt (enc.data (), enc.size ());
std::array<uint32_t,2> dec (t.enc);
gen.decrypt (dec.data (), dec.size ());
tap.expect (enc == t.enc, "XTEA_enc %zu", i);
tap.expect (dec == t.dec, "XTEA_dec %zu", i);
}
return tap.status ();
}

View File

@ -1,114 +0,0 @@
#include "crypto/xxtea.hpp"
#include "debug.hpp"
#include "tap.hpp"
#include "types.hpp"
#include <vector>
int
main ()
{
// test vectors from 'TeaCrypt', by Logan J. Drews.
static const struct {
std::array<uint32_t,4> key;
std::vector<uint32_t> dec;
std::vector<uint32_t> enc;
} TESTS[] = {
// 64 bit
{
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x00000000, 0x00000000 },
{ 0x053704AB, 0x575D8C80 }
},
{
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x01020304, 0x05060708},
{0xE6911910, 0x0C35DCDA},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x01020304, 0x05060708},
{0x961D49FC, 0x61FF12D6},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x01234567, 0x89ABCDEF},
{0x34354989, 0xDD7D1A7A},
},
// 96 bit
{
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00000000, 0x00000000, 0x00000000},
{0x5E3CD3F0, 0xE109E3CE, 0x79D7C945},
},
{
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00010203, 0x04050607, 0x08090A0B},
{0x5A545AAC, 0x684EB2CB, 0x3E1B8AA0},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x00010203, 0x04050607, 0x08090A0B},
{0x2E77CCEC, 0x674F5149, 0xA0E56496},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x01234567, 0x89ABCDEF, 0x01234567},
{0xEBC5DD46, 0xBE0FEE71, 0xC6BF7193},
},
// 128 bit
{
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0xE6C8D5FF, 0x070FB6E4, 0x98A534F7, 0xAC03E399},
},
{
{0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F},
{0xAF5CFB0E, 0xAE73552B, 0x1D968A9F, 0x5CB94509},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F},
{0x3EA0E16C, 0x9969535A, 0xE4796D50, 0xF217EEEA},
},
{
{0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF},
{0x01234567, 0x89ABCDEF, 0x01234567, 0x89ABCDEF},
{0x2B4AB1A4, 0x0E487B6D, 0x9A3AACC7, 0xE4132216},
},
};
util::TAP::logger tap;
for (size_t i = 0; i < std::size (TESTS); ++i) {
const auto &t = TESTS[i];
CHECK_EQ (t.dec.size (), t.enc.size ());
util::crypto::XXTEA gen (t.key);
std::vector<uint32_t> enc (t.dec);
gen.encrypt (enc.data (), enc.size ());
std::vector<uint32_t> dec (enc);
gen.decrypt (dec.data (), dec.size ());
tap.expect (enc == t.enc, "XXTEA_enc %zu", i);
tap.expect (dec == t.dec, "XXTEA_dec %zu", i);
}
return tap.status ();
}

View File

@ -1,7 +1,6 @@
#include "hash/adler.hpp"
#include "hash/bsdsum.hpp"
#include "hash/simple.hpp"
#include "types.hpp"
#include "tap.hpp"
@ -35,19 +34,19 @@ int
main (int, char**) {
util::TAP::logger tap;
util::hash::adler32 a;
util::hash::bsdsum b;
for (const auto &t: TESTS) {
tap.expect_eq (
t.adler,
util::hash::simple<util::hash::adler32> (
(const void*)t.data,
(const void*)(t.data + strlen (t.data))
),
a (util::view {t.data}.template cast<const uint8_t> ()),
"adler checksum: %s", t.msg
);
tap.expect_eq (
t.bsd,
util::hash::simple<util::hash::bsdsum> (t.data, t.data + strlen (t.data)),
b (util::view {t.data}.template cast<const uint8_t> ()),
"bsdsum checksum: %s", t.msg);
}

View File

@ -1,6 +1,5 @@
#include "tap.hpp"
#include "hash/crc.hpp"
#include "hash/simple.hpp"
#include <cstdint>
#include <utility>
@ -34,15 +33,8 @@ main (int, char**)
util::TAP::logger tap;
for (const auto &t: TESTS) {
auto first = t.dat;
auto last = first + strlen (t.dat);
#define TEST(KLASS) do { \
auto computed = \
util::hash::simple< \
util::hash::KLASS \
> (first, last); \
\
auto computed = util::hash::KLASS{}(util::view {t.dat}.template cast<const uint8_t> ()); \
tap.expect_eq (t.result.KLASS, computed, "%s: %s", #KLASS, t.msg); \
} while (0)

View File

@ -3,6 +3,19 @@
#include <cstring>
///////////////////////////////////////////////////////////////////////////////
std::vector<uint8_t>
operator"" _u8s (const char *str, size_t len)
{
std::vector<uint8_t> res;
res.resize (len);
std::copy_n (str, len, std::begin (res));
return res;
}
///////////////////////////////////////////////////////////////////////////////
int
main (void)
{
@ -13,23 +26,26 @@ main (void)
uint32_t hash32;
uint64_t seed64;
uint64_t hash64;
const char *str;
std::vector<uint8_t> data;
} TESTS[] = {
{ 0x00000000, 0x00000000, 0x0000000000000000, 0x0000000000000000, "" },
{ 0x00000001, 0xd30ac4de, 0x0000000000000001, 0x2127599bf4321e79, "" },
{ 0xffffffff, 0xf5c7b4b0, 0xffffffffffffffff, 0x9b4792000001368f, "" },
{ 0xf5c7b4b0, 0x228128b7, 0x9b4792000001368f, 0x67a642098cc81da6, "a" },
{ 0x228128b7, 0x8400568d, 0x67a642098cc81da6, 0xc906440e03ce99a8, "abc" },
{ 0x8400568d, 0x12b4858b, 0x67a642098cc81da6, 0x1a36fbf3d71b0737, "message digest" },
{ 0x12b4858b, 0x730b822e, 0x1a36fbf3d71b0737, 0x7b48e31e3ac40a0f, "abcdefghijklmnopqrstuvwxyz" },
{ 0x00000000, 0x00000000, 0x0000000000000000, 0x0000000000000000, ""_u8s },
{ 0x00000001, 0xd30ac4de, 0x0000000000000001, 0x2127599bf4321e79, ""_u8s },
{ 0xffffffff, 0xf5c7b4b0, 0xffffffffffffffff, 0x9b4792000001368f, ""_u8s },
{ 0xf5c7b4b0, 0x228128b7, 0x9b4792000001368f, 0x67a642098cc81da6, "a"_u8s },
{ 0x228128b7, 0x8400568d, 0x67a642098cc81da6, 0xc906440e03ce99a8, "abc"_u8s },
{ 0x8400568d, 0x12b4858b, 0x67a642098cc81da6, 0x1a36fbf3d71b0737, "message digest"_u8s },
{ 0x12b4858b, 0x730b822e, 0x1a36fbf3d71b0737, 0x7b48e31e3ac40a0f, "abcdefghijklmnopqrstuvwxyz"_u8s },
};
bool success32 = true;
bool success64 = true;
util::hash::fasthash<uint32_t> h32{};
util::hash::fasthash<uint64_t> h64{};
for (const auto &t: TESTS) {
success32 = success32 && t.hash32 == util::hash::fasthash::hash32 (t.str, strlen (t.str), t.seed32);
success64 = success64 && t.hash64 == util::hash::fasthash::hash64 (t.str, strlen (t.str), t.seed64);
success32 = success32 && t.hash32 == h32 (t.seed32, t.data);
success64 = success64 && t.hash64 == h64 (t.seed64, t.data);
}
tap.expect (success32, "fasthash32");

32
test/hash/fnv1a.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "hash/fnv1a.hpp"
#include "tap.hpp"
///////////////////////////////////////////////////////////////////////////////
static const struct {
uint32_t h32;
uint64_t h64;
const char *data;
} TESTS[] = {
{ 0x811c9dc5, 0xcbf29ce484222325, "" },
{ 0xe40c292c, 0xaf63dc4c8601ec8c, "a" },
{ 0xbf9cf968, 0x85944171f73967e8, "foobar" },
};
///////////////////////////////////////////////////////////////////////////////
int
main (void)
{
util::TAP::logger tap;
const util::hash::fnv1a<uint32_t> h32;
const util::hash::fnv1a<uint64_t> h64;
for (const auto &t: TESTS) {
tap.expect_eq (h32 (util::view{t.data}.cast <const uint8_t> ()), t.h32, "fnv1a32: '%s'", t.data);
tap.expect_eq (h64 (util::view{t.data}.cast <const uint8_t> ()), t.h64, "fnv1a64: '%s'", t.data);
}
return tap.status ();
}

View File

@ -1,280 +0,0 @@
#include "hash/hmac.hpp"
#include "debug.hpp"
#include "hash/md5.hpp"
#include "hash/sha1.hpp"
#include "tap.hpp"
#include "types.hpp"
#include <cstring>
#include <iostream>
#include <vector>
using util::hash::HMAC;
//-----------------------------------------------------------------------------
std::vector<uint8_t>
to_vector (const char *str)
{
return std::vector<uint8_t> (str, str + strlen (str));
}
//-----------------------------------------------------------------------------
template <class T>
bool
test_hmac (const std::vector<uint8_t> &key,
const std::vector<uint8_t> &dat,
const std::vector<uint8_t> &res)
{
util::hash::HMAC<T> h (key.data (), key.size ());
h.update (dat.data (), dat.size ());
h.finish ();
auto ours = h.digest ();
return std::equal (ours.begin (), ours.end (), res.begin ());
}
typedef bool (*test_func) (const std::vector<uint8_t>&,
const std::vector<uint8_t>&,
const std::vector<uint8_t>&);
//-----------------------------------------------------------------------------
static const struct {
std::vector<uint8_t> key;
std::vector<uint8_t> dat;
std::vector<uint8_t> res;
test_func fun;
} 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 },
&test_hmac<util::hash::MD5>
},
{
to_vector ("Jefe"),
to_vector ("what do ya want for nothing?"),
{ 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 },
&test_hmac<util::hash::MD5>
},
{
{ 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 },
&test_hmac<util::hash::MD5>
},
// RFC 2202 test data, MD5
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19 },
{ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
0xCD, 0xCD },
{ 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 },
&test_hmac<util::hash::MD5>
},
{
{ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
to_vector ("Test With Truncation"),
{ 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c },
&test_hmac<util::hash::MD5>
// digest-96: 0x56461ef2342edc00f9bab995
},
{
{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
to_vector ("Test Using Larger Than Block-Size Key - Hash Key First"),
{ 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd },
&test_hmac<util::hash::MD5>
},
{
{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
to_vector ("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
{ 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e },
&test_hmac<util::hash::MD5>
},
// RFC 2202 test data, SHA1
{
{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b },
to_vector ("Hi There"),
{ 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
0xf1, 0x46, 0xbe, 0x00 },
&test_hmac<util::hash::SHA1>
},
{
to_vector ("Jefe"),
to_vector ("what do ya want for nothing?"),
{ 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2,
0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c,
0x25, 0x9a, 0x7c, 0x79 },
&test_hmac<util::hash::SHA1>
},
{
{ 0xaa, 0xaa, 0xaa, 0xaa, 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 },
{ 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd,
0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f,
0x63, 0xf1, 0x75, 0xd3 },
&test_hmac<util::hash::SHA1>
},
{
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19 },
{ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd },
{ 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6,
0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c,
0x2d, 0x72, 0x35, 0xda },
&test_hmac<util::hash::SHA1>
},
{
{ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c },
to_vector ("Test With Truncation"),
{ 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f,
0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32,
0x4a, 0x9a, 0x5a, 0x04 },
&test_hmac<util::hash::SHA1>
},
{
{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
to_vector ("Test Using Larger Than Block-Size Key - Hash Key First"),
{ 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e,
0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55,
0xed, 0x40, 0x21, 0x12 },
&test_hmac<util::hash::SHA1>
},
{
{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
to_vector ("Test Using Larger Than Block-Size Key - Hash Key First"),
{ 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e,
0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55,
0xed, 0x40, 0x21, 0x12 },
&test_hmac<util::hash::SHA1>
},
{
{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
to_vector ("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
{ 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78,
0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08,
0xbb, 0xff, 0x1a, 0x91 },
&test_hmac<util::hash::SHA1>
},
};
//-----------------------------------------------------------------------------
int
main (int, char**)
{
util::TAP::logger tap;
for (size_t i = 0; i < std::size (TESTS); ++i)
tap.expect (TESTS[i].fun (TESTS[i].key, TESTS[i].dat, TESTS[i].res), "standard test vector %zu", i);
return tap.status ();
}

View File

@ -1,34 +0,0 @@
#include "hash/hotp.hpp"
#include "debug.hpp"
#include "tap.hpp"
#include "types.hpp"
using util::hash::HOTP;
int
main (int, char**)
{
HOTP h ("12345678901234567890", 0);
const unsigned EXPECTED[] = {
755224,
287082,
359152,
969429,
338314,
254676,
287922,
162583,
399871,
520489,
};
util::TAP::logger tap;
for (auto &i: EXPECTED)
tap.expect_eq (i, h.value (), "sequence");
return tap.status ();
}

View File

@ -1,180 +0,0 @@
#include "hash/keccak.hpp"
#include "debug.hpp"
#include "tap.hpp"
#include <iomanip>
#include <vector>
static constexpr
uint8_t
from_hex (char c) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return c - '0';
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
return 10 + c - 'A';
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
return 10 + c - 'a';
}
unreachable ();
}
template <size_t S>
static constexpr
std::array<uint8_t,S/2>
make_array (const char (&str)[S])
{
if (S < 1)
return {};
static_assert (S % 2 == 1, "requires full bytes + null");
std::array<uint8_t,S/2> out {};
for (size_t i = 0; i < S - 1; i+=2) {
out[i / 2] = +from_hex (str[i]) << 4 | +from_hex (str[i+1]);
}
return out;
}
template <size_t S>
static
std::vector<uint8_t>
make_vector (const char (&str)[S]) {
const auto arr = make_array (str);
return std::vector<uint8_t> (arr.cbegin (), arr.cend ());
}
int
main (int, char**)
{
util::TAP::logger tap;
static const struct {
const char *msg;
std::vector<uint8_t> data;
std::array<uint8_t, 28> sha3_224;
std::array<uint8_t, 32> sha3_256;
std::array<uint8_t, 48> sha3_384;
std::array<uint8_t, 64> sha3_512;
} TESTS[] = {
{
" empty string",
{ },
make_array ("6B4E03423667DBB73B6E15454F0EB1ABD4597F9A1B078E3F5B5A6BC7"),
make_array ("A7FFC6F8BF1ED76651C14756A061D662F580FF4DE43B49FA82D80A4B80F8434A"),
make_array ("0C63A75B845E4F7D01107D852E4C2485C51A50AAAA94FC61995E71BBEE983A2AC3713831264ADB47FB6BD1E058D5F004"),
make_array ("A69F73CCA23A9AC5C8B567DC185A756E97C982164FE25859E0D1DCC1475C80A615B2123AF1F5F94C11E3E9402C3AC558F500199D95B6D3E301758586281DCD26"),
},
{
" 8-bit string",
make_vector ("CC"),
make_array ("DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"),
make_array ("677035391CD3701293D385F037BA32796252BB7CE180B00B582DD9B20AAAD7F0"),
make_array ("5EE7F374973CD4BB3DC41E3081346798497FF6E36CB9352281DFE07D07FC530CA9AD8EF7AAD56EF5D41BE83D5E543807"),
make_array ("3939FCC8B57B63612542DA31A834E5DCC36E2EE0F652AC72E02624FA2E5ADEECC7DD6BB3580224B4D6138706FC6E80597B528051230B00621CC2B22999EAA205"),
},
{
" 16-bit string",
make_vector ("41FB"),
make_array ("BFF295861DAEDF33E70519B1E2BCB4C2E9FE3364D789BC3B17301C15"),
make_array ("39F31B6E653DFCD9CAED2602FD87F61B6254F581312FB6EEEC4D7148FA2E72AA"),
make_array ("1DD81609DCC290EFFD7AC0A95D4A20821580E56BD50DBD843920650BE7A80A1719577DA337CFDF86E51C764CAA2E10BD"),
make_array ("AA092865A40694D91754DBC767B5202C546E226877147A95CB8B4C8F8709FE8CD6905256B089DA37896EA5CA19D2CD9AB94C7192FC39F7CD4D598975A3013C69"),
},
{
"224-bit string",
make_vector ("0F8B2D8FCFD9D68CFFC17CCFB117709B53D26462A3F346FB7C79B85E"),
make_array ("1E693B0BCE2372550DAEF35B14F13AB43441ED6742DEE3E86FD1D8EF"),
make_array ("6DE164A9626D5A4F54D854AC158994F35A8E362ECC753F55182790934A2E0D06"),
make_array ("641A7AF13B889D1A0F1AA3E4E4FF8CC5903C47E1A52BDEA257D80E37E596564AB33EEAD06717CDB6B706CB6986293D4F"),
make_array ("21132FC11F6040AD493D627027C752CE29816589DE7BE78562914B63D1A9219803DDBD9673AA749F37FF4D6E1B5AE2A12633BA8B0C9994E031EBF6C42E58A793"),
},
{
"256-bit string",
make_vector ("9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10"),
make_array ("887921848AD98458F3DB3E0ECD5AD5DB1F0BF9F2D0CA08601074D597"),
make_array ("2F1A5F7159E34EA19CDDC70EBF9B81F1A66DB40615D7EAD3CC1F1B954D82A3AF"),
make_array ("BAAE7AAED4FBF42F9316C7E8F722EEB06A598B509F184B22FBD5A81C93D95FFF711F5DE90847B3248B6DF76CABCE07EE"),
make_array ("B087C90421AEBF87911647DE9D465CBDA166B672EC47CCD4054A7135A1EF885E7903B52C3F2C3FE722B1C169297A91B82428956A02C631A2240F12162C7BC726"),
},
{
"384-bit string",
make_vector ("D8FABA1F5194C4DB5F176FABFFF856924EF627A37CD08CF55608BBA8F1E324D7C7F157298EABC4DCE7D89CE5162499F9"),
make_array ("B7A51FBB084DEEB55136EFD7260E5B112E3C40D1A2D14B142DF930DF"),
make_array ("34F8607EC10C092C1BA0B6565CE6197062C4E1A35A8E8C723E48A2D2416C3790"),
make_array ("A127FEFCDD240F762CCE3F5F1551FC7E1CDEBC7950D1CD94C6888F490CB2285A10FD0EE797B168C5CA4761FA232AAF05"),
make_array ("7EF3A2894C6ECBC4201B15348F90671515ACCBA3C8166621F864A9184BF08C3F5A895F6B599D3CB41F20A8A1DF25AE84F1A6D7C8DE74FB7CEF48F7E96FDE8D43"),
},
{
"512-bit string",
make_vector ("E926AE8B0AF6E53176DBFFCC2A6B88C6BD765F939D3D178A9BDE9EF3AA131C61E31C1E42CDFAF4B4DCDE579A37E150EFBEF5555B4C1CB40439D835A724E2FAE7"),
make_array ("C154607F986F9BF902D831293C8386D36B201EABA6F6FB0B678B4B81"),
make_array ("27A6441EE939B46E2C378D7AFEB0E891C47A28120E488EFF0AB71AF08788CEB3"),
make_array ("423BA134D3BCB5E440AC83372C7EDDBA3AE3BDDF1222F505C19CDE246AD76A2B0D07239A54E1D0934C9B3D29D49E5FBD"),
make_array ("EB5067BF762A291CF258AD69A816A0B089E0BD44F8E5B74CF60BCE64734E59853CCB8D091CD2E33F90AA063FB7942CF5965D459200144C1A0801ABD69A9A094A"),
},
{
"520-bit string",
make_vector ("16E8B3D8F988E9BB04DE9C96F2627811C973CE4A5296B4772CA3EEFEB80A652BDF21F50DF79F32DB23F9F73D393B2D57D9A0297F7A2F2E79CFDA39FA393DF1AC00"),
make_array ("95E87AC90F541AB90CBCF7FD7E0E0C152CEF78D5EE1830E9ED8A1ED7"),
make_array ("C4BB067383002DB44CA773918BB74104B604A583E12B06BE56C270F8B43512F2"),
make_array ("662C4851D311A786DE4CDA7E9EA1EFF0BFA462761FF6CF804E591ED9A15B0DC93A2BB6A6CFFDC8D7D23A233A52C86EAD"),
make_array ("B0E23D600BA4215F79D50047BBFED50DF7D6E769514D796AFD166DEECA88BD1CBE0AFC72A41E0317A223225B4F5882F723AFCBA3AF7C457EB525946DA6C53BB0"),
},
{
"1,000,000 'a' string",
std::vector<uint8_t> (1'000'000, 'a'),
make_array ("d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c"),
make_array ("5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1"),
make_array ("eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340"),
make_array ("3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87"),
}
};
for (const auto &t: TESTS) {
#define TEST(WIDTH) \
do { \
std::array<uint8_t, WIDTH/8> sha3_##WIDTH; \
std::fill (std::begin (sha3_##WIDTH), std::end (sha3_##WIDTH), 0); \
\
FIPS202_SHA3_##WIDTH (t.data.data (), t.data.size (), &sha3_##WIDTH[0]); \
\
tap.expect_eq (t.sha3_##WIDTH, sha3_##WIDTH, "sha3-%u %s", unsigned (WIDTH), t.msg); \
} while (0)
TEST(224);
TEST(256);
TEST(384);
TEST(512);
}
return tap.status ();
}

View File

@ -1,64 +0,0 @@
#include "hash/md2.hpp"
#include "tap.hpp"
using util::hash::MD2;
#include <cstring>
#include <iostream>
int
main (int, char **) {
static const struct {
const char *input;
MD2::digest_t output;
} TESTS[] = {
{ "",
{ { 0x83, 0x50, 0xe5, 0xa3, 0xe2, 0x4c, 0x15, 0x3d,
0xf2, 0x27, 0x5c, 0x9f, 0x80, 0x69, 0x27, 0x73 } }
},
{ "a",
{ { 0x32, 0xec, 0x01, 0xec, 0x4a, 0x6d, 0xac, 0x72,
0xc0, 0xab, 0x96, 0xfb, 0x34, 0xc0, 0xb5, 0xd1 } }
},
{ "abc",
{ { 0xda, 0x85, 0x3b, 0x0d, 0x3f, 0x88, 0xd9, 0x9b,
0x30, 0x28, 0x3a, 0x69, 0xe6, 0xde, 0xd6, 0xbb } }
},
{ "message digest",
{ { 0xab, 0x4f, 0x49, 0x6b, 0xfb, 0x2a, 0x53, 0x0b,
0x21, 0x9f, 0xf3, 0x30, 0x31, 0xfe, 0x06, 0xb0 } }
},
{ "abcdefghijklmnopqrstuvwxyz",
{ { 0x4e, 0x8d, 0xdf, 0xf3, 0x65, 0x02, 0x92, 0xab,
0x5a, 0x41, 0x08, 0xc3, 0xaa, 0x47, 0x94, 0x0b } }
},
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{ { 0xda, 0x33, 0xde, 0xf2, 0xa4, 0x2d, 0xf1, 0x39,
0x75, 0x35, 0x28, 0x46, 0xc3, 0x03, 0x38, 0xcd } }
},
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{ { 0xd5, 0x97, 0x6f, 0x79, 0xd8, 0x3d, 0x3a, 0x0d,
0xc9, 0x80, 0x6c, 0x3c, 0x66, 0xf3, 0xef, 0xd8 } }
}
};
bool success = true;
for (const auto &i: TESTS) {
MD2 h;
h.update (i.input, strlen (i.input));
h.finish ();
auto out = h.digest ();
if (out != i.output) {
std::cerr << "Failed on " << i.input << "\n";
success = false;
}
}
util::TAP::logger tap;
tap.expect (success, "test vectors");
return tap.status ();
}

View File

@ -1,72 +0,0 @@
#include "hash/md4.hpp"
#include "tap.hpp"
#include <cstring>
#include <iostream>
using util::hash::MD4;
int
main (int, char**) {
static const struct {
const char *input;
MD4::digest_t output;
} TESTS[] = {
{
"",
{ { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 } }
},
{
"a",
{ { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 } }
},
{
"abc",
{ { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d } }
},
{
"message digest",
{ { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b } }
},
{
"abcdefghijklmnopqrstuvwxyz",
{ { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 }, }
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{ { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 } }
},
{
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{ { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 } }
}
};
bool success = true;
for (auto i: TESTS) {
MD4 h;
h.update (i.input, strlen (i.input));
h.finish ();
auto out = h.digest ();
if (out != i.output) {
std::cerr << "Failed on '" << i.input << "'\n";
success = false;
}
}
util::TAP::logger tap;
tap.expect (success, "test vectors");
return tap.status ();
}

View File

@ -1,63 +0,0 @@
#include "hash/md5.hpp"
#include "tap.hpp"
#include <iostream>
#include <cstring>
using util::hash::MD5;
int
main (int, char**) {
static const struct {
const char *input;
MD5::digest_t output;
} TESTS[] = {
{ "",
{ { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }
},
{ "a",
{ { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }
},
{ "abc",
{ { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }
},
{ "message digest",
{ { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }
},
{ "abcdefghijklmnopqrstuvwxyz",
{ { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }
},
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{ { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }
},
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{ { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }
}
};
bool success = true;
for (auto i: TESTS) {
MD5 h;
h.update (i.input, strlen (i.input));
h.finish ();
auto out = h.digest ();
if (out != i.output) {
std::cerr << "Failed on '" << i.input << "'\n";
success = false;
}
}
util::TAP::logger tap;
tap.expect (success, "test vectors");
return tap.status ();
}

View File

@ -6,11 +6,35 @@
#include <cstring>
///////////////////////////////////////////////////////////////////////////////
std::vector<uint8_t>
operator"" _u8s (const char *str, size_t len)
{
std::vector<uint8_t> res;
res.resize (len);
std::copy_n (str, len, std::begin (res));
return res;
}
///////////////////////////////////////////////////////////////////////////////
template <size_t N>
std::ostream&
operator<< (std::ostream &os, std::array<uint8_t,N> &val)
{
for (auto c: val)
os << c;
return os;
}
///////////////////////////////////////////////////////////////////////////////
void
test (util::TAP::logger &tap)
{
struct {
const char *key;
std::vector<uint8_t> data;
const char *msg;
struct { uint32_t seed; uint32_t hash; } m1_32;
struct { uint32_t seed; uint32_t hash; } m2_32;
@ -21,7 +45,8 @@ test (util::TAP::logger &tap)
struct { uint32_t seed; std::array<uint64_t,2> hash; } m3_128_x64;
} TESTS[] = {
{ "",
{ ""_u8s,
"empty, zero seed",
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
@ -30,7 +55,8 @@ test (util::TAP::logger &tap)
{ 0, 0 },
},
{ "",
{ ""_u8s,
"empty, nonzero seed",
{ 0x00000001, 0x8f5a8d63 },
{ 0x00000001, 0x5bd15e36 },
{ 1, 0xc6a4a7935bd064dc },
@ -39,7 +65,8 @@ test (util::TAP::logger &tap)
{ 1, { 0x4610abe56eff5cb5, 0x51622daa78f83583 } },
},
{ "",
{ ""_u8s,
"empty, max seed",
{ 0xffffffff, 0x7a3f4f7e },
{ 0xffffffff, 0xb35966b0 },
{ uint64_t(-1), 0xb0d9485c2cd761b2 },
@ -48,7 +75,8 @@ test (util::TAP::logger &tap)
{ 0xffffffff, { 0x6af1df4d9d3bc9ec, 0x857421121ee6446b } },
},
{ "a",
{ "a"_u8s,
"1 byte",
{ 0x7a3f4f7e, 0x18abad09 },
{ 0xb35966b0, 0x1eea8b10 },
{ 0xb0d9485c2cd761b2, 0x0a9b4c93b35b1b9f },
@ -56,7 +84,8 @@ test (util::TAP::logger &tap)
{ 0x051e08a9, { 0x08e91d27, 0x12c6d92a, 0x12c6d92a, 0x12c6d92a } },
{ 0x9d3bc9ec, { 0xf79489c9f1a785de, 0xf6486d31835a9c7f } },
},
{ "abc",
{ "abc"_u8s,
"3 byte",
{ 0x18abad09, 0x1defb5e9 },
{ 0x1eea8b10, 0x72cac527 },
{ 0x0a9b4c93b35b1b9f, 0x2ffdf3214d9a4fa4 },
@ -64,7 +93,8 @@ test (util::TAP::logger &tap)
{ 0x08e91d27, { 0xc11cc883, 0xb5d7f69a, 0xb5d7f69a, 0xb5d7f69a } },
{ 0xf1a785de, { 0x946e5ee63ce3b80e, 0xadb7d6d0e2558c3c } },
},
{ "message digest",
{ "message digest"_u8s,
"14 byte",
{ 0x1defb5e9, 0x7b3ea4bd },
{ 0x72cac527, 0x68563c37 },
{ 0x2ffdf3214d9a4fa4, 0x9a83e79336350cee },
@ -73,7 +103,8 @@ test (util::TAP::logger &tap)
{ 0x3ce3b80e, { 0x2c91b16326bf5f7f, 0xa21acf13c39485bc } },
},
{ "abcdefghijklmnopqrstuvwxyz",
{ "abcdefghijklmnopqrstuvwxyz"_u8s,
"26 byte",
{ 0x7b3ea4bd, 0xd94ee9ea },
{ 0x68563c37, 0x0473b699 },
{ 0x9a83e79336350cee, 0x1f256c898952ae12 },
@ -83,42 +114,29 @@ test (util::TAP::logger &tap)
}
};
bool m1_32 = true;
bool m2_32 = true;
bool m2_64 = true;
bool m3_32 = true;
bool m3_128_x86 = true;
bool m3_128_x64 = true;
for (const auto &t: TESTS) {
m1_32 = m1_32 && (t.m1_32.hash == util::hash::murmur1::hash_32 (t.key, strlen (t.key), t.m1_32.seed));
m2_32 = m2_32 && (t.m2_32.hash == util::hash::murmur2::hash_32 (t.key, strlen (t.key), t.m2_32.seed));
m2_64 = m2_64 && (t.m2_64.hash == util::hash::murmur2::hash_64 (t.key, strlen (t.key), t.m2_64.seed));
m3_32 = m3_32 && (t.m3_32.hash == util::hash::murmur3::hash_32 (t.key, strlen (t.key), t.m3_32.seed));
const util::hash::murmur1 h1 (t.m1_32.seed);
{
auto result = util::hash::murmur3::hash_128_x86 (t.key, strlen (t.key), t.m3_128_x86.seed);
bool success = t.m3_128_x86.hash == result;
m3_128_x86 = m3_128_x86 && success;
}
const util::hash::murmur2<uint32_t> h2_32 (t.m2_32.seed);
const util::hash::murmur2<uint64_t> h2_64 (t.m2_64.seed);
{
auto result = util::hash::murmur3::hash_128_x64 (t.key, strlen (t.key), t.m3_128_x64.seed);
bool success = t.m3_128_x64.hash == result;
m3_128_x64 = m3_128_x64 && success;
const util::hash::murmur3_32 h3 (t.m3_32.seed);
const util::hash::murmur3_128_x86 h3_x86 (t.m3_128_x86.seed);
const util::hash::murmur3_128_x64 h3_x64 (t.m3_128_x64.seed);
tap.expect_eq (h1 (t.data), t.m1_32.hash, "murmur1_32, '%s'", t.msg);
tap.expect_eq (h2_32 (t.data), t.m2_32.hash, "murmur2_32, '%s'", t.msg);
tap.expect_eq (h2_64 (t.data), t.m2_64.hash, "murmur2_64, '%s'", t.msg);
tap.expect_eq (h3 (t.data), t.m3_32.hash, "murmur3_32, '%s'", t.msg);
tap.expect_eq (h3_x86 (t.data), t.m3_128_x86.hash, "murmur3_128_x86, '%s'", t.msg);
tap.expect_eq (h3_x64 (t.data), t.m3_128_x64.hash, "murmur3_128_x64, '%s'", t.msg);
}
}
tap.expect (m1_32, "murmur1_32");
tap.expect (m2_32, "murmur2_32");
tap.expect (m2_64, "murmur2_64");
tap.expect (m3_32, "murmur3_32");
tap.expect (m3_128_x86, "murmur3_128_x86");
tap.expect (m3_128_x64, "murmur3_128_x64");
}
///////////////////////////////////////////////////////////////////////////////
int
main (void)
{

View File

@ -1,142 +0,0 @@
#include "hash/ripemd.hpp"
#include "tap.hpp"
#include "types.hpp"
#include <cstring>
static const
struct {
const char *msg;
const char *data;
util::hash::RIPEMD::digest_t output;
} TESTS[] = {
{
"empty",
"",
{ 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 },
// 128: cdf26213a150dc3ecb610f18f6b38b46
// 160: 9c1185a5c5e9fc54612808977ee8f548b2258d31
// 256: 02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d
// 320: 22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8
},
{
"a",
"a",
{ 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe },
// 128: 86be7afa339d0fc7cfc785e72f578d33
// 160: 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe
// 256: f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925
// 320: ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d
},
{
"abc",
"abc",
{ 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc },
// 128: c14a12199c66e4ba84636b0f69144c77
// 160: 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
// 256: afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65
// 320: de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d
},
{
"message digest",
"message digest",
{ 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 },
// 128: 9e327b3d6e523062afc1132d7df9d1b8
// 160: 5d0689ef49d2fae572b881b123a85ffa21595f36
// 256: 87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e
// 320: 3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197
},
{
"26 characters",
"abcdefghijklmnopqrstuvwxyz",
{ 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc },
// 128: fd2aa607f71dc8f510714922b371834e
// 160: f71c27109c692c1b56bbdceb5b9d2865b3708dbc
// 256: 649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133
// 320: cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009
},
{
"57 characters",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{ 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b },
// 128: a1aa0689d0fafa2ddc22e88b49133a06
// 160: 12a053384a9c0c88e405a06c27dcf49ada62eb2b
// 256: 3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f
// 320: d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac
},
{
"63 characters",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{ 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,
0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 },
// 128: d1e959eb179c911faea4624c60c5c702
// 160: b0e20b6e3116640286ed3a87a5713079b21f5189
// 256: 5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8
// 320: ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4
},
{
"81 digits",
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{ 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,
0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }
// 128: 3f45ef194732c2dbb2c4a2c769795fa3
// 160: 9b752e45573d4b39f4dbd3323cab82bf63326bfb
// 256: 06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd
// 320: 557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42
}
};
// 1 million times "a"
// 128: 4a7f5723f954eba1216c9d8f6320431f
// 160: 52783243c1697bdbe16d37f97f68f08325dc1528
// 256: ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978
// 320: bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66
int
main(int, char**) {
util::TAP::logger tap;
// Check against simple test vectors
for (const auto &i: TESTS) {
util::hash::RIPEMD obj;
obj.update (reinterpret_cast<const uint8_t*> (i.data), strlen (i.data));
obj.finish ();
tap.expect_eq (obj.digest (), i.output, "%s", i.msg);
}
// Perform 'million-a' check
static const size_t CHUNK_WIDTH = 1'000;
util::hash::RIPEMD obj;
for (size_t i = 0; i < 1'000'000; i += CHUNK_WIDTH) {
uint8_t data[CHUNK_WIDTH];
memset (data, 'a', sizeof (data));
obj.update (data, sizeof (data));
}
obj.finish ();
static const util::hash::RIPEMD::digest_t MILLION {
0x52, 0x78, 0x32, 0x43, 0xc1, 0x69, 0x7b, 0xdb, 0xe1, 0x6d,
0x37, 0xf9, 0x7f, 0x68, 0xf0, 0x83, 0x25, 0xdc, 0x15, 0x28
};
tap.expect_eq (obj.digest (), MILLION, "million 'a'");
return tap.status ();
}

View File

@ -1,73 +0,0 @@
#include "hash/sha1.hpp"
#include "debug.hpp"
#include "tap.hpp"
#include "types.hpp"
#include <cstdlib>
#include <cstring>
#include <iostream>
int
main (int, char**)
{
util::TAP::logger tap;
static const struct {
const char *msg;
const char *input;
util::hash::SHA1::digest_t output;
} TESTS[] = {
{
"empty string",
"",
{ { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 } }
},
{
"single a",
"a",
{ { 0x86, 0xf7, 0xe4, 0x37, 0xfa, 0xa5, 0xa7, 0xfc, 0xe1, 0x5d,
0x1d, 0xdc, 0xb9, 0xea, 0xea, 0xea, 0x37, 0x76, 0x67, 0xb8 } }
},
{
"abc",
"abc",
{ { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D } }
},
{
"abc...opq",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 } }
},
// 1'000'000 * 'a'
//{ "a",
// { { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
// 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } }
//},
// 80 repetitions of 01234567
//{ "0123456701234567012345670123456701234567012345670123456701234567",
// { { 0xDE, 0xA3, 0x56, 0xA2, 0xCD, 0xDD, 0x90, 0xC7, 0xA7, 0xEC,
// 0xED, 0xC5, 0xEB, 0xB5, 0x63, 0x93, 0x4F, 0x46, 0x04, 0x52 } }
//}
};
for (const auto &i: TESTS) {
util::hash::SHA1 obj;
obj.update (reinterpret_cast<const uint8_t*> (i.input), strlen (i.input));
obj.finish ();
tap.expect_eq (obj.digest (), i.output, "%s", i.msg);
}
return tap.status ();
}

View File

@ -1,62 +0,0 @@
#include "hash/sha2.hpp"
#include "tap.hpp"
#include <cstring>
static const struct {
const char *msg;
const char *input;
util::hash::SHA256::digest_t output;
} TESTS[] = {
{
"empty",
"",
{ 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55 }
},
{
"single a",
"a",
{ 0xCA, 0x97, 0x81, 0x12, 0xCA, 0x1B, 0xBD, 0xCA, 0xFA, 0xC2, 0x31, 0xB3, 0x9A, 0x23, 0xDC, 0x4D,
0xA7, 0x86, 0xEF, 0xF8, 0x14, 0x7C, 0x4E, 0x72, 0xB9, 0x80, 0x77, 0x85, 0xAF, 0xEE, 0x48, 0xBB }
},
{
"abc",
"abc",
{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
},
{
"abc...opq",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }
},
{
"77 digits",
"0123456701234567012345670123456701234567012345670123456701234567",
{ 0x81, 0x82, 0xCA, 0xDB, 0x21, 0xAF, 0x0E, 0x37, 0xC0, 0x64, 0x14, 0xEC, 0xE0, 0x8E, 0x19, 0xC6,
0x5B, 0xDB, 0x22, 0xC3, 0x96, 0xD4, 0x8B, 0xA7, 0x34, 0x10, 0x12, 0xEE, 0xA9, 0xFF, 0xDF, 0xDD }
}
};
int
main (int, char **) {
util::TAP::logger tap;
for (const auto &i: TESTS) {
util::hash::SHA256 obj;
obj.update (reinterpret_cast<const uint8_t*> (i.input), strlen (i.input));
obj.finish ();
tap.expect_eq (obj.digest (), i.output, "%s", i.msg);
}
return tap.status ();
}

View File

@ -17,9 +17,21 @@
#include "tap.hpp"
#include "hash/simple.hpp"
#include "hash/xxhash.hpp"
///////////////////////////////////////////////////////////////////////////////
std::vector<uint8_t>
operator"" _u8s (const char *str, size_t len)
{
std::vector<uint8_t> res;
res.resize (len);
std::copy_n (str, len, std::begin (res));
return res;
}
///////////////////////////////////////////////////////////////////////////////
int
main (int, char **)
{
@ -29,29 +41,27 @@ main (int, char **)
uint32_t hash32;
uint64_t hash64;
unsigned seed;
std::string data;
std::string msg;
std::vector<uint8_t> data;
const char *msg;
} TESTS[] = {
{ 0x02CC5D05, 0xef46db3751d8e999, 0, "", "empty string, 0 seed" },
{ 0x0b2cb792, 0xd5afba1336a3be4b, 1, "", "empty string, 1 seed" },
{ 0x550d7456, 0xd24ec4f1a98c6e5b, 0, "a", "single a, 0 seed" },
{ 0xf514706f, 0xdec2bc81c3cd46c6, 1, "a", "single a, 1 seed" },
{ 0x32d153ff, 0x44bc2cf5ad770999, 0, "abc", "abc, 0 seed" },
{ 0xaa3da8ff, 0xbea9ca8199328908, 1, "abc", "abc, 1 seed" },
{ 0x02CC5D05, 0xef46db3751d8e999, 0, ""_u8s, "empty string, 0 seed" },
{ 0x0b2cb792, 0xd5afba1336a3be4b, 1, ""_u8s, "empty string, 1 seed" },
{ 0x550d7456, 0xd24ec4f1a98c6e5b, 0, "a"_u8s, "single a, 0 seed" },
{ 0xf514706f, 0xdec2bc81c3cd46c6, 1, "a"_u8s, "single a, 1 seed" },
{ 0x32d153ff, 0x44bc2cf5ad770999, 0, "abc"_u8s, "abc, 0 seed" },
{ 0xaa3da8ff, 0xbea9ca8199328908, 1, "abc"_u8s, "abc, 1 seed" },
{ 0x54ca7e46, 0x892a0760a6343391, 0x1234,
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+",
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+"_u8s,
"long alphabet" }
};
for (const auto &t: TESTS) {
auto first = t.data.data ();
auto last = first + t.data.size ();
util::hash::xxhash32 h32 (t.seed);
//util::hash::xxhash32 h64 (t.seed);
auto digest32 = util::hash::simple<util::hash::xxhash32> (first, last, t.seed);
//auto digest64 = util::hash::simple<util::hash::xxhash64> (first, last, t.seed);
tap.expect_eq (digest32, t.hash32, "xxhash32 %s", t.msg);
//tap.expect_eq (digest64, t.hash64, "xxhash64 %s", t.msg);
tap.expect_eq (h32 (t.data), t.hash32, "xxhash32 %s", t.msg);
//tap.expect_eq (h64 (t.data), t.hash64, "xxhash64 %s", t.msg);
}
return tap.status ();

View File

@ -6,6 +6,8 @@
using namespace util;
///////////////////////////////////////////////////////////////////////////////
int
main (void)
{

View File

@ -97,7 +97,6 @@ to_epoch (const tm &t)
// similar. in the future we can account for this
CHECK_SANITY (t);
constexpr int
cumulative_days [12] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334

View File

@ -1,151 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright:
* 2014-2016, Danny Robson <danny@nerdcruft.net>
*/
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "io.hpp"
#include "stream.hpp"
#include "hash/simple.hpp"
#include "hash/adler.hpp"
#include "hash/bsdsum.cpp"
#include "hash/crc.hpp"
#include "hash/md2.hpp"
#include "hash/md4.hpp"
#include "hash/md5.hpp"
#include "hash/ripemd.hpp"
#include "hash/sha1.hpp"
#include "hash/sha2.hpp"
///////////////////////////////////////////////////////////////////////////////
static
const char* NAMES[] = {
"adler32",
"bsdsum",
"crc",
"MD2",
"MD4",
"MD5",
"RIPEMD",
"SHA1",
"SHA256",
};
///////////////////////////////////////////////////////////////////////////////
std::ostream&
print_digest (std::ostream &os, uint32_t t)
{
return os << std::hex << t << std::dec;
}
//-----------------------------------------------------------------------------
template <size_t S>
std::ostream&
print_digest (std::ostream &os, std::array<uint8_t,S> digest)
{
util::stream::scoped::flags f (os);
os << std::hex;
for (auto c: digest)
os << +(c >> 4) << +(c & 0x0F);
return os;
}
///////////////////////////////////////////////////////////////////////////////
static
void
compute (const std::string &name,
const unsigned char *restrict first,
const unsigned char *restrict last)
{
#define stream(TYPE, ...) do { \
if (name != #TYPE) \
break; \
\
auto sum = util::hash::simple<util::hash::TYPE> ( \
first, last, ##__VA_ARGS__ \
); \
\
print_digest (std::cout, sum) << '\n'; \
return; \
} while (0);
stream (adler32);
stream (bsdsum);
stream (crc32);
stream (MD2);
stream (MD4);
stream (MD5);
stream (RIPEMD);
stream (SHA1);
stream (SHA256);
#undef stream
}
///////////////////////////////////////////////////////////////////////////////
enum {
ARG_CMD,
ARG_HASH,
ARG_INPUT,
NUM_ARGS
};
//-----------------------------------------------------------------------------
void
print_usage (int argc, char **argv)
{
(void)argc;
std::cerr << argv[ARG_CMD] << " [";
for (auto name: NAMES)
std::cerr << name << "|";
std::cerr << "] <input>\n";
}
//-----------------------------------------------------------------------------
int
main (int argc, char **argv)
{
if (argc != NUM_ARGS) {
print_usage (argc, argv);
return EXIT_FAILURE;
}
if (strcmp (argv[ARG_INPUT], "-")) {
util::mapped_file src (argv[ARG_INPUT]);
compute (argv[ARG_HASH], src.cbegin (), src.cend ());
return EXIT_SUCCESS;
} else {
//compute (argv[ARG_HASH], std::cin);
return EXIT_SUCCESS;
}
}

View File

@ -51,7 +51,7 @@ main (int argc, char **argv)
try {
const util::mapped_file src (argv[ARG_INPUT]);
std::cout << *json::tree::parse (src.as_view<const char> ()) << '\n';
std::cout << *json::tree::parse (util::view{src}.cast<const char> ()) << '\n';
} catch (const json::error& err) {
std::cerr << err.what () << "\n";
return EXIT_FAILURE;

View File

@ -50,8 +50,8 @@ main (int argc, char **argv) {
const util::mapped_file schema_src (argv[ARG_SCHEMA]);
const util::mapped_file input_src (argv[ARG_INPUT]);
auto schema = json::tree::parse (schema_src.as_view<const char> ());
auto input = json::tree::parse (input_src.as_view<const char> ());
auto schema = json::tree::parse (util::view{schema_src}.cast<const char>());
auto input = json::tree::parse (util::view{input_src} .cast<const char>());
json::schema::validate (*input, schema->as_object ());
} catch (const json::error &e) {

View File

@ -42,7 +42,7 @@ main (int argc, char ** argv) {
try {
const util::mapped_file data (argv[ARG_PATH]);
json::flat::parse (data.as_view<const char> ());
json::flat::parse (util::view{data}.cast<const char> ());
} catch (const json::error &x) {
std::cerr << "error: " << x.what () << '\n';
return EXIT_FAILURE;

View File

@ -270,6 +270,29 @@ template <std::size_t N, typename FuncT>
using nth_argument_t = typename nth_argument<N, FuncT>::type;
///////////////////////////////////////////////////////////////////////////////
template <typename T, typename = std::void_t<>>
struct is_container : public std::false_type {};
template <typename T>
struct is_container<
T,
std::void_t<
typename T::value_type,
typename T::reference,
typename T::const_reference,
typename T::iterator,
typename T::const_iterator,
typename T::difference_type,
typename T::size_type
>
> : public std::true_type {};
template <typename T>
constexpr auto is_container_v = is_container<T>::value;
///////////////////////////////////////////////////////////////////////////////
#include <string>
#include <array>

Some files were not shown because too many files have changed in this diff Show More