File indexing completed on 2025-01-18 09:55:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #ifndef CRYPTOPP_SIPHASH_H
0027 #define CRYPTOPP_SIPHASH_H
0028
0029 #include "cryptlib.h"
0030 #include "secblock.h"
0031 #include "seckey.h"
0032 #include "misc.h"
0033
0034 NAMESPACE_BEGIN(CryptoPP)
0035
0036
0037
0038 template <bool T_128bit>
0039 class SipHash_Info : public FixedKeyLength<16>
0040 {
0041 public:
0042 CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "SipHash";}
0043 CRYPTOPP_CONSTANT(DIGESTSIZE = (T_128bit ? 16 : 8));
0044 };
0045
0046
0047
0048
0049
0050 template <unsigned int C, unsigned int D, bool T_128bit>
0051 class SipHash_Base : public MessageAuthenticationCode, public SipHash_Info<T_128bit>
0052 {
0053 public:
0054 static std::string StaticAlgorithmName() {
0055 return std::string(SipHash_Info<T_128bit>::StaticAlgorithmName())+"-"+IntToString(C)+"-"+IntToString(D);
0056 }
0057
0058 virtual ~SipHash_Base() {}
0059
0060 SipHash_Base() : m_idx(0) {}
0061
0062 virtual unsigned int DigestSize() const
0063 {return SipHash_Info<T_128bit>::DIGESTSIZE;}
0064 virtual size_t MinKeyLength() const
0065 {return SipHash_Info<T_128bit>::MIN_KEYLENGTH;}
0066 virtual size_t MaxKeyLength() const
0067 {return SipHash_Info<T_128bit>::MAX_KEYLENGTH;}
0068 virtual size_t DefaultKeyLength() const
0069 {return SipHash_Info<T_128bit>::DEFAULT_KEYLENGTH;}
0070 virtual size_t GetValidKeyLength(size_t keylength) const
0071 {CRYPTOPP_UNUSED(keylength); return SipHash_Info<T_128bit>::DEFAULT_KEYLENGTH;}
0072 virtual IV_Requirement IVRequirement() const
0073 {return SimpleKeyingInterface::NOT_RESYNCHRONIZABLE;}
0074 virtual unsigned int IVSize() const
0075 {return 0;}
0076 virtual unsigned int OptimalBlockSize() const
0077 {return sizeof(word64);}
0078 virtual unsigned int OptimalDataAlignment () const
0079 {return GetAlignmentOf<word64>();}
0080
0081 virtual void Update(const byte *input, size_t length);
0082 virtual void TruncatedFinal(byte *digest, size_t digestSize);
0083
0084 protected:
0085
0086 virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
0087 virtual void Restart();
0088
0089 inline void SIPROUND()
0090 {
0091 m_v[0] += m_v[1];
0092 m_v[1] = rotlConstant<13>(m_v[1]);
0093 m_v[1] ^= m_v[0];
0094 m_v[0] = rotlConstant<32>(m_v[0]);
0095 m_v[2] += m_v[3];
0096 m_v[3] = rotlConstant<16>(m_v[3]);
0097 m_v[3] ^= m_v[2];
0098 m_v[0] += m_v[3];
0099 m_v[3] = rotlConstant<21>(m_v[3]);
0100 m_v[3] ^= m_v[0];
0101 m_v[2] += m_v[1];
0102 m_v[1] = rotlConstant<17>(m_v[1]);
0103 m_v[1] ^= m_v[2];
0104 m_v[2] = rotlConstant<32>(m_v[2]);
0105 }
0106
0107 private:
0108 FixedSizeSecBlock<word64, 4> m_v;
0109 FixedSizeSecBlock<word64, 2> m_k;
0110 FixedSizeSecBlock<word64, 2> m_b;
0111
0112
0113 FixedSizeSecBlock<byte, 8> m_acc;
0114 size_t m_idx;
0115 };
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 template <unsigned int C=2, unsigned int D=4, bool T_128bit=false>
0142 class SipHash : public SipHash_Base<C, D, T_128bit>
0143 {
0144 public:
0145
0146 SipHash()
0147 {this->UncheckedSetKey(NULLPTR, 0, g_nullNameValuePairs);}
0148
0149
0150
0151 SipHash(const byte *key, unsigned int length)
0152 {this->ThrowIfInvalidKeyLength(length);
0153 this->UncheckedSetKey(key, length, g_nullNameValuePairs);}
0154 };
0155
0156 template <unsigned int C, unsigned int D, bool T_128bit>
0157 void SipHash_Base<C,D,T_128bit>::Update(const byte *input, size_t length)
0158 {
0159 CRYPTOPP_ASSERT((input && length) || !length);
0160 if (!length) return;
0161
0162 if (m_idx)
0163 {
0164 size_t head = STDMIN(size_t(8U-m_idx), length);
0165 std::memcpy(m_acc+m_idx, input, head);
0166 m_idx += head; input += head; length -= head;
0167
0168 if (m_idx == 8)
0169 {
0170 word64 m = GetWord<word64>(true, LITTLE_ENDIAN_ORDER, m_acc);
0171 m_v[3] ^= m;
0172 for (unsigned int i = 0; i < C; ++i)
0173 SIPROUND();
0174
0175 m_v[0] ^= m;
0176 m_b[0] += 8;
0177
0178 m_idx = 0;
0179 }
0180 }
0181
0182 while (length >= 8)
0183 {
0184 word64 m = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, input);
0185 m_v[3] ^= m;
0186 for (unsigned int i = 0; i < C; ++i)
0187 SIPROUND();
0188
0189 m_v[0] ^= m;
0190 m_b[0] += 8;
0191
0192 input += 8;
0193 length -= 8;
0194 }
0195
0196 CRYPTOPP_ASSERT(length < 8);
0197 size_t tail = length % 8;
0198 if (tail)
0199 {
0200 std::memcpy(m_acc+m_idx, input, tail);
0201 m_idx += tail;
0202 }
0203 }
0204
0205 template <unsigned int C, unsigned int D, bool T_128bit>
0206 void SipHash_Base<C,D,T_128bit>::TruncatedFinal(byte *digest, size_t digestSize)
0207 {
0208 CRYPTOPP_ASSERT(digest);
0209
0210 ThrowIfInvalidTruncatedSize(digestSize);
0211
0212
0213 m_b[0] += m_idx; m_b[0] <<= 56U;
0214 switch (m_idx)
0215 {
0216 case 7:
0217 m_b[0] |= ((word64)m_acc[6]) << 48;
0218
0219 case 6:
0220 m_b[0] |= ((word64)m_acc[5]) << 40;
0221
0222 case 5:
0223 m_b[0] |= ((word64)m_acc[4]) << 32;
0224
0225 case 4:
0226 m_b[0] |= ((word64)m_acc[3]) << 24;
0227
0228 case 3:
0229 m_b[0] |= ((word64)m_acc[2]) << 16;
0230
0231 case 2:
0232 m_b[0] |= ((word64)m_acc[1]) << 8;
0233
0234 case 1:
0235 m_b[0] |= ((word64)m_acc[0]);
0236
0237 case 0:
0238 break;
0239 }
0240
0241 m_v[3] ^= m_b[0];
0242
0243 for (unsigned int i=0; i<C; i++)
0244 SIPROUND();
0245
0246 m_v[0] ^= m_b[0];
0247
0248 if (T_128bit)
0249 m_v[2] ^= 0xee;
0250 else
0251 m_v[2] ^= 0xff;
0252
0253 for (unsigned int i=0; i<D; i++)
0254 SIPROUND();
0255
0256 m_b[0] = m_v[0] ^ m_v[1] ^ m_v[2] ^ m_v[3];
0257 m_b[0] = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, m_b[0]);
0258
0259 if (T_128bit)
0260 {
0261 m_v[1] ^= 0xdd;
0262 for (unsigned int i = 0; i<D; ++i)
0263 SIPROUND();
0264
0265 m_b[1] = m_v[0] ^ m_v[1] ^ m_v[2] ^ m_v[3];
0266 m_b[1] = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, m_b[1]);
0267 }
0268
0269 memcpy_s(digest, digestSize, m_b.begin(), STDMIN(digestSize, (size_t)SipHash_Info<T_128bit>::DIGESTSIZE));
0270 Restart();
0271 }
0272
0273 template <unsigned int C, unsigned int D, bool T_128bit>
0274 void SipHash_Base<C,D,T_128bit>::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
0275 {
0276 CRYPTOPP_UNUSED(params);
0277 if (key && length)
0278 {
0279 m_k[0] = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, key);
0280 m_k[1] = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, key+8);
0281 }
0282 else
0283 {
0284
0285 m_k[0] = m_k[1] = 0;
0286 }
0287 Restart();
0288 }
0289
0290 template <unsigned int C, unsigned int D, bool T_128bit>
0291 void SipHash_Base<C,D,T_128bit>::Restart ()
0292 {
0293 m_v[0] = W64LIT(0x736f6d6570736575);
0294 m_v[1] = W64LIT(0x646f72616e646f6d);
0295 m_v[2] = W64LIT(0x6c7967656e657261);
0296 m_v[3] = W64LIT(0x7465646279746573);
0297
0298 m_v[3] ^= m_k[1];
0299 m_v[2] ^= m_k[0];
0300 m_v[1] ^= m_k[1];
0301 m_v[0] ^= m_k[0];
0302
0303 if (T_128bit)
0304 {
0305 m_v[1] ^= 0xee;
0306 }
0307
0308 m_idx = 0;
0309 m_b[0] = 0;
0310 }
0311
0312 NAMESPACE_END
0313
0314 #endif