Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pdf signature validation: CMSSignedData contains no signed attributes #1984

Open
ralfhauser opened this issue Feb 3, 2025 · 3 comments
Open

Comments

@ralfhauser
Copy link

The signed attached file validates with Acrobat Viewer but not with BouncyCastle.
It seems that the

SignerInformation signer = (SignerInformation) signerIt.next(); AttributeTable sigAttr = signer.getSignedAttributes();

returns null ?

This happens with the JcaSimpleSignerInfoVerifierBuilder() as per org.bouncycastle.cms.test.BcSignedDataTest.verifySignatures()
or also with BcRSASignerInfoVerifierBuilder.

  1. Any idea why Adobe thinks the signature is still good?
  2. And if so, is there an example how to validate this with BC ?

t14675.pdf

@bsanchezb
Copy link

Hi @ralfhauser,

The signature does not contain any signed attributes, therefore BouncyCastle correctly returns null from the signer.getSignedAttributes() method. Please note that the signedAttrs field is optional in CMS:

RFC 5652 (5.3. SignerInfo Type):
signedAttrs is a collection of attributes that are signed. The
field is optional, but it MUST be present if the content type of
the EncapsulatedContentInfo value being signed is not id-data.

The signature is computed differently in case the signerAttrs are absent:

RFC 5652 (5.4. Message Digest Calculation Process):
The result of the message digest calculation process depends on
whether the signedAttrs field is present. When the field is absent,
the result is just the message digest of the content as described
above. When the field is present, however, the result is the message
digest of the complete DER encoding of the SignedAttrs value
contained in the signedAttrs field.

Therefore, in you case, the signature is computed directly on the original detached content. In case of a PDF, the signed content will correspond to the /ByteRange field's definition of the signature's revision (so it will cover the complete signed PDF file, with exception to the /Contents field encapsulating the CMS signature). In your case it is /ByteRange[0 139490 160282 5924]. You may see ISO 32000-1 for more information on how the signed data can be extracted according to the defined byte range.

In order to be able to validate the signature with BouncyCastle, you will need to provide the extracted content externally, as it is not encapsulated within the signature. For that you may use a constructor CMSSignedData(CMSProcessable signedContent, byte[] sigBlock) and provide the extracted content as a CMSProcessable, or use another constructor and provide only the hash of signed PDF content within a Map.

KR,
Aleksandr

@ralfhauser
Copy link
Author

Thanks - works!
(No signed attributes may save a few bytes, but in case of corruption, it is hard to determine what the original digest was?)

@bsanchezb
Copy link

bsanchezb commented Feb 5, 2025

@ralfhauser , please note that in general CMS without signed attributes are considered less secure, in particular due to an absence of a signing-certificate(-v2), which is, for example, a required property for a PAdES format (see ETSI EN 319 142-1, "Table 1: Requirements on the main attributes for PAdES baseline signatures").

but in case of corruption, it is hard to determine what the original digest was?)

Generally speaking, one still may try to decrypt the signature value using the public key of the signing certificate, provided that it is valid. The output should correspond to the original signed digest value.

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

No branches or pull requests

2 participants