openwall / openwall/john

pdf2john.py incorrectly defaults to 40-bit key length in V4/R4 PDF

Open Beginner friendly
#6,033 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C
Stars
13.6k
Forks
2.6k
PR merge metrics
No merged PRs in 30d

Description

Hi,
I found a V4/R4 PDF where the encryption dictionary does not contain a top-level /Length, but the applicable crypt filter does:

qpdf output for the encryption object:

/V 4
/R 4
/CF <<
  /StdCF <<
    /AuthEvent /DocOpen
    /CFM /AESV2
    /Length 16
  >>
>>
/StmF /StdCF
/StrF /StdCF

There is no top-level /Length entry.

Running:

pdf2john.py sample.pdf

produces:

$pdf$4*4*40*-4*...

The 40 seems to come from:

self.length = self.encrypt_dict.get("/Length", 40)

However, for this V4/R4 PDF the applicable /StdCF crypt filter has:

/Length 16

which corresponds to a 128-bit encryption key.

For comparison, qpdf --show-encryption --password='...' sample.pdf reports:

R = 4
stream encryption method: AESv2
string encryption method: AESv2
file encryption method: AESv2

The resulting 40 in the $pdf$ hash causes john to interpret the PDF as having a 40-bit key, even though the actual encryption uses AES-128.
This then results in the hash not being able to be cracked.

Manually chaning the length to 128 instead of 40 fixes the issue and the password was correctly found by john.

PDF metadata:

Creator:     Aspose Pty Ltd.
Producer:    PDFsharp 6.2.0 (Original: Aspose.PDF for .NET 26.3.0)
PDF version: 1.7
Encryption:  AES (Revision 4 / V4)

The reference also states that /Length is optional:
https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/pdfreference1.7old.pdf - section 3.5, page 117

(Optional; PDF 1.4; only if V is 2 or 3) The length of the encryption key, in bits. The value
must be a multiple of 8, in the range 40 to 128. Default value: 40.

Expected behavior

For V4/R4 PDFs using a crypt filter, pdf2john.py should determine the effective key length from the applicable crypt filter when /Length is not present at the top level, rather than unconditionally falling back to the 40-bit default.

KR Alex

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in pdf2john.py at the self.length assignment and trace how the V4/R4 encryption dictionary and applicable crypt filter are parsed. Use the provided sample.pdf scenario to verify that the generated $pdf$ hash reports the effective 128-bit length rather than 40 bits; no test file is named in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.