]> git.kaiwu.me - nginx.git/commitdiff
Core: added SipHash-2-4 implementation
authorEugene Grebenschikov <e.grebenshchikov@f5.com>
Thu, 21 May 2026 17:37:23 +0000 (10:37 -0700)
committerEugene <54681898+jimf5@users.noreply.github.com>
Tue, 2 Jun 2026 22:30:30 +0000 (15:30 -0700)
Added ngx_siphash() function implementing the SipHash-2-4
algorithm for fast pseudorandom number generation with good
statistical properties.

Co-authored-by: Sergey Kandaurov <pluknet@nginx.com>
auto/sources
src/core/ngx_core.h
src/core/ngx_siphash.c [new file with mode: 0644]
src/core/ngx_siphash.h [new file with mode: 0644]

index 46408ee5371f1c6c0fcb7ec821ac4de9ccef3667..2bce9cf8d0a6317beaa6adcf072632edd7c1ab15 100644 (file)
@@ -25,6 +25,7 @@ CORE_DEPS="src/core/nginx.h \
            src/core/ngx_crc.h \
            src/core/ngx_crc32.h \
            src/core/ngx_murmurhash.h \
+           src/core/ngx_siphash.h \
            src/core/ngx_md5.h \
            src/core/ngx_sha1.h \
            src/core/ngx_rbtree.h \
@@ -60,6 +61,7 @@ CORE_SRCS="src/core/nginx.c \
            src/core/ngx_file.c \
            src/core/ngx_crc32.c \
            src/core/ngx_murmurhash.c \
+           src/core/ngx_siphash.c \
            src/core/ngx_md5.c \
            src/core/ngx_sha1.c \
            src/core/ngx_rbtree.c \
index 02890b843ac2c54db25a7a698c743b71578fbf80..b919d5b31d356fd2aad92cd8967f6504cfdffb6a 100644 (file)
@@ -71,6 +71,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
 #include <ngx_crc.h>
 #include <ngx_crc32.h>
 #include <ngx_murmurhash.h>
+#include <ngx_siphash.h>
 #if (NGX_PCRE)
 #include <ngx_regex.h>
 #endif
diff --git a/src/core/ngx_siphash.c b/src/core/ngx_siphash.c
new file mode 100644 (file)
index 0000000..8cf8128
--- /dev/null
@@ -0,0 +1,95 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+/*
+ * SipHash-2-4 implementation based on the SipHash specification by
+ * Jean-Philippe Aumasson and Daniel J. Bernstein.
+ * https://eprint.iacr.org/2012/351.pdf
+ */
+
+
+#define ngx_siphash_rotl(x, b)                                                \
+    (uint64_t) (((x) << (b)) | ((x) >> (64 - (b))))
+
+#define ngx_sipround                                                          \
+    do {                                                                      \
+        v0 += v1; v1 = ngx_siphash_rotl(v1, 13); v1 ^= v0;                    \
+        v0 = ngx_siphash_rotl(v0, 32);                                        \
+        v2 += v3; v3 = ngx_siphash_rotl(v3, 16); v3 ^= v2;                    \
+        v0 += v3; v3 = ngx_siphash_rotl(v3, 21); v3 ^= v0;                    \
+        v2 += v1; v1 = ngx_siphash_rotl(v1, 17); v1 ^= v2;                    \
+        v2 = ngx_siphash_rotl(v2, 32);                                        \
+    } while (0)
+
+
+uint64_t
+ngx_siphash(uint64_t k0, uint64_t k1, u_char *data, size_t len)
+{
+    u_char    *end;
+    size_t     remainder;
+    uint64_t   v0, v1, v2, v3, m;
+
+    v0 = k0 ^ 0x736f6d6570736575ULL;
+    v1 = k1 ^ 0x646f72616e646f6dULL;
+    v2 = k0 ^ 0x6c7967656e657261ULL;
+    v3 = k1 ^ 0x7465646279746573ULL;
+
+    remainder = len & 7;
+    end = data + len - remainder;
+
+    for ( /* void */ ; data != end; data += 8) {
+        ngx_memcpy(&m, data, 8);
+        v3 ^= m;
+        ngx_sipround;
+        ngx_sipround;
+        v0 ^= m;
+    }
+
+    m = (uint64_t) len << 56;
+
+    switch (remainder) {
+    case 7:
+        m |= (uint64_t) data[6] << 48;
+        /* fall through */
+    case 6:
+        m |= (uint64_t) data[5] << 40;
+        /* fall through */
+    case 5:
+        m |= (uint64_t) data[4] << 32;
+        /* fall through */
+    case 4:
+        m |= (uint64_t) data[3] << 24;
+        /* fall through */
+    case 3:
+        m |= (uint64_t) data[2] << 16;
+        /* fall through */
+    case 2:
+        m |= (uint64_t) data[1] << 8;
+        /* fall through */
+    case 1:
+        m |= (uint64_t) data[0];
+        break;
+    case 0:
+        break;
+    }
+
+    v3 ^= m;
+    ngx_sipround;
+    ngx_sipround;
+    v0 ^= m;
+
+    v2 ^= 0xff;
+    ngx_sipround;
+    ngx_sipround;
+    ngx_sipround;
+    ngx_sipround;
+
+    return v0 ^ v1 ^ v2 ^ v3;
+}
diff --git a/src/core/ngx_siphash.h b/src/core/ngx_siphash.h
new file mode 100644 (file)
index 0000000..dd72a78
--- /dev/null
@@ -0,0 +1,18 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_SIPHASH_H_INCLUDED_
+#define _NGX_SIPHASH_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+uint64_t ngx_siphash(uint64_t k0, uint64_t k1, u_char *data, size_t len);
+
+
+#endif /* _NGX_SIPHASH_H_INCLUDED_ */