{"record":{"id":"1cc0224ebbf8583c","repo":"XTLS/Xray-core","slug":"bad-shared-secret-length-d","errorCode":null,"errorMessage":"bad shared secret length: %d","messagePattern":"bad shared secret length: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/server.go","lineNumber":194,"sourceCode":"\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"read encrypt response: %w\", err)\n\t\t}\n\n\t\tif pkt.packetID != 0x01 {\n\t\t\treturn fmt.Errorf(\"bad encrypt response packet id\")\n\t\t}\n\n\t\terr = pkt.readFields(&encryptedSharedSecret, &encryptedVerifyToken)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"read encrypt response: %w\", err)\n\t\t}\n\n\t\tsharedSecret, err = rsa.DecryptPKCS1v15(rand.Reader, c.rsaPrivateKey, encryptedSharedSecret)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"decrypt shared secret: %w\", err)\n\t\t}\n\t\tif len(sharedSecret) != 16 {\n\t\t\treturn fmt.Errorf(\"bad shared secret length: %d\", len(sharedSecret))\n\t\t}\n\n\t\tdecryptedVerifyToken, err = rsa.DecryptPKCS1v15(rand.Reader, c.rsaPrivateKey, encryptedVerifyToken)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"decrypt verify token: %w\", err)\n\t\t}\n\n\t\tif len(decryptedVerifyToken) < 4 || !bytes.Equal(verifyToken, decryptedVerifyToken[:4]) {\n\t\t\treturn fmt.Errorf(\"verify token mismatch\")\n\t\t}\n\n\t\tc.reader, err = newCryptoReader(c.reader, sharedSecret)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"new crypto reader: %w\", err)\n\t\t}\n\n\t\tc.writer, err = newCryptoWriter(c.writer, sharedSecret)\n\t\tif err != nil {","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/server.go#L176-L212","documentation":"The decrypted shared secret is not exactly 16 bytes. The Minecraft protocol fixes the AES shared secret at 128 bits (16 bytes); after successful RSA decryption any other length means the client encrypted something that is not a conforming secret. This is a hard protocol violation, not a transient fault.","triggerScenarios":"A client that encrypts a secret of the wrong size (e.g. 24 or 32 bytes for AES-192/256), a custom client that concatenated secret+extra data, or an attacker whose random ciphertext happened to decrypt to a different plaintext length.","commonSituations":"Modified or exotic Minecraft client forks using non-standard key sizes; test harnesses generating arbitrary plaintexts; protocol-version mismatch where the secret layout changed.","solutions":["Reject and disconnect: this is the correct server behavior; no retry is defined by the protocol.","If you control the client, make it generate the secret with aes.NewCipher-compatible 16-byte keys (crypto/rand.Read(make([]byte, 16))).","Log the observed length and client address to spot systematic client-side bugs versus one-off junk."],"exampleFix":"// before\nif len(sharedSecret) != 16 {\n    return fmt.Errorf(\"bad shared secret length: %d\", len(sharedSecret))\n}\n\n// after: same check, but send a proper disconnect before dropping\nif len(sharedSecret) != 16 {\n    writeDisconnectPacket(c.writer, `{\"text\":\"Bad shared secret length\"}`)\n    return fmt.Errorf(\"bad shared secret length: %d\", len(sharedSecret))\n}","handlingStrategy":"validation","validationCode":"if len(sharedSecret) != 16 {\n    // protocol violation; disconnect, never negotiate\n    return fmt.Errorf(\"bad shared secret length: %d\", len(sharedSecret))\n}","typeGuard":"func isValidSharedSecret(s []byte) bool { return len(s) == 16 }","tryCatchPattern":null,"preventionTips":["On the client, always generate the secret via make([]byte, 16) filled from crypto/rand.","Never accept AES-192/256 secrets from forks; the protocol fixes the secret at 128 bits.","Include the observed length in logs to catch client-side key-size bugs early."],"tags":["crypto","aes","protocol-violation","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}