fatedier/frp · error
unknown selected crypto algorithm: %s
Error message
unknown selected crypto algorithm: %s
What it means
Thrown by ValidateServerHelloForClient when the crypto algorithm in ServerHello.Selected.Crypto.Algorithm is not in supportedAEADAlgorithms ("aes-256-gcm" or "xchacha20-poly1305"). This catches servers that select an algorithm this build cannot instantiate, before any AEAD cipher is constructed.
Source
Thrown at pkg/proto/wire/crypto.go:107
return nil
}
func ValidateServerHelloForClient(clientHello ClientHello, serverHello ServerHello) error {
if serverHello.Selected.Message.Codec != MessageCodecJSON {
return fmt.Errorf("unsupported selected message codec: %s", serverHello.Selected.Message.Codec)
}
udpPacketCodec := serverHello.Selected.Message.UDPPacketCodec
if udpPacketCodec != "" {
if udpPacketCodec != UDPPacketCodecBinary {
return fmt.Errorf("unsupported selected UDP packet codec: %s", udpPacketCodec)
}
if !Supports(clientHello.Capabilities.Message.UDPPacketCodecs, udpPacketCodec) {
return fmt.Errorf("selected UDP packet codec was not advertised by client: %s", udpPacketCodec)
}
}
cryptoSelection := serverHello.Selected.Crypto
if !IsSupportedAEADAlgorithm(cryptoSelection.Algorithm) {
return fmt.Errorf("unknown selected crypto algorithm: %s", cryptoSelection.Algorithm)
}
if !Supports(clientHello.Capabilities.Crypto.Algorithms, cryptoSelection.Algorithm) {
return fmt.Errorf("selected crypto algorithm was not advertised by client: %s", cryptoSelection.Algorithm)
}
if len(cryptoSelection.ServerRandom) != CryptoRandomSize {
return fmt.Errorf("invalid crypto server random length %d, want %d", len(cryptoSelection.ServerRandom), CryptoRandomSize)
}
return nil
}
func selectUDPPacketCodec(codecs []string) string {
if Supports(codecs, UDPPacketCodecBinary) {
return UDPPacketCodecBinary
}
return ""
}
func NewCryptoContext(algorithm string, clientHelloPayload, serverHelloPayload []byte) *CryptoContext {View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Run the same frp version on client and server so the supported algorithm sets are identical.
- On the server, select the algorithm only via SelectAEADAlgorithm(clientHello...Algorithms), never from config strings or user input.
- Verify the ServerHello payload is not being truncated or modified in transit (TLS/proxy setups that mangle bodies).
Example fix
// before (server, hand-rolled)
selected.Crypto.Algorithm = "aes-128-gcm"
// after
algorithm, ok := wire.SelectAEADAlgorithm(clientHello.Capabilities.Crypto.Algorithms)
if !ok { return errors.New("no shared algorithm") }
selected.Crypto.Algorithm = algorithm Defensive patterns
Strategy: validation
Validate before calling
if !wire.IsSupportedAEADAlgorithm(serverHello.Selected.Crypto.Algorithm) {
return fmt.Errorf("server selected unknown algorithm %q — likely version mismatch",
serverHello.Selected.Crypto.Algorithm)
} Prevention
- Servers: select algorithms only via SelectAEADAlgorithm over the client's list.
- Deploy matching frp versions on both peers.
When it happens
Trigger: Server sends an algorithm string outside the supported set — empty string, "aes-128-gcm", typo, or an algorithm introduced in a newer frp version. Detected in NewClientCryptoContext after decoding the ServerHello transcript.
Common situations: Version mismatch between client and server; corrupted handshake bytes that still parse as JSON; malicious server attempting to downgrade to a weak/unknown cipher.
Related errors
- no supported crypto algorithm
- invalid crypto client random length %d, want %d
- unsupported selected message codec: %s
- unsupported selected UDP packet codec: %s
- selected crypto algorithm was not advertised by client: %s
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/5b5b2127b6240d44.
Report an issue: GitHub.