{"record":{"id":"64f664e90a2c1aa3","repo":"txthinking/brook","slug":"password-is-wrong","errorCode":null,"errorMessage":"Password is wrong","messagePattern":"Password is wrong","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"simplepacketserverconn.go","lineNumber":45,"sourceCode":"\ntype SimplePacketServerConnFactory struct {\n\tConns map[string]*PacketConn\n\tLock  *sync.Mutex\n}\n\nfunc NewSimplePacketServerConnFactory() *SimplePacketServerConnFactory {\n\treturn &SimplePacketServerConnFactory{\n\t\tConns: make(map[string]*PacketConn),\n\t\tLock:  &sync.Mutex{},\n\t}\n}\n\nfunc (f *SimplePacketServerConnFactory) Handle(addr *net.UDPAddr, b, p []byte, w func([]byte) (int, error), timeout int) (net.Conn, []byte, error) {\n\tif len(b) < 32+4 {\n\t\treturn nil, nil, errors.New(\"data too small\")\n\t}\n\tif bytes.Compare(p, b[:32]) != 0 {\n\t\treturn nil, nil, errors.New(\"Password is wrong\")\n\t}\n\ti := int64(binary.BigEndian.Uint32(b[32 : 32+4]))\n\tif time.Now().Unix()-i > 60 {\n\t\treturn nil, nil, errors.New(\"Expired request\")\n\t}\n\ta, h, p, err := socks5.ParseBytesAddress(b[32+4:])\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdst := socks5.ToAddress(a, h, p)\n\tf.Lock.Lock()\n\tc, ok := f.Conns[addr.String()+dst]\n\tf.Lock.Unlock()\n\tif ok {\n\t\t_ = c.In(b[32+4+1+len(h)+2:])\n\t\treturn nil, nil, nil\n\t}\n\tf.Lock.Lock()","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/simplepacketserverconn.go#L27-L63","documentation":"Handle compares the caller-supplied password p against the first 32 bytes of the packet b. If bytes.Compare(p, b[:32]) != 0 the embedded credential does not match the expected password, so authentication fails and the connection setup is aborted with this error.","triggerScenarios":"Calling Handle where p (expected password) differs byte-for-byte from b[:32] (password embedded in the packet): client configured with the wrong password, encoding/padding differences, or a stale password after a server-side rotation.","commonSituations":"Password rotated on the server but not the client (or vice versa); trailing newline/whitespace or non-zero padding differences in the 32-byte field; clients pointing at the wrong server deployment; attackers probing the UDP endpoint.","solutions":["Verify the client's configured password exactly matches the server's 32-byte key (same bytes, same padding — exactly 32 bytes, no trailing NUL/newline mismatch).","Re-sync credentials after a password rotation and redeploy both sides.","Log addr on mismatch to detect probing clients, but do not echo which side mismatched.","Hash/compare with a constant-time comparison (e.g. subtle.ConstantTimeCompare or hmac.Equal) if you control the code, and confirm key derivation is identical on both ends."],"exampleFix":"// before (client)\ncopy(buf, []byte(password)) // may be shorter/longer than 32 bytes\n// after\nkey := sha256.Sum256([]byte(password)) // deterministic 32 bytes\ncopy(buf, key[:])","handlingStrategy":"validation","validationCode":"func passwordBytes(pw string) ([32]byte, error) {\n    var k [32]byte\n    b := []byte(pw)\n    if len(b) > 32 { return k, errors.New(\"password longer than 32 bytes\") }\n    copy(k[:], b)\n    return k, nil\n}","typeGuard":"func is32ByteKey(b []byte) bool { return len(b) == 32 }","tryCatchPattern":"conn, rest, err := factory.Handle(addr, b, password, w, timeout)\nif err != nil {\n    if strings.Contains(err.Error(), \"Password is wrong\") {\n        return fmt.Errorf(\"authentication failed for %s: check shared key\", addr)\n    }\n    return err\n}","preventionTips":["Derive the 32-byte key deterministically (e.g. SHA-256 of the secret) on both sides.","Rotate credentials atomically across client and server.","Strip no/whitespace and encoding variations from configured passwords before use.","Rate-limit or drop sources with repeated password mismatches.","Use constant-time comparison if you control the comparison code."],"tags":["authentication","udp","password-mismatch","security"],"backgroundTag":"authentication-required","analyzedSha":"5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8","analyzedAt":"2026-09-06T04:35:00.432Z","contentChangedAt":"2026-09-06T04:35:00.432Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}