123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /**
- This code is licensed under the MCGSI Public License
- Copyright 2018 Jeff Becker
- Kovri go write your own code
- */
- #ifndef SIPHASH_H
- #define SIPHASH_H
- #include <cstdint>
- #include "Crypto.h"
- #if !OPENSSL_SIPHASH
- namespace i2p
- {
- namespace crypto
- {
- namespace siphash
- {
- constexpr int crounds = 2;
- constexpr int drounds = 4;
- inline uint64_t rotl(const uint64_t & x, int b)
- {
- uint64_t ret = x << b;
- ret |= x >> (64 - b);
- return ret;
- }
- inline void u32to8le(const uint32_t & v, uint8_t * p)
- {
- p[0] = (uint8_t) v;
- p[1] = (uint8_t) (v >> 8);
- p[2] = (uint8_t) (v >> 16);
- p[3] = (uint8_t) (v >> 24);
- }
- inline void u64to8le(const uint64_t & v, uint8_t * p)
- {
- p[0] = v & 0xff;
- p[1] = (v >> 8) & 0xff;
- p[2] = (v >> 16) & 0xff;
- p[3] = (v >> 24) & 0xff;
- p[4] = (v >> 32) & 0xff;
- p[5] = (v >> 40) & 0xff;
- p[6] = (v >> 48) & 0xff;
- p[7] = (v >> 56) & 0xff;
- }
- inline uint64_t u8to64le(const uint8_t * p)
- {
- uint64_t i = 0;
- int idx = 0;
- while(idx < 8)
- {
- i |= ((uint64_t) p[idx]) << (idx * 8);
- ++idx;
- }
- return i;
- }
-
- inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3)
- {
- _v0 += _v1;
- _v1 = rotl(_v1, 13);
- _v1 ^= _v0;
- _v0 = rotl(_v0, 32);
- _v2 += _v3;
- _v3 = rotl(_v3, 16);
- _v3 ^= _v2;
- _v0 += _v3;
- _v3 = rotl(_v3, 21);
- _v3 ^= _v0;
- _v2 += _v1;
- _v1 = rotl(_v1, 17);
- _v1 ^= _v2;
- _v2 = rotl(_v2, 32);
- }
- }
-
- /** hashsz must be 8 or 16 */
- template<std::size_t hashsz>
- inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key)
- {
- uint64_t v0 = 0x736f6d6570736575ULL;
- uint64_t v1 = 0x646f72616e646f6dULL;
- uint64_t v2 = 0x6c7967656e657261ULL;
- uint64_t v3 = 0x7465646279746573ULL;
- const uint64_t k0 = siphash::u8to64le(key);
- const uint64_t k1 = siphash::u8to64le(key + 8);
- uint64_t msg;
- int i;
- const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t));
- auto left = bufsz & 7;
- uint64_t b = ((uint64_t)bufsz) << 56;
- v3 ^= k1;
- v2 ^= k0;
- v1 ^= k1;
- v0 ^= k0;
- if(hashsz == 16) v1 ^= 0xee;
- while(buf != end)
- {
- msg = siphash::u8to64le(buf);
- v3 ^= msg;
- for(i = 0; i < siphash::crounds; ++i)
- siphash::round(v0, v1, v2, v3);
-
- v0 ^= msg;
- buf += 8;
- }
- while(left)
- {
- --left;
- b |= ((uint64_t)(buf[left])) << (left * 8);
- }
- v3 ^= b;
- for(i = 0; i < siphash::crounds; ++i)
- siphash::round(v0, v1, v2, v3);
- v0 ^= b;
- if(hashsz == 16)
- v2 ^= 0xee;
- else
- v2 ^= 0xff;
- for(i = 0; i < siphash::drounds; ++i)
- siphash::round(v0, v1, v2, v3);
- b = v0 ^ v1 ^ v2 ^ v3;
- siphash::u64to8le(b, h);
- if(hashsz == 8) return;
- v1 ^= 0xdd;
- for (i = 0; i < siphash::drounds; ++i)
- siphash::round(v0, v1, v2, v3);
- b = v0 ^ v1 ^ v2 ^ v3;
- siphash::u64to8le(b, h + 8);
- }
- }
- }
- #endif
- #endif
|