Using the 128-bit hash function, instead of 64-Bit one.
This commit is contained in:
parent
0e75e05fda
commit
fde0906f98
@ -12,6 +12,12 @@
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Intrinsic */
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic(_umul128)
|
||||
#endif
|
||||
|
||||
/* Compiler compatibility */
|
||||
#if defined(_MSC_VER)
|
||||
# define FORCE_INLINE __forceinline
|
||||
@ -30,10 +36,6 @@ const uint16_t SLUNKCRYPT_VERSION_MINOR = MY_VERSION_MINOR;
|
||||
const uint16_t SLUNKCRYPT_VERSION_PATCH = MY_VERSION_PATCH;
|
||||
const char *const SLUNKCRYPT_BUILD = __DATE__ " " __TIME__;
|
||||
|
||||
/* Const */
|
||||
#define HASH_MAGIC_PRIME 0x00000100000001B3ull
|
||||
#define HASH_OFFSET_BASE 0xCBF29CE484222325ull
|
||||
|
||||
/* Utilities */
|
||||
#define BOOLIFY(X) (!!(X))
|
||||
|
||||
@ -43,9 +45,9 @@ const char *const SLUNKCRYPT_BUILD = __DATE__ " " __TIME__;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t a, b, c;
|
||||
uint64_t hi, lo;
|
||||
}
|
||||
key_data_t;
|
||||
uint128_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -88,13 +90,7 @@ static FORCE_INLINE uint32_t lower_u64(const uint64_t value)
|
||||
|
||||
static FORCE_INLINE uint32_t upper_u64(const uint64_t value)
|
||||
{
|
||||
return (uint32_t)((value >> 32U) & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static FORCE_INLINE uint8_t byte_u16(const uint16_t value, const size_t off)
|
||||
{
|
||||
assert(off < sizeof(uint16_t));
|
||||
return (uint8_t)((value >> (CHAR_BIT * off)) & 0xFF);
|
||||
return (uint32_t)(value >> 32U);
|
||||
}
|
||||
|
||||
static FORCE_INLINE uint8_t byte_u64(const uint64_t value, const size_t off)
|
||||
@ -103,89 +99,104 @@ static FORCE_INLINE uint8_t byte_u64(const uint64_t value, const size_t off)
|
||||
return (uint8_t)((value >> (CHAR_BIT * off)) & 0xFF);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// 128-Bit math support
|
||||
// ==========================================================================
|
||||
|
||||
static FORCE_INLINE void mult_u128(uint128_t *const out, const uint128_t lhs, const uint128_t rhs)
|
||||
{
|
||||
#if defined(__GNUC__) && defined(__SIZEOF_INT128__)
|
||||
const __uint128_t lhs_128 = ((__uint128_t)lhs.hi << 64U) | lhs.lo;
|
||||
const __uint128_t rhs_128 = ((__uint128_t)rhs.hi << 64U) | rhs.lo;
|
||||
const __uint128_t out_128 = lhs_128 * rhs_128;
|
||||
out->hi = (uint64_t)(out_128 >> 64U);
|
||||
out->lo = (uint64_t)(out_128 & 0xFFFFFFFFFFFFFFFF);
|
||||
#else
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
out->lo = _umul128(lhs.lo, rhs.lo, &out->hi);
|
||||
#else
|
||||
const uint64_t lolo = (lhs.lo & 0xFFFFFFFF) * (rhs.lo & 0xFFFFFFFF);
|
||||
const uint64_t hilo = (lhs.lo >> 32U) * (rhs.lo & 0xFFFFFFFF);
|
||||
const uint64_t lohi = (lhs.lo & 0xFFFFFFFF) * (rhs.lo >> 32U);
|
||||
const uint64_t hihi = (lhs.lo >> 32U) * (rhs.lo >> 32U);
|
||||
const uint64_t crss = (lolo >> 32U) + (hilo & 0xFFFFFFFF) + lohi;
|
||||
out->hi = (hilo >> 32U) + (crss >> 32) + hihi;
|
||||
out->lo = (crss << 32U) | (lolo & 0xFFFFFFFF);
|
||||
#endif
|
||||
out->hi += (lhs.hi * rhs.lo) + (lhs.lo * rhs.hi); /* 128x128=128 */
|
||||
#endif
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Hash function
|
||||
// ==========================================================================
|
||||
|
||||
static FORCE_INLINE void hash_update_str(uint64_t* const hash, const uint8_t *const data, const size_t data_len)
|
||||
static const uint128_t HASH_OFFSET_BASE = { 0x6C62272E07BB0142, 0x62B821756295C58D };
|
||||
static const uint128_t HASH_MAGIC_PRIME = { 0x0000000001000000, 0x000000000000013B };
|
||||
|
||||
static FORCE_INLINE void hash_update_str(uint128_t *const hash, const uint8_t *const data, const size_t data_len)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0U; i < data_len; ++i)
|
||||
{
|
||||
*hash = ((*hash) ^ data[i]) * HASH_MAGIC_PRIME;
|
||||
hash->lo ^= data[i];
|
||||
mult_u128(hash, *hash, HASH_MAGIC_PRIME);
|
||||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void hash_update_u64(uint64_t *const hash, const uint64_t value)
|
||||
static FORCE_INLINE void hash_update_u64(uint128_t *const hash, const uint64_t value)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0U; i < sizeof(uint64_t); ++i)
|
||||
{
|
||||
*hash = ((*hash) ^ byte_u64(value, i)) * HASH_MAGIC_PRIME;
|
||||
hash->lo ^= byte_u64(value, i);
|
||||
mult_u128(hash, *hash, HASH_MAGIC_PRIME);
|
||||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void hash_update_u16(uint64_t *const hash, const uint16_t value)
|
||||
static uint64_t hash_code(const uint64_t salt, const uint8_t *const data, const size_t data_len)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0U; i < sizeof(uint16_t); ++i)
|
||||
{
|
||||
*hash = ((*hash) ^ byte_u16(value, i)) * HASH_MAGIC_PRIME;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t hash_code_init(const uint64_t salt, const uint16_t i, const uint8_t *const data, const size_t data_len)
|
||||
{
|
||||
uint64_t hash = HASH_OFFSET_BASE;
|
||||
hash_update_u64(&hash, salt);
|
||||
hash_update_u16(&hash, i);
|
||||
hash_update_str(&hash, data, data_len);
|
||||
return hash;
|
||||
}
|
||||
|
||||
static uint64_t hash_code_next(const uint64_t salt, const uint8_t *const data, const size_t data_len)
|
||||
{
|
||||
uint64_t hash = HASH_OFFSET_BASE;
|
||||
uint128_t hash = HASH_OFFSET_BASE;
|
||||
hash_update_u64(&hash, salt);
|
||||
hash_update_str(&hash, data, data_len);
|
||||
return hash;
|
||||
return hash.hi ^ hash.lo;
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Key derivation
|
||||
// ==========================================================================
|
||||
|
||||
static FORCE_INLINE uint64_t keygen_loop(uint64_t salt, const uint16_t i, const uint8_t *const passwd, const size_t passwd_len)
|
||||
static FORCE_INLINE uint64_t keygen_loop(uint64_t salt, const uint8_t *const passwd, const size_t passwd_len)
|
||||
{
|
||||
uint64_t result = 0U;
|
||||
size_t u;
|
||||
uint64_t result = salt = hash_code_init(salt, i, passwd, passwd_len);
|
||||
for (u = 1U; u < 99971U; ++u)
|
||||
for (u = 0U; u < 99971U; ++u)
|
||||
{
|
||||
result ^= salt = hash_code_next(salt, passwd, passwd_len);
|
||||
result ^= salt = hash_code(salt, passwd, passwd_len);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void generate_key(key_data_t *const key, const uint64_t salt, const uint16_t pepper, const uint8_t *const passwd, const size_t passwd_len)
|
||||
static void generate_key(uint64_t *const key, const uint64_t salt, const uint16_t pepper, const uint8_t *const passwd, const size_t passwd_len)
|
||||
{
|
||||
key->a = keygen_loop(salt, (pepper & 0x3FFF) | 0x0000, passwd, passwd_len);
|
||||
key->b = keygen_loop(salt, (pepper & 0x3FFF) | 0x4000, passwd, passwd_len);
|
||||
key->c = keygen_loop(salt, (pepper & 0x3FFF) | 0x8000, passwd, passwd_len);
|
||||
key[0U] = keygen_loop(0x243F6A8885A308D3 + salt + pepper, passwd, passwd_len);
|
||||
key[1U] = keygen_loop(0x13198A2E03707344 + salt + pepper, passwd, passwd_len);
|
||||
key[2U] = keygen_loop(0xA4093822299F31D0 + salt + pepper, passwd, passwd_len);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Deterministic random bit generator
|
||||
// ==========================================================================
|
||||
|
||||
static void random_init(rand_state_t *const state, const key_data_t *const key)
|
||||
static void random_init(rand_state_t *const state, const uint64_t *const key)
|
||||
{
|
||||
slunkcrypt_bzero(state, sizeof(rand_state_t));
|
||||
state->x = lower_u64(key->a);
|
||||
state->y = upper_u64(key->a);
|
||||
state->z = lower_u64(key->b);
|
||||
state->w = upper_u64(key->b);
|
||||
state->v = lower_u64(key->c);
|
||||
state->d = upper_u64(key->c);
|
||||
state->x = lower_u64(key[0U]);
|
||||
state->y = upper_u64(key[0U]);
|
||||
state->z = lower_u64(key[1U]);
|
||||
state->w = upper_u64(key[1U]);
|
||||
state->v = lower_u64(key[2U]);
|
||||
state->d = upper_u64(key[2U]);
|
||||
}
|
||||
|
||||
static uint32_t random_next(rand_state_t *const state)
|
||||
@ -202,12 +213,12 @@ static uint32_t random_next(rand_state_t *const state)
|
||||
static void random_seed(rand_state_t *const state, uint64_t salt, const uint16_t pepper, const uint8_t *const passwd, const size_t passwd_len)
|
||||
{
|
||||
size_t i;
|
||||
key_data_t key;
|
||||
uint64_t key[3U];
|
||||
do
|
||||
{
|
||||
generate_key(&key, salt++, pepper, passwd, passwd_len);
|
||||
random_init(state, &key);
|
||||
slunkcrypt_bzero(&key, sizeof(key_data_t));
|
||||
generate_key(key, salt++, pepper, passwd, passwd_len);
|
||||
random_init(state, key);
|
||||
slunkcrypt_bzero(&key, 3U * sizeof(uint64_t));
|
||||
}
|
||||
while (!(state->x || state->y || state->z || state->w || state->v));
|
||||
for (i = 0U; i < 97U; ++i)
|
||||
|
Loading…
Reference in New Issue
Block a user