XTLS/Xray-core · critical
encrypt verify token: %w
Error message
encrypt verify token: %w
What it means
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.
Source
Thrown at transport/internet/finalmask/xmc/client.go:169
if !ok {
return fmt.Errorf("parse server public key: not rsa")
}
sharedSecret := make([]byte, 16)
if _, err = rand.Read(sharedSecret); err != nil {
return fmt.Errorf("generate shared secret: %w", err)
}
encryptedSharedSecret, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, sharedSecret)
if err != nil {
return fmt.Errorf("encrypt shared secret: %w", err)
}
verifyToken = append(verifyToken, []byte(c.password)...) // append pre-shared password
encryptedVerifyToken, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, verifyToken)
if err != nil {
return fmt.Errorf("encrypt verify token: %w", err)
}
// Send Encryption Response
err = writePacket(
c.writer,
0x01,
(*Bytes)(&encryptedSharedSecret),
(*Bytes)(&encryptedVerifyToken),
)
if err != nil {
return fmt.Errorf("write encryption response: %w", err)
}
// Enable encryption
c.reader, err = newCryptoReader(c.reader, sharedSecret)
if err != nil {
return fmt.Errorf("new crypto reader: %w", err)
}View on GitHub (pinned to 7d214f8b09)
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
Example fix
// before cfg.Password = "a1b2c3...very-long-512-char-secret..." // with 1024-bit key // after priv, _ := rsa.GenerateKey(rand.Reader, 2048) // server side cfg.Password = "reasonable-length-secret"
Defensive patterns
Strategy: validation
Validate before calling
k, _ := x509.ParsePKIXPublicKey(cfg.RsaPublicKey)
rpk, _ := k.(*rsa.PublicKey)
maxPwd := rpk.Size() - 11 - 4 // key bytes - PKCS1 overhead - 4-byte verify token
if len(cfg.Password) > maxPwd {
return fmt.Errorf("password exceeds %d bytes for this RSA key", maxPwd)
} Prevention
- Keep pre-shared passwords under ~100 bytes
- Pair long secrets with 2048+ bit keys
- Validate password length against key size at config load
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- encrypt shared secret: %w
- parse server public key: %w
- parse server public key: not rsa
- read login finished: %w
- failed to compute mod inverse
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/f9a3453caf480b62.
Report an issue: GitHub.