AlexxIT/go2rtc · error

%w: %v

Error message

%w: %v

What it means

When the AEAD Open (authenticated decryption) fails — typically because the Poly1305 tag does not verify — Decrypt wraps the underlying error as '<errDecryptPacket>: <detail>'. This means the record failed authentication: wrong key material, wrong nonce, or corrupted/altered ciphertext.

Solutions

  1. Check PSK/session key agreement — both sides must derive identical keys (verify credentials/handshake).
  2. Ensure records are processed in order and sequence numbers/epochs match; drop replays before decrypt.
  3. Enable DTLS retransmission/anti-replay handling on the transport and retransmit lost handshake flights.
  4. If corruption is environmental (bad Wi-Fi/cabling), fix the link layer or add per-record retransmission.

Example fix

// before
out, err := cipher.Decrypt(h, raw)
if err != nil { return err }
// after
out, err := cipher.Decrypt(h, raw)
if err != nil {
	log.Printf("dtls decrypt failed (seq=%d): %v", h.SequenceNumber, err)
	return nil // drop inauthentic record, don't crash session
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Drop replays and out-of-order records before decrypting
if h.SequenceNumber <= lastSeenSeq || h.Epoch != expectedEpoch {
	return nil
}

Try / catch

out, err := cipher.Decrypt(h, raw)
if err != nil {
	if errors.Is(err, errDecryptPacket) {
		log.Printf("inauthentic record seq=%d: %v", h.SequenceNumber, err)
		return nil // drop record, keep session
	}
	return err
}

Prevention

When it happens

Trigger: Calling Decrypt when remoteCipher.Open returns an error: packet bytes corrupted in transit, replayed/reordered records producing wrong epoch/sequence nonce, or DTLS keys not synchronized (peer rekeyed mid-session).

Common situations: UDP packet corruption or tampering; handshake completed with mismatched keys (e.g. PSK differs between peers); sequence-number desync after dropped/reordered datagrams; replay of old packets.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/c571013601fa20c8. Report an issue: GitHub.

Appendix: source

Thrown at pkg/tutk/dtls/cipher.go:116

func (c *ChaCha20Poly1305Cipher) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) {
	err := header.Unmarshal(in)
	switch {
	case err != nil:
		return nil, err
	case header.ContentType == protocol.ContentTypeChangeCipherSpec:
		return in, nil
	case len(in) <= header.Size()+chachaTagLength:
		return nil, fmt.Errorf("ciphertext too short: %d <= %d", len(in), header.Size()+chachaTagLength)
	}

	nonce := computeNonce(c.remoteWriteIV, header.Epoch, header.SequenceNumber)
	out := in[header.Size():]
	additionalData := generateAEADAdditionalData(&header, len(out)-chachaTagLength)

	out, err = c.remoteCipher.Open(out[:0], nonce, out, additionalData)
	if err != nil {
		return nil, fmt.Errorf("%w: %v", errDecryptPacket, err)
	}

	return append(in[:header.Size()], out...), nil
}

type TLSEcdhePskWithChacha20Poly1305Sha256 struct {
	aead atomic.Value
}

func NewTLSEcdhePskWithChacha20Poly1305Sha256() *TLSEcdhePskWithChacha20Poly1305Sha256 {
	return &TLSEcdhePskWithChacha20Poly1305Sha256{}
}

func (c *TLSEcdhePskWithChacha20Poly1305Sha256) CertificateType() clientcertificate.Type {
	return clientcertificate.Type(0)
}

func (c *TLSEcdhePskWithChacha20Poly1305Sha256) KeyExchangeAlgorithm() dtls.CipherSuiteKeyExchangeAlgorithm {

View on GitHub (pinned to c245815e75)