XTLS/Xray-core · error
new crypto reader: %w
Error message
new crypto reader: %w
What it means
Constructing the AES-CFB crypto reader over the shared secret failed (newCryptoReader wraps the handshake reader with symmetric encryption). In this codebase the constructor derives an AES cipher from the 16-byte sharedSecret, so it only fails if the key length is not a valid AES size — which cannot happen since sharedSecret is hardcoded to 16 bytes. In practice this error is a defensive guard that is not expected to fire.
Source
Thrown at transport/internet/finalmask/xmc/client.go:186
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)
}
c.writer, err = newCryptoWriter(c.writer, sharedSecret)
if err != nil {
return fmt.Errorf("new crypto writer: %w", err)
}
pkt, err = readPacket(c.reader)
if err != nil {
return fmt.Errorf("read login finished: %w", err)
}
if pkt.packetID == 0x00 {
var reason String
if readErr := pkt.readFields(&reason); readErr != nil {
return fmt.Errorf("authentication rejected")
}
return fmt.Errorf("authentication rejected: %s", reason)
}View on GitHub (pinned to 7d214f8b09)
Solutions
- If you maintain a fork: keep the shared secret at 16 bytes (AES-128) to match the server
- Report upstream if it fires on unmodified code, since it indicates memory/state corruption
- Diff local changes against upstream to find altered key-derivation logic
Defensive patterns
Strategy: try-catch
Try / catch
if _, err := conn.Read(buf); err != nil && strings.Contains(err.Error(), "new crypto reader") {
// defensive branch: indicates modified build or corruption; do not retry
log.Error("unexpected crypto init failure", "err", err)
return err
} Prevention
- Do not change the 16-byte shared secret size in forks
- Pin to upstream releases for the crypto path
- Report occurrences upstream with a reproducer
When it happens
Trigger: Only reachable if newCryptoReader's internal aes.NewCipher(sharedSecret) fails, which requires a key size outside {16,24,32}; the fixed 16-byte allocation makes this unreachable under current code.
Common situations: None in normal operation. Seeing it usually means a fork modified the shared-secret size or the crypto constructor signature.
Related errors
- new crypto writer: %w
- outbound metadata not found
- Failed to build REALITY config.
- parse server public key: %w
- parse server public key: not rsa
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/8de4d24b8b55c1cf.
Report an issue: GitHub.