IntersectMBO / IntersectMBO/evolution-sdk

COSE_Sign1 signedData() re-encodes protected headers instead of preserving the original signed bytes

Offen
#480 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
bug external-review
Vorherrschende Sprache
TypeScript
Sterne
22
Forks
30
Ø Merge
5 Std. 29 Min.
Gemergte PRs (30 T.)
12

Beschreibung

## Summary
On decode, the original protected-header bytes of a COSE_Sign1 are dropped and only the parsed `HeaderMap` is kept; `signedData()` then rebuilds the `Sig_structure` by re-encoding those headers with canonical CBOR. In COSE (RFC 8152 / RFC 9052) the protected header is a `bstr` whose exact bytes are what the signature covers, so a conformant verifier must reuse the received bytes rather than re-encode. In practice most signers emit canonical bytes, so this SDK's re-encode usually matches and verification succeeds; but any signer whose protected-header bytes differ from this SDK's canonical re-encode will have a valid signature rejected. Fail closed: only ever rejects a valid signature, never accepts an invalid one.

## Affected
packages/evolution/src/cose/Sign1.ts
- signedData (L70-86): re-encodes protected headers via CBOR.CML_DEFAULT_OPTIONS (L76)
- decoder (L165): decodes protectedBytes into a HeaderMap and discards the original bytes

## Fix
Preserve the original protected-header bytes through decode and replay them in `signedData()`, decoding to a `HeaderMap` only as an on-demand view. The repo already has this mechanism: the `WeakMap` `formatCache` in `Transaction.ts` (L130) captures the `CBORFormat` at decode time so `toCBORBytes`/`toCBORHex` reproduce the original encoding byte-for-byte (non-default codec options opt out). Apply the same pattern to the COSE HeaderMap / COSESign1 path.

## Regression test
- given: a COSE_Sign1 whose protected headers use a non-minimal encoding (e.g. label 1 as 2 bytes), with a valid signature over those original bytes
- before fix: verifyData returns false (valid signature rejected)
- after fix: verifyData returns true
Must FAIL on main today and PASS after the fix.

## Reference
Reported informally (COSE protected-header re-serialization). Standard basis: RFC 8152 / RFC 9052 — the protected header is a signed `bstr`, so verification must operate on the received bytes. Same root principle as the CBOR duplicate-key / re-encode fidelity item (separate issue): a decoder must not alter the decoded bytes, and anything signed or hashed must use the original bytes.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Start in packages/evolution/src/cose/Sign1.ts, reading signedData() at L70-86 and the decoder at L165, then compare the original-byte preservation pattern in Transaction.ts around the formatCache at L130. Add the described non-minimal protected-header regression case and verify that it fails on main and passes once verification reuses the received bytes.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
cryptography, security
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Ruhig
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
72/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.