{"record":{"id":"443f43b11b452873","repo":"AlexxIT/go2rtc","slug":"wrong-timedelta-s","errorCode":null,"errorMessage":"wrong timedelta %s","messagePattern":"wrong timedelta (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/webtorrent/crypto.go","lineNumber":32,"sourceCode":"\tgcm   cipher.AEAD\n\tiv    []byte\n\tnonce []byte\n}\n\nfunc NewCipher(share, pwd, nonce string) (*Cipher, error) {\n\ttimestamp, err := strconv.ParseInt(nonce, 36, 64)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdelta := time.Duration(time.Now().UnixNano() - timestamp)\n\tif delta < 0 {\n\t\tdelta = -delta\n\t}\n\n\t// protect from replay attack, but respect wrong timezone on server\n\tif delta > 12*time.Hour {\n\t\treturn nil, fmt.Errorf(\"wrong timedelta %s\", delta)\n\t}\n\n\tc := &Cipher{}\n\n\thash := sha256.New()\n\thash.Write([]byte(nonce + \":\" + pwd))\n\tkey := hash.Sum(nil)\n\n\thash.Reset()\n\thash.Write([]byte(share + \":\" + nonce))\n\tc.iv = hash.Sum(nil)[:12]\n\n\tblock, err := aes.NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tc.gcm, err = cipher.NewGCM(block)\n\tif err != nil {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/webtorrent/crypto.go#L14-L50","documentation":"Returned by webtorrent NewCipher. The ciphertext embeds a timestamp; NewCipher computes the delta between that timestamp and now, and rejects anything whose absolute delta exceeds 12 hours. This replay-protection window tolerates server/client clock skew (including timezone differences) but refuses tokens that are too old or dated in the future.","triggerScenarios":"Creating a webtorrent Cipher via NewCipher (directly or through NewClient/reader) when the embedded timestamp in the input is more than 12 hours away from the local clock — either genuinely stale input or a badly skewed clock.","commonSituations":"Client machine clock drifted by hours (dead CMOS battery, wrong timezone/NTP); reusing a cached magnet/infohash token from a previous session; processing recorded/old WebTorrent data long after creation.","solutions":["Sync the system clock (NTP) and verify the timezone is correct","Regenerate the token/input — do not reuse ciphertexts older than 12 hours","Check for clock skew between client and the WebTorrent server (compare `date -u` on both)","If legitimate long-lived tokens are needed, this library's 12h window is by design; issue fresh tokens instead","If skew is systemic in your fleet, deploy NTP/chrony across hosts"],"exampleFix":"// before\n$ date\nThu Sep 7 03:12:00 UTC 2026  // clock is actually Sep 7 15:00 -> delta > 12h\n// after\n$ sudo ntpdate pool.ntp.org  # or enable systemd-timesyncd / chronyd\n$ date\nMon Sep 7 14:59:58 UTC 2026  // within 12h window, NewCipher succeeds","handlingStrategy":"validation","validationCode":"// Go/shell: check clock sanity before cipher use\nif drift := time.Since(lastNtpSync); drift > time.Hour { return errors.New(\"clock drift too large; sync NTP first\") }","typeGuard":null,"tryCatchPattern":"c, err := webtorrent.NewCipher(nonce, pwd, data)\nif err != nil {\n    if strings.Contains(err.Error(), \"wrong timedelta\") {\n        return errors.New(\"stale token or clock skew — resync NTP and regenerate token\")\n    }\n    return err\n}","preventionTips":["Run NTP/chrony on all hosts running go2rtc","Never cache webtorrent ciphertexts longer than 12 hours","Compare `date -u` across client and server when debugging","Regenerate tokens instead of reusing old sessions"],"tags":["webtorrent","crypto","clock-skew","replay-protection"],"backgroundTag":"timestamp-skew","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}