0

I am trying to receive the user's password from a PDF file. For testing purposes I'm given both, the master's and user's password. Right now I am passing the master's password in a parameter and use it to create a new instance of iTextSharp.text.pdf.PdfReader which works fine. Then I'm entering an if-clause which should return whether the PDF is being opened with full permissions or not. Inside this if-clause I request the user's password by calling iTextSharp.text.pdf.PdfReader.ComputeUserPassword() which returns null.


My entire code looks like this (GetByteAr(string s) returns the password converted to a byte array):

public static bool IsPasswordProtectedOwner(string pdf, string ownerPw)
{

    try
    {
        var reader = new PdfReader(pdf, GetByteAr(ownerPw));
        if (reader.IsOpenedWithFullPermissions)
        {
            Console.WriteLine("opened with full permissions");
            string pw = String.Empty;
            var computedPassword = reader.ComputeUserPassword();
            foreach (byte b in computedPassword)
                pw += Char.ConvertFromUtf32(b);
        }
        else
        {
            Console.WriteLine("not opened with full permissions");
        }
    }
    catch (Exception e) when (e is NullReferenceException || e is BadPasswordException)
    {
        Console.WriteLine(e);
    }
    return true;
}

And my output looks like this:

opened with full permissions
System.NullReferenceException: Object reference not set to an instance of an object.
   at PDFsV2.PDFInteractor.IsPasswordProtectedOwner(String pdf, String ownerPw) 
      in C:\Users\user\source\repos\PDFsV2\PDFsV2\PDFInteractor.cs:line 57

Can you help me understand why computedPassword is null? Why is ComputeUserPassword returning null?

Edit, this is the reason why it returns null:

https://api.itextpdf.com/iText5/5.5.13/

public byte[] computeUserPassword()

Computes user password if standard encryption handler is used with Standard40, Standard128 or AES128 encryption algorithm.

Returns: user password, or null if not a standard encryption handler was used, if standard encryption handler was used with AES256 encryption algorithm, or if ownerPasswordUsed wasn't use to open the document.

JieBaef
  • 122
  • 1
  • 11

1 Answers1

1

https://github.com/kusl/itextsharp/blob/master/tags/iTextSharp_5_4_5/src/core/iTextSharp/text/pdf/PdfReader.cs#L3849 shows the implementation of ComputeUserPassword as:

public byte[] ComputeUserPassword() {
    if (!encrypted || !ownerPasswordUsed) return null;
    return decrypt.ComputeUserPassword(password);
}

As per that code (second line) it is possible for ComputeUserPassword to be null. As such, you need to cater for that in your code (i.e. check whether it is null before foreaching over it).

In your case, it is likely because:

ownerPasswordUsed = decrypt.ReadKey(enc, password);

is returning false. This may indicate you have the wrong password value.

Similarly, the docs state:

user password, or null if not a standard encryption handler was used or if ownerPasswordUsed wasn't use to open the document.

mjwills
  • 23,389
  • 6
  • 40
  • 63