Skip to content

Commit a8f1dca

Browse files
committed
random.c: use sip_hash13 as faster but still safe alternative to sip_hash24
SipHash13 is secure enough to be used in hash-tables, and SipHash's author confirms that. Rust already considered switch to SipHash13: rust-lang/rust#29754 (comment) Jean-Philippe Aumasson confirmation: rust-lang/rust#29754 (comment) Merged pull request: rust-lang/rust#33940
1 parent 27af0e7 commit a8f1dca

File tree

3 files changed

+92
-31
lines changed

3 files changed

+92
-31
lines changed

random.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1521,7 +1521,7 @@ init_siphash(sipseed_keys_t key, uint32_t* cnt)
15211521
st_index_t
15221522
rb_memhash(const void *ptr, long len)
15231523
{
1524-
sip_uint64_t h = sip_hash24(sipseed.key, ptr, len);
1524+
sip_uint64_t h = sip_hash13(sipseed.key, ptr, len);
15251525
#ifdef HAVE_UINT64_T
15261526
return (st_index_t)h;
15271527
#else

siphash.c

+90-30
Original file line numberDiff line numberDiff line change
@@ -394,37 +394,10 @@ do { \
394394
XOR64_TO((v0), (m)); \
395395
} while (0)
396396

397-
uint64_t
398-
sip_hash24(const uint8_t key[16], const uint8_t *data, size_t len)
397+
static inline uint64_t
398+
sip_read_last(const uint8_t *end, size_t len)
399399
{
400-
uint64_t k0, k1;
401-
uint64_t v0, v1, v2, v3;
402-
uint64_t m, last;
403-
const uint8_t *end = data + len - (len % sizeof(uint64_t));
404-
405-
k0 = U8TO64_LE(key);
406-
k1 = U8TO64_LE(key + sizeof(uint64_t));
407-
408-
v0 = k0; XOR64_TO(v0, sip_init_state[0]);
409-
v1 = k1; XOR64_TO(v1, sip_init_state[1]);
410-
v2 = k0; XOR64_TO(v2, sip_init_state[2]);
411-
v3 = k1; XOR64_TO(v3, sip_init_state[3]);
412-
413-
#if BYTE_ORDER == LITTLE_ENDIAN && UNALIGNED_WORD_ACCESS
414-
{
415-
uint64_t *data64 = (uint64_t *)data;
416-
while (data64 != (uint64_t *) end) {
417-
m = *data64++;
418-
SIP_2_ROUND(m, v0, v1, v2, v3);
419-
}
420-
}
421-
#else
422-
for (; data != end; data += sizeof(uint64_t)) {
423-
m = U8TO64_LE(data);
424-
SIP_2_ROUND(m, v0, v1, v2, v3);
425-
}
426-
#endif
427-
400+
uint64_t last;
428401
#ifdef HAVE_UINT64_T
429402
last = (uint64_t)len << 56;
430403
#define OR_BYTE(n) (last |= ((uint64_t) end[n]) << ((n) * 8))
@@ -467,7 +440,41 @@ sip_hash24(const uint8_t key[16], const uint8_t *data, size_t len)
467440
case 0:
468441
break;
469442
}
443+
return last;
444+
}
445+
446+
uint64_t
447+
sip_hash24(const uint8_t key[16], const uint8_t *data, size_t len)
448+
{
449+
uint64_t k0, k1;
450+
uint64_t v0, v1, v2, v3;
451+
uint64_t m, last;
452+
const uint8_t *end = data + len - (len % sizeof(uint64_t));
453+
454+
k0 = U8TO64_LE(key);
455+
k1 = U8TO64_LE(key + sizeof(uint64_t));
456+
457+
v0 = k0; XOR64_TO(v0, sip_init_state[0]);
458+
v1 = k1; XOR64_TO(v1, sip_init_state[1]);
459+
v2 = k0; XOR64_TO(v2, sip_init_state[2]);
460+
v3 = k1; XOR64_TO(v3, sip_init_state[3]);
461+
462+
#if BYTE_ORDER == LITTLE_ENDIAN && UNALIGNED_WORD_ACCESS
463+
{
464+
uint64_t *data64 = (uint64_t *)data;
465+
while (data64 != (uint64_t *) end) {
466+
m = *data64++;
467+
SIP_2_ROUND(m, v0, v1, v2, v3);
468+
}
469+
}
470+
#else
471+
for (; data != end; data += sizeof(uint64_t)) {
472+
m = U8TO64_LE(data);
473+
SIP_2_ROUND(m, v0, v1, v2, v3);
474+
}
475+
#endif
470476

477+
last = sip_read_last(end, len);
471478
SIP_2_ROUND(last, v0, v1, v2, v3);
472479

473480
XOR64_INT(v2, 0xff);
@@ -482,3 +489,56 @@ sip_hash24(const uint8_t key[16], const uint8_t *data, size_t len)
482489
XOR64_TO(v0, v3);
483490
return v0;
484491
}
492+
493+
#define SIP_1_ROUND(m, v0, v1, v2, v3) \
494+
do { \
495+
XOR64_TO((v3), (m)); \
496+
SIP_COMPRESS(v0, v1, v2, v3); \
497+
XOR64_TO((v0), (m)); \
498+
} while (0)
499+
500+
uint64_t
501+
sip_hash13(const uint8_t key[16], const uint8_t *data, size_t len)
502+
{
503+
uint64_t k0, k1;
504+
uint64_t v0, v1, v2, v3;
505+
uint64_t m, last;
506+
const uint8_t *end = data + len - (len % sizeof(uint64_t));
507+
508+
k0 = U8TO64_LE(key);
509+
k1 = U8TO64_LE(key + sizeof(uint64_t));
510+
511+
v0 = k0; XOR64_TO(v0, sip_init_state[0]);
512+
v1 = k1; XOR64_TO(v1, sip_init_state[1]);
513+
v2 = k0; XOR64_TO(v2, sip_init_state[2]);
514+
v3 = k1; XOR64_TO(v3, sip_init_state[3]);
515+
516+
#if BYTE_ORDER == LITTLE_ENDIAN && UNALIGNED_WORD_ACCESS
517+
{
518+
uint64_t *data64 = (uint64_t *)data;
519+
while (data64 != (uint64_t *) end) {
520+
m = *data64++;
521+
SIP_1_ROUND(m, v0, v1, v2, v3);
522+
}
523+
}
524+
#else
525+
for (; data != end; data += sizeof(uint64_t)) {
526+
m = U8TO64_LE(data);
527+
SIP_1_ROUND(m, v0, v1, v2, v3);
528+
}
529+
#endif
530+
531+
last = sip_read_last(end, len);
532+
SIP_1_ROUND(last, v0, v1, v2, v3);
533+
534+
XOR64_INT(v2, 0xff);
535+
536+
SIP_COMPRESS(v0, v1, v2, v3);
537+
SIP_COMPRESS(v0, v1, v2, v3);
538+
SIP_COMPRESS(v0, v1, v2, v3);
539+
540+
XOR64_TO(v0, v1);
541+
XOR64_TO(v0, v2);
542+
XOR64_TO(v0, v3);
543+
return v0;
544+
}

siphash.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,6 @@ void sip_hash_free(sip_hash *h);
4444
void sip_hash_dump(sip_hash *h);
4545

4646
uint64_t sip_hash24(const uint8_t key[16], const uint8_t *data, size_t len);
47+
uint64_t sip_hash13(const uint8_t key[16], const uint8_t *data, size_t len);
4748

4849
#endif

0 commit comments

Comments
 (0)