pdf-lib icon indicating copy to clipboard operation
pdf-lib copied to clipboard

Dev/doc encrypt

Open PhakornKiong opened this issue 4 years ago • 43 comments

Continuation of PR #917 & #243

Hope to get some advanced review on the PR as this is quite a significant addition,

What?

This PR add the feature for user to be able to Encrypt an unencrypted file.

Why?

Enables the encryption feature in this library

How?

On the branch, you can try it by using the scratchpad

yarn run scratchpad:start to start the build, then yarn scratchpad:run. It should create a new pdf in the root level. Then you can verify it.

  const pdfDoc = await PDFDocument.create();
  const existingPdfBytes = fs.readFileSync('test.pdf');
  const pdfDoc = await PDFDocument.load(existingPdfBytes);
  const page = pdfDoc.addPage();
  page.drawText('Creating PDFs in JavaScript is awesome!', {
    x: 50,
    y: 700,
  });

  pdfDoc.encrypt({
    userPassword: 'abcd',
    ownerPassword: '1234',
    permissions: { modifying: true },
  });

 // useObjectStreams true and false works
 // note on the following section on bugs on adobe acrobat reader
  const pdfBytes = await pdfDoc.save({ useObjectStreams: false });
  fs.writeFileSync('sample.pdf', pdfBytes);

Testing?

Manual testing by verifying the permission in PDF Reader application.

Added Integration test test19.ts and test20.ts in node

File should only be able to open and get decrypted in the PDF Reader if everything is implemented correctly.

Suggestions on testing is welcomed.

New Dependencies?

Crypto.js Saslprep

Both are famous public libraries.

Screenshots

N/A

Suggested Reading?

Yes

Anything Else?

There are 2 areas that I would need help with on this PR.

  1. How to verify that the build is working, as raised in #917

  2. Currently, there is a bug when using pdfDoc.save({ useObjectStreams: true }), the file is not able to be opened in Adobe Acrobat Reader, but works fine on browser and other PDF readers.

Checklist

  • [x] I read CONTRIBUTING.md.
  • [x] I read MAINTAINERSHIP.md#pull-requests.
  • [ ] I added/updated unit tests for my changes.
  • [x] I added/updated integration tests for my changes.
  • [x] I ran the integration tests.
  • [x] I tested my changes in Node, ~~Deno~~, and the ~~browser~~.
  • [x] I viewed documents produced with my changes in Adobe Acrobat, Foxit Reader, Firefox, and Chrome.
  • [ ] I added/updated doc comments for any new/modified public APIs.
  • [x] My changes work for both new and existing PDF files.
  • [x] I ran the linter on my changes.

PhakornKiong avatar Oct 03 '21 07:10 PhakornKiong

@PhakornKiong thanks for reopening this PR! It's pretty hefty, so it'll be awhile before I can look through all this.

Sidenote: If you'd like for folks to be able to use your work without waiting, you might consider making a separate library that people can pass a PDFDocument object to for encryption.

Hopding avatar Oct 31 '21 19:10 Hopding

@PhakornKiong thanks for reopening this PR! It's pretty hefty, so it'll be awhile before I can look through all this.

Sidenote: If you'd like for folks to be able to use your work without waiting, you might consider making a separate library that people can pass a PDFDocument object to for encryption.

No worries, take your time.

It would be difficult to spin off as a separate library as the change rely heavily on the pdfWriter to write the encrypted content into the file.

PhakornKiong avatar Nov 01 '21 08:11 PhakornKiong

This looks awesome; it would be great to see this pulled in and also the ability to decrypt pdfs =] (dealing with that now, trying to decide how to handle it)

taxilian avatar Dec 02 '21 05:12 taxilian

Hi, how can I use it in a browser environment? It seems that npm run build creates a dist compatible only with node In my case the inclusion of the saslprep library produced a few lines of code that point directly to the local filesystem to access code-point.mem Can you add some instruction on how to use this mod in standard web pages? Thanks and congratulations again for the excellent work done

cristianocaruso avatar Dec 28 '21 16:12 cristianocaruso

Hello,

I'm very interested by this one. Any chance to see this feature added in the near future ?

Thanks.

42retfa avatar Apr 06 '22 09:04 42retfa

Hey @Hopding @PhakornKiong, this feature is a great and i see how it could re written outside of pdf-lib so i can keep using the latest release without doing any refactoring in the future, but before i do is it going to be added in the near future? Not a problem at all just curious.

Lex-talionis avatar May 31 '22 09:05 Lex-talionis

Hey @Hopding @PhakornKiong, this feature is a great and i see how it could re written outside of pdf-lib so i can keep using the latest release without doing any refactoring in the future, but before i do is it going to be added in the near future? Not a problem at all just curious.

At this rate, i doubt it will be merge anytime soon. Might be a great solution to those that need this functionality.

How would you write it outside of pdf-lib ? (Just curious, since i relied heavily on the parser in pdf-lib)

PhakornKiong avatar May 31 '22 10:05 PhakornKiong

Hey @Hopding @PhakornKiong, this feature is a great and i see how it could re written outside of pdf-lib so i can keep using the latest release without doing any refactoring in the future, but before i do is it going to be added in the near future? Not a problem at all just curious.

At this rate, i doubt it will be merge anytime soon. Might be a great solution to those that need this functionality.

How would you write it outside of pdf-lib ? (Just curious, since i relied heavily on the parser in pdf-lib)

This idea is really more a guess. But a while back I found a solution on here to update spot colours in a pdf and has been expanded for other features. So using the research from your blog plus the pdf specification I'm thinking that might work.

Lex-talionis avatar May 31 '22 20:05 Lex-talionis

This would be incredibly useful for us. Any idea when it might get merged?

slegay avatar Jun 21 '22 13:06 slegay

Hi~ @PhakornKiong the PR code I use cannot be opened in the adobe reader after encrypting the pdf in my workplace, but it can be opened in other pdf readers (the browser can be opened)

JayceV552 avatar Oct 19 '22 06:10 JayceV552

This feature would be immensely useful. I'm voting to move forward with merging. Any ETA?

ryangriggs avatar Feb 13 '23 23:02 ryangriggs

@PhakornKiong What an incredible job!

Maybe, while this processes until merge, can you release your fork on npm?

Sharcoux avatar Apr 23 '23 01:04 Sharcoux

+1 for adding it in. Anybody from the repo bossmen available for a review? @MatheusHCP I see it was approved, could we merge it in? @PhakornKiong Some merge conflicts here, a small fix for man, a giant PDF encryption leap for all developer kind. Plz resolve.

peterpoliwoda avatar Apr 25 '23 18:04 peterpoliwoda

+1 for adding it in. Anybody from the repo bossmen available for a review? @MatheusHCP I see it was approved, could we merge it in? @PhakornKiong Some merge conflicts here, a small fix for man, a giant PDF encryption leap for all developer kind. Plz resolve.

Ok, let me do it this weekend.

PhakornKiong avatar Apr 25 '23 18:04 PhakornKiong

Thanks so much @PhakornKiong!

peterpoliwoda avatar Apr 25 '23 19:04 peterpoliwoda

This looks awesome; it would be great to see this pulled in and also the ability to decrypt pdfs =] (dealing with that now, trying to decide how to handle it)

decrypt is super helpful as well, any updates on this? thanks!

kenhosr avatar May 29 '23 15:05 kenhosr

@PhakornKiong I fork your repo and build, but error about fs founded, would u kindly tell me how to build correctly?

gonyulian415 avatar Jun 30 '23 10:06 gonyulian415

Would love to get this implemented. As of right now, there are not a lot of ways to encrypt an already existing pdf using node.

CBEngineer9 avatar Jul 15 '23 09:07 CBEngineer9

@PhakornKiong Still some merge conflicts 🥲. Or are there some new ones now? Let's get this party started please.

@gonyulian415 are you using the correct version of nodejs?

peterpoliwoda avatar Jul 15 '23 15:07 peterpoliwoda

Hey @peterpoliwoda, I faced 2 issues while building Phakorn's fork for browser.

  1. The fork uses crypto-js and saslprep. Rollup config bundles them too when building the umd or esm package via yarn build:esm or yarn build:umd.
  2. Even if you do not bundle crypto-js(as most browsers support it), saslprep has statements like const fs = require('fs') which throws errors in browser.

Can you guide me how to bundle the fork to make it work on browser?

Edit:

  1. Resolved above two by dropping crypto-js during build and including saslprep from https://github.com/foliojs/pdfkit/tree/master/lib/saslprep.
  2. Another error popped up, ReferenceError: Buffer is not defined which was quite easy to resolve.
npm install --save buffer

src/core/security/PDFSecurity.ts should be somewhat like this.

// import CryptoJS from 'crypto-js';
import { Buffer } from 'buffer';
import saslprep from './saslprep/index';

@gonyulian415 Please go through this once and let me know whether your issue is resolved or not

PROxZIMA avatar Aug 07 '23 12:08 PROxZIMA

Awesome! Well done sir!

peterpoliwoda avatar Aug 08 '23 06:08 peterpoliwoda

Hell

Awesome! Well done sir!

Hello, I want to ask this feature will be merge or still is review?

LLT9 avatar Aug 21 '23 08:08 LLT9

Closing this? So is there no hope for this to go in? What's happening?

peterpoliwoda avatar Aug 22 '23 07:08 peterpoliwoda

@peterpoliwoda I forced pushed and it automatically closed it, probably have to do with history

PhakornKiong avatar Aug 22 '23 07:08 PhakornKiong

Hi @PhakornKiong, with encryption enabled (ownerPassword and permissions only), document's metadata seems to be encrypted as well. Is this expected result or a bug?

Without Encryption With Encryption
image image

PROxZIMA avatar Aug 22 '23 08:08 PROxZIMA

Hi @PhakornKiong, with encryption enabled (ownerPassword and permissions only), document's metadata seems to be encrypted as well. Is this expected result or a bug?

Without Encryption With Encryption image image

I'm not 100% sure, would need to check the standard to verify.

What tools do you use to display this? Maybe i can take a peek

Left is unencrypted, middle is encrypted by ilovepdf, right is from the PR image

PhakornKiong avatar Aug 22 '23 08:08 PhakornKiong

What tools do you use to display this? Maybe i can take a peek

Simply viewing the pdf in MS Edge (chromium to be specific).

Left is unencrypted, middle is encrypted by ilovepdf, right is from the PR image

Both the images of the encrypted pdf are not showing the metadata.

Also from Adobe Acrobat Reader Untitled


Created a sample pdf usingjsPDF with ownerPassword and permissions only. The metadata is intact.

The more modern PDF encryption methods allow the file’s XMP metadata stream (XML Metadata) to be left unencrypted so it may be extracted and read by programs which don’t know how to open encrypted PDF files, or if the password is not known.^1

PROxZIMA avatar Aug 22 '23 10:08 PROxZIMA

I'm of the opinion that the default is to encrypt metadata. So probably i would not change this implementation here.

image

https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf

PhakornKiong avatar Aug 22 '23 11:08 PhakornKiong

The encryption is grate, however I’m facing the same issue as PROxZIMA ,metadata are also encrypted, and I can’t reset team by pdfDoc.setTitle(“”) (same as setAuthor, setSubject)

ccidcce32167 avatar Aug 23 '23 03:08 ccidcce32167

In most PDF encryption apps and libraries there is an option to enable/disable the encryption of document metadata. I would recommend adding this option so that the developer can choose to encrypt the metadata or leave as-is.

ryangriggs avatar Aug 23 '23 12:08 ryangriggs