Skip to content

feat(sign): expose SignData.ExtraSignedAttributes for caller-supplied PKCS#7 attrs#139

Open
jhionan wants to merge 1 commit into
digitorus:mainfrom
jhionan:feat/expose-extra-signed-attributes
Open

feat(sign): expose SignData.ExtraSignedAttributes for caller-supplied PKCS#7 attrs#139
jhionan wants to merge 1 commit into
digitorus:mainfrom
jhionan:feat/expose-extra-signed-attributes

Conversation

@jhionan
Copy link
Copy Markdown

@jhionan jhionan commented May 6, 2026

Summary

Currently `createSignedData` in `sign/pdfsignature.go` hard-codes the CMS `SignerInfoConfig.ExtraSignedAttributes` to exactly two entries — the Adobe RevocationData OID (`1.2.840.113583.1.1.8`) and the signing-certificate-v2 attribute. Callers who want to embed additional OID-keyed attributes inside the cryptographically protected PKCS#7 SignedAttributes set (RFC 5652 §11) have no way to do so today without forking the library.

This PR adds an opt-in field `SignData.ExtraSignedAttributes []pkcs7.Attribute`. When non-empty, the slice is appended to the library's two defaults before the SignerInfoConfig is wired into `AddSignerChain`. An empty slice is the default and preserves the prior behavior exactly.

Motivation

Use cases include:

  • Embedding a canonical content hash for downstream tamper detection (ICP-Brasil DOC-ICP-15.03 §6.4-style integrity attestations on PAdES laudos and similar regulated artifacts).
  • Transport-specific provenance OIDs that need to ride inside the signed bytes rather than free-form PDF string fields like `/Reason`.

In our use case (Brazilian NR-12 industrial-safety reports under CONFEA Resolução 1.025/2009), the `/Reason` field is too free-form for cryptographically anchored content-hash binding — the audit chain we sign requires an OID-keyed attribute that breaks `pkcs7.Verify` on tamper. We've been carrying an in-tree fork with this two-line patch and would prefer to retire it.

Diff at a glance

```
sign/pdfsignature.go | 13 ++++++++++---
sign/sign_test.go | 91 ++++++++++++++++++++++++++++++++++++++++++++++
sign/types.go | 18 ++++++++++++++++
3 files changed, 119 insertions(+), 3 deletions(-)
```

`sign/types.go` — adds the optional field with documentation.
`sign/pdfsignature.go` — appends caller-supplied attributes after the library defaults at the existing `SignerInfoConfig` construction site (no other behavior change).
`sign/sign_test.go` — `TestSignPDF_ExtraSignedAttributes_AppearInPKCS7`: signs a PDF with a custom OID-keyed attribute, re-parses the resulting PKCS#7 from the signed file, and recovers the value via `p7.UnmarshalSignedAttribute`.

Backward compatibility

Zero behavior change for any caller who does not set `ExtraSignedAttributes`. The new field is purely additive on the public `SignData` struct.

Test plan

  • `go test ./...` passes (`sign` 7.975s, `verify` 1.242s, `cli` 0.428s)
  • New test demonstrates round-trip embedding + extraction via `pkcs7.UnmarshalSignedAttribute`
  • No changes to existing test expectations

… PKCS#7 attrs

The CMS SignerInfoConfig built in createSignedData currently hard-codes
ExtraSignedAttributes to exactly the Adobe RevocationData OID
(1.2.840.113583.1.1.8) and the signing-certificate-v2 attribute. Callers
who want to embed additional OID-keyed attributes inside the
cryptographically protected PKCS#7 SignedAttributes set (RFC 5652 §11)
have no way to do so today without forking.

This adds an opt-in field SignData.ExtraSignedAttributes []pkcs7.Attribute.
When non-empty, the slice is appended to the library's two defaults
before the SignerInfoConfig is wired into AddSignerChain. An empty
slice is the default and preserves the prior behavior exactly.

Use cases include:

  - Embedding a canonical content hash for downstream tamper detection
    (ICP-Brasil DOC-ICP-15.03 §6.4-style integrity attestations on
    PAdES laudos and similar regulated artifacts).
  - Transport-specific provenance OIDs that need to ride inside the
    signed bytes rather than free-form PDF string fields.

Tested by signing a PDF with a custom OID-keyed attribute, re-parsing
the resulting PKCS#7 from the signed file, and recovering the value
via p7.UnmarshalSignedAttribute.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant