{"record":{"id":"46e5a2cdac809a37","repo":"AlexxIT/go2rtc","slug":"ciphertext-too-short-d-d","errorCode":null,"errorMessage":"ciphertext too short: %d <= %d","messagePattern":"ciphertext too short: (.+?) <= (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tutk/dtls/cipher.go","lineNumber":107,"sourceCode":"\n\tr := make([]byte, len(raw)+len(encryptedPayload))\n\tcopy(r, raw)\n\tcopy(r[len(raw):], encryptedPayload)\n\n\tbinary.BigEndian.PutUint16(r[pkt.Header.Size()-2:], uint16(len(r)-pkt.Header.Size()))\n\n\treturn r, nil\n}\n\nfunc (c *ChaCha20Poly1305Cipher) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) {\n\terr := header.Unmarshal(in)\n\tswitch {\n\tcase err != nil:\n\t\treturn nil, err\n\tcase header.ContentType == protocol.ContentTypeChangeCipherSpec:\n\t\treturn in, nil\n\tcase len(in) <= header.Size()+chachaTagLength:\n\t\treturn nil, fmt.Errorf(\"ciphertext too short: %d <= %d\", len(in), header.Size()+chachaTagLength)\n\t}\n\n\tnonce := computeNonce(c.remoteWriteIV, header.Epoch, header.SequenceNumber)\n\tout := in[header.Size():]\n\tadditionalData := generateAEADAdditionalData(&header, len(out)-chachaTagLength)\n\n\tout, err = c.remoteCipher.Open(out[:0], nonce, out, additionalData)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: %v\", errDecryptPacket, err)\n\t}\n\n\treturn append(in[:header.Size()], out...), nil\n}\n\ntype TLSEcdhePskWithChacha20Poly1305Sha256 struct {\n\taead atomic.Value\n}\n","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/tutk/dtls/cipher.go#L89-L125","documentation":"The DTLS ChaCha20-Poly1305 decrypt path validates that the record is longer than the record header plus the 16-byte AEAD tag before attempting to open the ciphertext. If the payload is too short to possibly contain valid ciphertext plus tag, decryption is skipped and this error is returned instead of a cryptic AEAD failure.","triggerScenarios":"Calling Decrypt on a record whose total length is <= header size + chachaTagLength — i.e. truncated packet, a zero-length payload record, or corrupted framing on the wire. ChangeCipherSpec records bypass the check.","commonSituations":"Corrupted or truncated UDP datagrams on lossy networks (TUTK runs DTLS over UDP); packets reassembled incorrectly; a peer sending malformed DTLS records due to a version/implementation mismatch.","solutions":["Check the captured raw packet length — the peer sent a record smaller than header+16 bytes; look for truncation or corruption upstream.","Verify both peers negotiate the same DTLS record format/cipher suite version.","Add packet-loss/duplication handling on the UDP transport and retransmit failed records.","If it happens on handshake boundary, ensure the ChangeCipherSpec record is delivered before encrypted application data."],"exampleFix":"// before\nout, err := cipher.Decrypt(h, raw)\nif err != nil { return err }\n// after\nif len(raw) <= recordHeaderSize+16 {\n\tlog.Printf(\"dropping short DTLS record: %d bytes\", len(raw))\n\treturn nil // skip malformed record\n}\nout, err := cipher.Decrypt(h, raw)","handlingStrategy":"validation","validationCode":"// Validate record length before decrypting\nif len(raw) <= recordHeaderSize+16 {\n\tlog.Printf(\"skipping short DTLS record: %d bytes\", len(raw))\n\treturn nil\n}","typeGuard":"func isDecryptableRecord(raw []byte, hdrSize, tagLen int) bool {\n\treturn len(raw) > hdrSize+tagLen\n}","tryCatchPattern":"out, err := cipher.Decrypt(h, raw)\nif err != nil {\n\tif strings.Contains(err.Error(), \"ciphertext too short\") {\n\t\tmetrics.ShortRecordDropped.Inc()\n\t\treturn nil // drop malformed record\n\t}\n\treturn err\n}","preventionTips":["Check UDP transport for truncation/reassembly bugs","Verify both peers use the same DTLS version and record framing","Drop-and-count malformed records instead of failing the session","Monitor packet corruption rates on lossy links"],"tags":["dtls","crypto","tls","packet"],"backgroundTag":"invalid-argument-format","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"}