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

  1. Shorten the pre-shared password so len(password)+4 <= rsaKeyBytes-11 (for 2048-bit: max 245 bytes; for 1024-bit: 133)
  2. Increase the server RSA key to 2048 bits so any reasonable password fits
  3. 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

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


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/f9a3453caf480b62. Report an issue: GitHub.