From e93087afeb46d550920c65417ba842c27f8ad6f6 Mon Sep 17 00:00:00 2001 From: "Brandon McGinty (deepseek)" Date: Sun, 9 Aug 2026 02:30:28 -0400 Subject: [PATCH] Fix udp15Server decrypt IV: use server_nonce, not client_nonce MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SetUDP15Crypto was initializing udp15Server with setup15(key, serverNonce, clientNonce), which set decryptIV=clientNonce. But the server encrypts with server_nonce, so the client-side decryptIV must be server_nonce. The incoming IV byte from the server was 0x58, but our decryptIV[0] was 0xab (client_nonce[0]). Diff of -83, way outside the ±30 acceptance window. Now udp15Server.decryptIV is directly set to server_nonce. --- gumble/gumble/udp15.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gumble/gumble/udp15.go b/gumble/gumble/udp15.go index 1132c53..a91b7ec 100644 --- a/gumble/gumble/udp15.go +++ b/gumble/gumble/udp15.go @@ -412,6 +412,8 @@ var udp15Client *cryptState15 var udp15Server *cryptState15 // SetUDP15Crypto installs the 1.5 native UDP crypto state from CryptSetup. +// udp15Client: encrypts with client_nonce (outbound). +// udp15Server: decrypts with server_nonce (inbound). func SetUDP15Crypto(key, clientNonce, serverNonce []byte) { csClient := &cryptState15{} if err := csClient.setup15(key, clientNonce, serverNonce); err != nil { @@ -420,11 +422,12 @@ func SetUDP15Crypto(key, clientNonce, serverNonce []byte) { } udp15Client = csClient + // Server state: we only use decryptIV (to decrypt server→client packets). + // The server encrypts with server_nonce, so our decryptIV must be server_nonce. csServer := &cryptState15{} - if err := csServer.setup15(key, serverNonce, clientNonce); err != nil { - log.Error("SetUDP15Crypto server: %v", err) - return - } + copy(csServer.key[:], key) + copy(csServer.decryptIV[:], serverNonce) + csServer.initialized = true udp15Server = csServer log.Info("Mumble 1.5 native UDP crypto initialized")