{"record":{"id":"bafb49e8501480da","repo":"XTLS/Xray-core","slug":"new-crypto-reader-w-bafb49","errorCode":null,"errorMessage":"new crypto reader: %w","messagePattern":"new crypto reader: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/server.go","lineNumber":208,"sourceCode":"\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 {\n\t\t\treturn fmt.Errorf(\"new crypto writer: %w\", err)\n\t\t}\n\n\t\t// verify password\n\t\treceivedPassword := decryptedVerifyToken[4:]\n\n\t\tif subtle.ConstantTimeCompare(receivedPassword, []byte(c.password)) != 1 {\n\t\t\twriteDisconnectPacket(c.writer, `{\"type\":\"translatable\",\"translate\":\"multiplayer.disconnect.authservers_down\"}`)\n\t\t\treturn fmt.Errorf(\"bad password\")\n\t\t}\n\t\tif !found {\n\t\t\tif err = writeDisconnectPacket(c.writer, `{\"text\":\"You are not white-listed on this server!\"}`); err != nil {\n\t\t\t\treturn fmt.Errorf(\"write unknown login profile disconnect: %w\", err)\n\t\t\t}","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/server.go#L190-L226","documentation":"Constructing the decrypting stream cipher (newCryptoReader) over the connection reader with the negotiated shared secret failed. This wraps the AES/CFB8 (Minecraft standard) stream initialization — with a 16-byte secret the only realistic failure paths are an AES cipher construction error from a wrong key length or an error from the underlying reader wrapping. Given the 16-byte check upstream, seeing this error is rare.","triggerScenarios":"sharedSecret passed with an unexpected length despite the earlier check (only possible via code drift), aes.NewCipher failing on a non-16/24/32-byte key, or an error returned by a wrapper around c.reader at construction time.","commonSituations":"Almost exclusively a code-regression symptom: someone relaxed the length check or changed the cipher mode/key derivation; in a healthy build this branch is effectively unreachable.","solutions":["If you see this in production, diff recent changes to the shared-secret length validation and newCryptoReader's key handling.","Add an assertion/test that newCryptoReader accepts any 16-byte key.","Treat as fatal for the connection; do not fall back to plaintext."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if len(sharedSecret) != 16 {\n    return fmt.Errorf(\"bad shared secret length: %d\", len(sharedSecret))\n}","typeGuard":null,"tryCatchPattern":"if _, err := newCryptoReader(c.reader, sharedSecret); err != nil {\n    // with a validated 16-byte key this is a code bug, not a runtime condition: fail loudly\n    return fmt.Errorf(\"new crypto reader: %w\", err)\n}","preventionTips":["Keep the 16-byte length check directly upstream of newCryptoReader/newCryptoWriter.","Unit-test newCryptoReader with random 16-byte keys so regressions surface in CI, not prod.","Never fall back to a plaintext reader on failure."],"tags":["crypto","aes","stream-cipher","unreachable-in-practice"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}