{"record":{"id":"f9a3453caf480b62","repo":"XTLS/Xray-core","slug":"encrypt-verify-token-w","errorCode":null,"errorMessage":"encrypt verify token: %w","messagePattern":"encrypt verify token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"transport/internet/finalmask/xmc/client.go","lineNumber":169,"sourceCode":"\tif !ok {\n\t\treturn fmt.Errorf(\"parse server public key: not rsa\")\n\t}\n\n\tsharedSecret := make([]byte, 16)\n\tif _, err = rand.Read(sharedSecret); err != nil {\n\t\treturn fmt.Errorf(\"generate shared secret: %w\", err)\n\t}\n\n\tencryptedSharedSecret, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, sharedSecret)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"encrypt shared secret: %w\", err)\n\t}\n\n\tverifyToken = append(verifyToken, []byte(c.password)...) // append pre-shared password\n\n\tencryptedVerifyToken, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, verifyToken)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"encrypt verify token: %w\", err)\n\t}\n\n\t// Send Encryption Response\n\terr = writePacket(\n\t\tc.writer,\n\t\t0x01,\n\t\t(*Bytes)(&encryptedSharedSecret),\n\t\t(*Bytes)(&encryptedVerifyToken),\n\t)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"write encryption response: %w\", err)\n\t}\n\n\t// Enable encryption\n\tc.reader, err = newCryptoReader(c.reader, sharedSecret)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"new crypto reader: %w\", err)\n\t}","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/client.go#L151-L187","documentation":"rsa.EncryptPKCS1v15 failed while encrypting verifyToken||password. Unlike the 16-byte shared secret (error 863), this input grows with the password length, so it overflows whenever len(verifyToken)+len(c.Password) > keySize-11. With a 512-bit server key (k=64) any password longer than ~40 bytes (minus the 4-byte token) fails; even 1024-bit keys cap the password around 133 bytes.","triggerScenarios":"First Read/Write on a WrapConnClient connection where Config.Password is long relative to the server RSA key size. The server appends the 4-byte verify token then the password before encrypting, so oversized passwords or undersized keys trigger rsa.ErrMessageTooLong.","commonSituations":"Using a long pre-shared secret (e.g. a 64+ hex char token) with a 512-bit test key, or pasting an API-key-style long password while the server still runs a small key.","solutions":["Shorten the pre-shared password so len(password)+4 <= rsaKeyBytes-11 (for 2048-bit: max 245 bytes; for 1024-bit: 133)","Increase the server RSA key to 2048 bits so any reasonable password fits","Keep the same password on client and server after any change — mismatch causes 'authentication rejected' instead"],"exampleFix":"// before\ncfg.Password = \"a1b2c3...very-long-512-char-secret...\" // with 1024-bit key\n\n// after\npriv, _ := rsa.GenerateKey(rand.Reader, 2048) // server side\ncfg.Password = \"reasonable-length-secret\"","handlingStrategy":"validation","validationCode":"k, _ := x509.ParsePKIXPublicKey(cfg.RsaPublicKey)\nrpk, _ := k.(*rsa.PublicKey)\nmaxPwd := rpk.Size() - 11 - 4 // key bytes - PKCS1 overhead - 4-byte verify token\nif len(cfg.Password) > maxPwd {\n    return fmt.Errorf(\"password exceeds %d bytes for this RSA key\", maxPwd)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep pre-shared passwords under ~100 bytes","Pair long secrets with 2048+ bit keys","Validate password length against key size at config load"],"tags":["crypto","rsa","password","key-size","go"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}