]> git.kaiwu.me - nginx.git/commitdiff
Switched $request_id to SipHash-based generation
authorEugene Grebenschikov <e.grebenshchikov@f5.com>
Thu, 21 May 2026 17:38:47 +0000 (10:38 -0700)
committerEugene <54681898+jimf5@users.noreply.github.com>
Tue, 2 Jun 2026 22:30:30 +0000 (15:30 -0700)
Replaced RAND_bytes() and random() based $request_id
generation with SipHash-2-4.  The previous implementation
used RAND_bytes() when built with OpenSSL, which is
50-100x slower than needed for a non-security identifier,
and fell back to random() which produces poor 128-bit
random numbers.

The new implementation calls SipHash twice with a secret
key and a monotonic counter, producing 128 bits with good
statistical distribution at a fraction of the cost.

src/http/ngx_http_variables.c

index 37cd0d2877fe5a8c0b2938e2f2c68df97df021c2..191bc73c7f9c7e0856aa417690c7494fd76c8259 100644 (file)
@@ -2298,11 +2298,10 @@ static ngx_int_t
 ngx_http_variable_request_id(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    u_char  *id;
+    u_char    *id;
+    uint64_t   random_bytes[2];
 
-#if (NGX_OPENSSL)
-    u_char   random_bytes[16];
-#endif
+    static uint64_t  counter, key[2];
 
     id = ngx_pnalloc(r->pool, 32);
     if (id == NULL) {
@@ -2316,20 +2315,25 @@ ngx_http_variable_request_id(ngx_http_request_t *r,
     v->len = 32;
     v->data = id;
 
+    if (counter == 0) {
 #if (NGX_OPENSSL)
-
-    if (RAND_bytes(random_bytes, 16) == 1) {
-        ngx_hex_dump(id, random_bytes, 16);
-        return NGX_OK;
+        if (RAND_bytes((u_char *) key, 16) != 1)
+#endif
+        {
+            key[0] = ((uint64_t) ngx_random() << 32) | (uint32_t) ngx_random();
+            key[1] = ((uint64_t) ngx_random() << 32) | (uint32_t) ngx_random();
+            key[0] ^= (uint64_t) ngx_pid << 16;
+            key[1] ^= (uint64_t) ngx_time();
+        }
     }
 
-    ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0, "RAND_bytes() failed");
+    counter++;
+    random_bytes[0] = ngx_siphash(key[0], key[1], (u_char *) &counter, 8);
 
-#endif
+    counter++;
+    random_bytes[1] = ngx_siphash(key[0], key[1], (u_char *) &counter, 8);
 
-    ngx_sprintf(id, "%08xD%08xD%08xD%08xD",
-                (uint32_t) ngx_random(), (uint32_t) ngx_random(),
-                (uint32_t) ngx_random(), (uint32_t) ngx_random());
+    ngx_hex_dump(id, (u_char *) random_bytes, 16);
 
     return NGX_OK;
 }