Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening password-protected pdf file with iTextSharp

I'm making an application that should display PDFs with password. This is my code:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        try
        {
            string filePath = Request.QueryString["filePath"];
            if (filePath.ToUpper().EndsWith("PDF"))
            {
                copyPDF(filePath);
            }
        }
        catch
        {
            string message = "<script language='Javascript'>alert('File Not Found! Call Records Department for verification. ')</script>";
            ScriptManager.RegisterStartupScript(Page, this.GetType(), message, message, false);
        }
    }
}
public void copyPDF(string filePath)
{
    iTextSharp.text.pdf.RandomAccessFileOrArray ra = new iTextSharp.text.pdf.RandomAccessFileOrArray(Server.MapPath(ResolveUrl(filePath)));
    if (ra != null)
    {
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        byte[] password = System.Text.ASCIIEncoding.ASCII.GetBytes("Secretinfo");
        iTextSharp.text.pdf.PdfReader thepdfReader = new iTextSharp.text.pdf.PdfReader(ra, password);
        int pages = thepdfReader.NumberOfPages;
        iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document();
        iTextSharp.text.pdf.PdfCopy pdfCopy = new iTextSharp.text.pdf.PdfCopy(pdfDoc, ms);

        pdfDoc.Open();
        int i = 0;
        while (i < pages)
        {
            pdfCopy.AddPage(pdfCopy.GetImportedPage(thepdfReader, i + 1));
            i += 1;
        }
        pdfDoc.Close();
        Byte[] byteInfo = ms.ToArray();
        Response.Clear();
        Response.ContentType = "application/pdf";
        Response.AddHeader("content-length", byteInfo.Length.ToString());
        Response.BinaryWrite(byteInfo);
        Response.Flush();
        Response.End();
    }
}

My code has no problem opening pdf files without password but it can't open pdfs with password even though the password is supplied. The application executes the catch instead. What seems to be wrong with my code?

EDIT: I removed the Catch to see the exception thrown.

Exception Details: System.ArgumentException: PdfReader not opened with owner password

It says the source of the error is Line 51.

Line 49:    while (i < pages)
Line 50:    {
Line 51:         pdfCopy.AddPage(pdfCopy.GetImportedPage(thepdfReader, i + 1));
Line 52:         i += 1;
Line 53:    }
like image 934
Artemis Avatar asked Jul 16 '13 01:07

Artemis


1 Answers

For certain operations on encrypted documents iText(Sharp) requires that the document not merely is opened with the user password but instead with the owner password. This corresponds to the definition of these passwords in the PDF specification:

Whether additional operations shall be allowed on a decrypted document depends on which password (if any) was supplied when the document was opened and on any access restrictions that were specified when the document was created:

  • Opening the document with the correct owner password should allow full (owner) access to the document. This unlimited access includes the ability to change the document’s passwords and access permissions.
  • Opening the document with the correct user password (or opening a document with the default password) should allow additional operations to be performed according to the user access permissions specified in the document’s encryption dictionary.

(section 7.6.3.1 in ISO 32000-1)

iText(Sharp) currently does not check in detail the user access permissions specified in the document’s encryption dictionary but instead always requires the owner password for operations requiring certain permissions, and copying whole pages from a document definitively is one of them.

This been said, the iText(Sharp) developers are very much aware (due to many such questions asked)

  • that iText(Sharp) users may be entitled to execute such operations even without the owner password on account of the before mentioned user access permissions specified in the document’s encryption dictionary,
  • that there are myriad PDFs to which their respective owners applied an owner password (to prevent misuse by others) and then forgot it (or by using a randomly generated one never knew it to start with), and
  • that iText(Sharp) (being open source) can easily be patched by anyone not to respect the differences between user and owner password.

To allow users to do what they are entitled to and to prevent the spreading of patched copies of the library, iText(Sharp) contains an override for this test in the PdfReader class:

/**
 * The iText developers are not responsible if you decide to change the
 * value of this static parameter.
 * @since 5.0.2
 */
public static bool unethicalreading = false;

Thus, by setting

PdfReader.unethicalreading = true;

you globally override this permission checking mechanism.

Please respect the rights of PDF authors and only use this override if you indeed are entitled to execute the operations in question.

like image 118
mkl Avatar answered Sep 20 '22 12:09

mkl