{"record":{"id":"e41df29bfc79418d","repo":"fatedier/frp","slug":"invalid-crypto-client-random-length-d-want-d","errorCode":null,"errorMessage":"invalid crypto client random length %d, want %d","messagePattern":"invalid crypto client random length (.+?), want (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proto/wire/crypto.go","lineNumber":84,"sourceCode":"\t\treturn ServerHello{}, err\n\t}\n\treturn ServerHello{\n\t\tSelected: ServerSelection{\n\t\t\tMessage: MessageSelection{\n\t\t\t\tCodec:          MessageCodecJSON,\n\t\t\t\tUDPPacketCodec: selectUDPPacketCodec(clientHello.Capabilities.Message.UDPPacketCodecs),\n\t\t\t},\n\t\t\tCrypto: CryptoSelection{\n\t\t\t\tAlgorithm:    algorithm,\n\t\t\t\tServerRandom: serverRandom,\n\t\t\t},\n\t\t},\n\t}, nil\n}\n\nfunc ValidateCryptoCapabilities(c CryptoCapabilities) error {\n\tif len(c.ClientRandom) != CryptoRandomSize {\n\t\treturn fmt.Errorf(\"invalid crypto client random length %d, want %d\", len(c.ClientRandom), CryptoRandomSize)\n\t}\n\tif _, ok := SelectAEADAlgorithm(c.Algorithms); !ok {\n\t\treturn fmt.Errorf(\"no supported crypto algorithm\")\n\t}\n\treturn nil\n}\n\nfunc ValidateServerHelloForClient(clientHello ClientHello, serverHello ServerHello) error {\n\tif serverHello.Selected.Message.Codec != MessageCodecJSON {\n\t\treturn fmt.Errorf(\"unsupported selected message codec: %s\", serverHello.Selected.Message.Codec)\n\t}\n\tudpPacketCodec := serverHello.Selected.Message.UDPPacketCodec\n\tif udpPacketCodec != \"\" {\n\t\tif udpPacketCodec != UDPPacketCodecBinary {\n\t\t\treturn fmt.Errorf(\"unsupported selected UDP packet codec: %s\", udpPacketCodec)\n\t\t}\n\t\tif !Supports(clientHello.Capabilities.Message.UDPPacketCodecs, udpPacketCodec) {\n\t\t\treturn fmt.Errorf(\"selected UDP packet codec was not advertised by client: %s\", udpPacketCodec)","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/proto/wire/crypto.go#L66-L102","documentation":"ValidateCryptoCapabilities rejected a ClientHello because its ClientRandom is not exactly CryptoRandomSize (32) bytes. The 32-byte random is a hard protocol requirement — it feeds the transcript hash used to derive session keys, so a wrong length breaks key derivation.","triggerScenarios":"Constructing or deserializing a ClientHello (or calling ValidateClientHello/ValidateCryptoCapabilities) where Capabilities.Crypto.ClientRandom has len != 32 — hand-built hello, truncated field, or a peer using a different protocol revision.","commonSituations":"Custom test code filling ClientRandom with a short constant; version skew changing the field's encoding; deserialization bug dropping bytes.","solutions":["Always create client random via NewClientHello / newCryptoRandom, which guarantees 32 bytes from crypto/rand","If building hello manually, copy exactly 32 bytes: make([]byte, wire.CryptoRandomSize) filled by crypto/rand","Align peer versions so the wire format matches"],"exampleFix":"// before\nhello := clientHelloWithCryptoRandom(bootstrap, []byte(\"short\")) // len 5\n\n// after\nr := make([]byte, wire.CryptoRandomSize) // 32\nrand.Read(r)\nhello := clientHelloWithCryptoRandom(bootstrap, r)","handlingStrategy":"validation","validationCode":"if len(hello.Capabilities.Crypto.ClientRandom) != wire.CryptoRandomSize {\n    return fmt.Errorf(\"client random must be %d bytes\", wire.CryptoRandomSize)\n}","typeGuard":"func hasValidClientRandom(c wire.CryptoCapabilities) bool {\n    return len(c.ClientRandom) == wire.CryptoRandomSize\n}","tryCatchPattern":"if err := wire.ValidateClientHello(hello); err != nil {\n    return fmt.Errorf(\"dropping malformed hello: %w\", err)\n}","preventionTips":["Never hand-build ClientRandom; use NewClientHello so random generation is correct","Validate deserialized hellos before acting on them"],"tags":["crypto","protocol","validation","handshake","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}