siphash.h
Go to the documentation of this file.
// siphash.h - written and placed in public domain by Jeffrey Walton.
/// \file siphash.h
/// \brief Classes for SipHash message authentication code
/// \details SipHash computes a 64-bit or 128-bit message authentication code from a variable-length
/// message and 128-bit secret key. It was designed to be efficient even for short inputs, with
/// performance comparable to non-cryptographic hash functions.
/// \details To create a SipHash-2-4 object with a 64-bit MAC use code similar to the following.
/// <pre> SecByteBlock key(16);
/// prng.GenerateBlock(key, key.size());
///
/// SipHash<2,4,false> hash(key, key.size());
/// hash.Update(...);
/// hash.Final(...);</pre>
/// \details To create a SipHash-2-4 object with a 128-bit MAC use code similar to the following.
/// <pre> SecByteBlock key(16);
/// prng.GenerateBlock(key, key.size());
///
/// SipHash<2,4,true> hash(key, key.size());
/// hash.Update(...);
/// hash.Final(...);</pre>
/// \sa Jean-Philippe Aumasson and Daniel J. Bernstein <A HREF="http://131002.net/siphash/siphash.pdf">SipHash:
/// a fast short-input PRF</A>
/// \since Crypto++ 6.0
#ifndef CRYPTOPP_SIPHASH_H
#define CRYPTOPP_SIPHASH_H
#include "cryptlib.h"
#include "secblock.h"
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
/// \brief SipHash message authentication code information
/// \tparam T_128bit flag indicating 128-bit (true) versus 64-bit (false) digest size
template <bool T_128bit>
class SipHash_Info : public FixedKeyLength<16>
{
public:
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SipHash";}
CRYPTOPP_CONSTANT(DIGESTSIZE = (T_128bit ? 16 : 8));
};
/// \brief SipHash message authentication code base class
/// \tparam C the number of compression rounds
/// \tparam D the number of finalization rounds
/// \tparam T_128bit flag indicating 128-bit (true) versus 64-bit (false) digest size
template <unsigned int C, unsigned int D, bool T_128bit>
class SipHash_Base : public MessageAuthenticationCode, public SipHash_Info<T_128bit>
{
public:
static std::string StaticAlgorithmName() {
return std::string(SipHash_Info<T_128bit>::StaticAlgorithmName())+"-"+IntToString(C)+"-"+IntToString(D);
}
virtual ~SipHash_Base() {}
SipHash_Base() : m_idx(0) {}
virtual unsigned int DigestSize() const
{return SipHash_Info<T_128bit>::DIGESTSIZE;}
virtual size_t MinKeyLength() const
{return SipHash_Info<T_128bit>::MIN_KEYLENGTH;}
virtual size_t MaxKeyLength() const
{return SipHash_Info<T_128bit>::MAX_KEYLENGTH;}
virtual size_t DefaultKeyLength() const
{return SipHash_Info<T_128bit>::DEFAULT_KEYLENGTH;}
virtual size_t GetValidKeyLength(size_t keylength) const
{CRYPTOPP_UNUSED(keylength); return SipHash_Info<T_128bit>::DEFAULT_KEYLENGTH;}
virtual IV_Requirement IVRequirement() const
{return SimpleKeyingInterface::NOT_RESYNCHRONIZABLE;}
virtual unsigned int IVSize() const
{return 0;}
virtual unsigned int OptimalBlockSize() const
{return sizeof(word64);}
virtual unsigned int OptimalDataAlignment () const
{return GetAlignmentOf<word64>();}
virtual void Update(const byte *input, size_t length);
virtual void TruncatedFinal(byte *digest, size_t digestSize);
protected:
virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
virtual void Restart();
inline void SIPROUND()
{
m_v[0] += m_v[1];
m_v[1] = rotlConstant<13>(m_v[1]);
m_v[1] ^= m_v[0];
m_v[0] = rotlConstant<32>(m_v[0]);
m_v[2] += m_v[3];
m_v[3] = rotlConstant<16>(m_v[3]);
m_v[3] ^= m_v[2];
m_v[0] += m_v[3];
m_v[3] = rotlConstant<21>(m_v[3]);
m_v[3] ^= m_v[0];
m_v[2] += m_v[1];
m_v[1] = rotlConstant<17>(m_v[1]);
m_v[1] ^= m_v[2];
m_v[2] = rotlConstant<32>(m_v[2]);
}
private:
FixedSizeSecBlock<word64, 4> m_v;
FixedSizeSecBlock<word64, 2> m_k;
FixedSizeSecBlock<word64, 2> m_b;
// Tail bytes
FixedSizeSecBlock<byte, 8> m_acc;
size_t m_idx;
};
/// \brief SipHash message authentication code
/// \tparam C the number of compression rounds
/// \tparam D the number of finalization rounds
/// \tparam T_128bit flag indicating 128-bit (true) versus 64-bit (false) digest size
/// \details SipHash computes a 64-bit or 128-bit message authentication code from a variable-length
/// message and 128-bit secret key. It was designed to be efficient even for short inputs, with
/// performance comparable to non-cryptographic hash functions.
/// \details To create a SipHash-2-4 object with a 64-bit MAC use code similar to the following.
/// <pre> SecByteBlock key(16);
/// prng.GenerateBlock(key, key.size());
///
/// SipHash<2,4,false> hash(key, key.size());
/// hash.Update(...);
/// hash.Final(...);</pre>
/// \details To create a SipHash-2-4 object with a 128-bit MAC use code similar to the following.
/// <pre> SecByteBlock key(16);
/// prng.GenerateBlock(key, key.size());
///
/// SipHash<2,4,true> hash(key, key.size());
/// hash.Update(...);
/// hash.Final(...);</pre>
/// \sa Jean-Philippe Aumasson and Daniel J. Bernstein <A HREF="http://131002.net/siphash/siphash.pdf">SipHash:
/// a fast short-input PRF</A>
/// \since Crypto++ 6.0
template <unsigned int C=2, unsigned int D=4, bool T_128bit=false>
class SipHash : public SipHash_Base<C, D, T_128bit>
{
public:
/// \brief Create a SipHash
SipHash()
{this->UncheckedSetKey(NULLPTR, 0, g_nullNameValuePairs);}
/// \brief Create a SipHash
/// \param key a byte array used to key the cipher
/// \param length the size of the byte array, in bytes
SipHash(const byte *key, unsigned int length)
{this->ThrowIfInvalidKeyLength(length);
this->UncheckedSetKey(key, length, g_nullNameValuePairs);}
};
template <unsigned int C, unsigned int D, bool T_128bit>
void SipHash_Base<C,D,T_128bit>::Update(const byte *input, size_t length)
{
CRYPTOPP_ASSERT((input && length) || !length);
if (!length) return;
if (m_idx)
{
size_t head = STDMIN(size_t(8U-m_idx), length);
memcpy(m_acc+m_idx, input, head);
m_idx += head; input += head; length -= head;
if (m_idx == 8)
{
word64 m = GetWord<word64>(true, LITTLE_ENDIAN_ORDER, m_acc);
m_v[3] ^= m;
for (unsigned int i = 0; i < C; ++i)
SIPROUND();
m_v[0] ^= m;
m_b[0] += 8;
m_idx = 0;
}
}
while (length >= 8)
{
word64 m = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, input);
m_v[3] ^= m;
for (unsigned int i = 0; i < C; ++i)
SIPROUND();
m_v[0] ^= m;
m_b[0] += 8;
input += 8;
length -= 8;
}
CRYPTOPP_ASSERT(length < 8);
size_t tail = length % 8;
if (tail)
{
memcpy(m_acc+m_idx, input, tail);
m_idx += tail;
}
}
template <unsigned int C, unsigned int D, bool T_128bit>
void SipHash_Base<C,D,T_128bit>::TruncatedFinal(byte *digest, size_t digestSize)
{
CRYPTOPP_ASSERT(digest); // Pointer is valid
ThrowIfInvalidTruncatedSize(digestSize);
// The high octet holds length and is digested mod 256
m_b[0] += m_idx; m_b[0] <<= 56U;
switch (m_idx)
{
case 7:
m_b[0] |= ((word64)m_acc[6]) << 48;
// fall through
case 6:
m_b[0] |= ((word64)m_acc[5]) << 40;
// fall through
case 5:
m_b[0] |= ((word64)m_acc[4]) << 32;
// fall through
case 4:
m_b[0] |= ((word64)m_acc[3]) << 24;
// fall through
case 3:
m_b[0] |= ((word64)m_acc[2]) << 16;
// fall through
case 2:
m_b[0] |= ((word64)m_acc[1]) << 8;
// fall through
case 1:
m_b[0] |= ((word64)m_acc[0]);
// fall through
case 0:
break;
}
m_v[3] ^= m_b[0];
for (unsigned int i=0; i<C; i++)
SIPROUND();
m_v[0] ^= m_b[0];
if (T_128bit)
m_v[2] ^= 0xee;
else
m_v[2] ^= 0xff;
for (unsigned int i=0; i<D; i++)
SIPROUND();
m_b[0] = m_v[0] ^ m_v[1] ^ m_v[2] ^ m_v[3];
m_b[0] = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, m_b[0]);
if (T_128bit)
{
m_v[1] ^= 0xdd;
for (unsigned int i = 0; i<D; ++i)
SIPROUND();
m_b[1] = m_v[0] ^ m_v[1] ^ m_v[2] ^ m_v[3];
m_b[1] = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, m_b[1]);
}
memcpy_s(digest, digestSize, m_b.begin(), STDMIN(digestSize, (size_t)SipHash_Info<T_128bit>::DIGESTSIZE));
Restart();
}
template <unsigned int C, unsigned int D, bool T_128bit>
void SipHash_Base<C,D,T_128bit>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
{
CRYPTOPP_UNUSED(params);
if (key && length)
{
m_k[0] = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, key);
m_k[1] = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, key+8);
}
else
{
// Avoid Coverity finding
m_k[0] = m_k[1] = 0;
}
Restart();
}
template <unsigned int C, unsigned int D, bool T_128bit>
void SipHash_Base<C,D,T_128bit>::Restart ()
{
m_v[0] = W64LIT(0x736f6d6570736575);
m_v[1] = W64LIT(0x646f72616e646f6d);
m_v[2] = W64LIT(0x6c7967656e657261);
m_v[3] = W64LIT(0x7465646279746573);
m_v[3] ^= m_k[1];
m_v[2] ^= m_k[0];
m_v[1] ^= m_k[1];
m_v[0] ^= m_k[0];
if (T_128bit)
{
m_v[1] ^= 0xee;
}
m_idx = 0;
m_b[0] = 0;
}
NAMESPACE_END
#endif // CRYPTOPP_SIPHASH_H
FixedKeyLength
Inherited by keyed algorithms with fixed key length.
Definition: seckey.h:125
FixedSizeSecBlock< word64, 4 >
MessageAuthenticationCode
Interface for message authentication codes.
Definition: cryptlib.h:1299
NameValuePairs
Interface for retrieving values given their names.
Definition: cryptlib.h:322
SimpleKeyingInterface::IV_Requirement
IV_Requirement
Secure IVs requirements as enumerated values.
Definition: cryptlib.h:719
SimpleKeyingInterface::NOT_RESYNCHRONIZABLE
@ NOT_RESYNCHRONIZABLE
The object does not use an IV.
Definition: cryptlib.h:729
SipHash_Base
SipHash message authentication code base class.
Definition: siphash.h:51
SipHash_Base::IVRequirement
virtual IV_Requirement IVRequirement() const
Minimal requirement for secure IVs.
Definition: siphash.h:71
SipHash_Base::TruncatedFinal
virtual void TruncatedFinal(byte *digest, size_t digestSize)
Computes the hash of the current message.
Definition: siphash.h:205
SipHash_Base::IVSize
virtual unsigned int IVSize() const
Returns length of the IV accepted by this object.
Definition: siphash.h:73
SipHash_Base::MinKeyLength
virtual size_t MinKeyLength() const
Returns smallest valid key length.
Definition: siphash.h:63
SipHash_Base::OptimalBlockSize
virtual unsigned int OptimalBlockSize() const
Provides the input block size most efficient for this hash.
Definition: siphash.h:75
SipHash_Base::Update
virtual void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: siphash.h:156
SipHash_Base::DigestSize
virtual unsigned int DigestSize() const
Provides the digest size of the hash.
Definition: siphash.h:61
SipHash_Base::DefaultKeyLength
virtual size_t DefaultKeyLength() const
Returns default key length.
Definition: siphash.h:67
SipHash_Base::MaxKeyLength
virtual size_t MaxKeyLength() const
Returns largest valid key length.
Definition: siphash.h:65
SipHash_Base::GetValidKeyLength
virtual size_t GetValidKeyLength(size_t keylength) const
Returns a valid key length for the algorithm.
Definition: siphash.h:69
SipHash_Base::OptimalDataAlignment
virtual unsigned int OptimalDataAlignment() const
Provides input and output data alignment for optimal performance.
Definition: siphash.h:77
SipHash_Info
SipHash message authentication code information.
Definition: siphash.h:39
SipHash
SipHash message authentication code.
Definition: siphash.h:142
SipHash::SipHash
SipHash(const byte *key, unsigned int length)
Create a SipHash.
Definition: siphash.h:150
SipHash::SipHash
SipHash()
Create a SipHash.
Definition: siphash.h:145
W64LIT
#define W64LIT(x)
Declare an unsigned word64.
Definition: config_int.h:119
word64
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:91
cryptlib.h
Abstract base classes that provide a uniform interface to this library.
g_nullNameValuePairs
const NameValuePairs & g_nullNameValuePairs
An empty set of name-value pairs.
Definition: cryptlib.h:529
LITTLE_ENDIAN_ORDER
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:145
misc.h
Utility functions for the Crypto++ library.
memcpy_s
void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memcpy()
Definition: misc.h:525
IntToString
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:724
ConditionalByteReverse
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
Definition: misc.h:2187
STDMIN
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:655
CryptoPP
Crypto++ library namespace.
secblock.h
Classes and functions for secure memory allocations.
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68