From c825507a1a391016067c7f51ffdb882dc208df54 Mon Sep 17 00:00:00 2001 From: 94xhn <87560781+94xhn@users.noreply.github.com> Date: Tue, 14 Jul 2026 08:39:54 +0800 Subject: [PATCH] Fix wrong Sec-WebSocket-Accept for non-24-char Sec-WebSocket-Key get_handshake_accept() always hashed a fixed WS_KEYMS_LEN (60) bytes of the key+magic-string buffer, regardless of the actual length of the client-supplied Sec-WebSocket-Key. This only produced the correct SHA-1 input for keys that happen to be exactly 24 characters (the common/base64-of-16-bytes case); for any other key length the hash covered stale/zero bytes beyond the real key+magic-string content, so the server computed and returned a Sec-WebSocket-Accept value that does not match RFC 6455 4.1, even though the connection was otherwise accepted. Fix by hashing strlen(str) instead of the fixed WS_KEYMS_LEN. Since str is calloc-zeroed and built via strncpy(str, wsKey, WS_KEY_LEN) followed by strcat(str, MAGIC_STRING), strlen(str) always equals the true (possibly truncated) key length plus the magic-string length, and is bounded by the buffer's allocated size (WS_KEY_LEN + WS_MS_LEN). Verified with a standalone harness against src/handshake.c: the standard 24-char RFC6455 example key still yields the well-known correct Accept value, and a 7-char test key now yields the independently-computed correct value (previously wrong). --- src/handshake.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handshake.c b/src/handshake.c index 57036c2..05c9d5e 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -63,7 +63,7 @@ int get_handshake_accept(char *wsKey, unsigned char **dest) strcat(str, MAGIC_STRING); SHA1Reset(&ctx); - SHA1Input(&ctx, (const uint8_t *)str, WS_KEYMS_LEN); + SHA1Input(&ctx, (const uint8_t *)str, strlen(str)); SHA1Result(&ctx, hash); *dest = base64_encode(hash, SHA1HashSize, NULL);