{"record":{"id":"101929ddefebd917","repo":"XTLS/Xray-core","slug":"decrypt-shared-secret-w","errorCode":null,"errorMessage":"decrypt shared secret: %w","messagePattern":"decrypt shared secret: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/server.go","lineNumber":191,"sourceCode":"\t\t)\n\n\t\tpkt, err = readPacket(c.reader)\n\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}","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/server.go#L173-L209","documentation":"RSA PKCS#1 v1.5 decryption of the client-encrypted shared secret failed. The client encrypts a 16-byte AES shared secret with the server's public key from the encryption request; the server decrypts with its private key using rsa.DecryptPKCS1v15. Failure means the ciphertext was not produced with the matching public key, is malformed, or was tampered with.","triggerScenarios":"The client encrypted the secret with a different/stale public key (server key rotated between connections), the ciphertext array is not exactly the key modulus size or is empty/truncated, a malicious client sends random bytes to probe the key, or the server's rsaPrivateKey does not correspond to rsaPublicKey in the connection config.","commonSituations":"Server RSA keypair regenerated while old clients replayed a cached key; client and server disagree on the key because a proxy rewrites the encryption request; fuzzing/attack traffic; a client library that pads or segments the secret incorrectly.","solutions":["Verify the RSA keypair is self-consistent: check rsaPrivateKey.PublicKey equals the rsaPublicKey sent in the encryption request.","Log (at debug) len(encryptedSharedSecret) versus the private key modulus size — mismatches immediately reveal truncation or a foreign key.","If key rotation happened, restart or drain old client sessions so every client gets the current public key.","Treat repeated failures from one source as hostile: rate-limit or ban, do not retry the handshake with the same key."],"exampleFix":"// before\nsharedSecret, err = rsa.DecryptPKCS1v15(rand.Reader, c.rsaPrivateKey, encryptedSharedSecret)\nif err != nil {\n    return fmt.Errorf(\"decrypt shared secret: %w\", err)\n}\n\n// after: include ciphertext size for diagnosis\nsharedSecret, err := rsa.DecryptPKCS1v15(rand.Reader, c.rsaPrivateKey, encryptedSharedSecret)\nif err != nil {\n    return fmt.Errorf(\"decrypt shared secret (ct len %d, key bits %d): %w\",\n        len(encryptedSharedSecret), c.rsaPrivateKey.N.BitLen(), err)\n}","handlingStrategy":"validation","validationCode":"// before decrypting, sanity-check ciphertext length against the key\nif len(encryptedSharedSecret) != c.rsaPrivateKey.Size() {\n    return fmt.Errorf(\"shared secret ciphertext has wrong size %d (want %d)\",\n        len(encryptedSharedSecret), c.rsaPrivateKey.Size())\n}","typeGuard":null,"tryCatchPattern":"sharedSecret, err := rsa.DecryptPKCS1v15(rand.Reader, key, ct)\nif err != nil {\n    // do not distinguish error types in logs: RSA error details are a padding-oracle side channel\n    return errors.New(\"encryption handshake rejected\")\n}","preventionTips":["Validate ciphertext length equals the private-key modulus size before calling DecryptPKCS1v15.","Keep one RSA keypair per server process and serve it consistently to avoid stale-key clients.","Return a generic error to the peer; never echo decryption error details."],"tags":["crypto","rsa","handshake","security"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}