mozilla / pdf.js

PDF Reader in JavaScript
https://mozilla.github.io/pdf.js/
Apache License 2.0
48.02k stars 9.93k forks source link

Digital signatures in pdf.js #1076

Closed soa-x closed 3 years ago

soa-x commented 12 years ago

Hi! We are interested about when or if you´re going to implement the Signature Data View (Xades, Pades & Cades) in the PDF viewer (PDF.js)

Kind Regards

Alejandro Pinedo, SOA-X

Herb-sh commented 5 years ago

Anyone knows any reliable workaround to this? Editing built files might only work locally or for testing purposes but no more than that.

xrkolovos commented 5 years ago

Is pdfjs a dead project? Why they don't implement for so many years the most wanted features??

image

KentuckyMC commented 5 years ago

I want to achieve that I can show a small notification somewhere in PDF.js that the digital signatures are not validated. I get that working on Chrome, but not on the other browsers. It's far from the best case, but we really want to show those signatures even if they're not 100% validated. I've tried to change the pdf.worker.js code at the piece where this.setFlags(AnnotationFlag.HIDDEN); stood. I've added a "document.getElementbyId" construction where I show my container when there is 1 or more signatures. But all the browsers (except chrome) don't recognize "document". Is there an option to add a property on the document or something, and use that in the viewer.js? There are more constructions with getElementbyId. Any help would be awesome.

rmhrisk commented 5 years ago

We recently wrapped our viewer that supports signature verification into a web component and iframe; you can find out more about how to use it here: https://verify.ink/

lexcorp commented 5 years ago

rmhrisk that’s great!!!

sxy9699 commented 4 years ago

@brianholle Thank you for your reply. I follow your example,but there was a problem in IE 11. The red chapter of digital signature obscures the text content. This is the effect on chrome. chrome pic This is the effect on IE11. ie11_pic I have the same question in IE, have you solved this?

yannisdran commented 4 years ago

Our organization is consisted by more than 2000 people. All of them are using Chrome, not Firefox because Firefox can't display PDFs' signatures correctly. I think this should be a priority for Mozilla.

PSpSynedra commented 4 years ago

@wolvz: Any progress on your side?

jstdoit commented 4 years ago

+1

zdravko61 commented 4 years ago

+1

lexcorp commented 4 years ago

We recently wrapped our viewer that supports signature verification into a web component and iframe; you can find out more about how to use it here: https://verify.ink/

@rmhrisk Ryan, have you considered opening a version of this visualizer to the community?

lexcorp commented 4 years ago

We have implemented a digital signature solution based on PKIjs and PDFjs that is capable of verifying and creating digital signatures. You can see an example of it viewing the US Digital Signature law here.

image

The viewer currently trusts the CAs on the eIDAS Trust List as well the Mozilla trusted S/MIME issuers.

If you encounter any issues email me at ryan@peculiarventures.com with sample files if any.

@rmhrisk Ryan, have you considered opening a version of this visualizer to the community?

rmhrisk commented 4 years ago

@lexcorp we made https:/verify.ink so you can easily embed our viewer was a web component.

Adding it is easy:

<html>
  <body>
    <verify-viewer  url="https://verify.ink/assets/documents/electronic_records_and_signatures_in_commerce.pdf"  show-signature-if-present="true"  notify-if-not-signed="true"  sign="true"  download="true"></verify-viewer><script type="module" src="https://verify.ink/webcomponent/index.js"></script>
    </body>
</html>

We recently added support for custom root stores also: https://verify.ink/guides#root-certificates

tuelle commented 4 years ago

From the various threads related do digital signatures, I got the impression that the main reason for the missing progress is that it is not able to verify signatures as a precondition for displaying them.

Would it make sense to distinguish the two use cases "Verify signature" and "Display signature"?

I think there are a lot of use cases where the display of even unverified signatures (if required with a warning added by the specific project team) is all that is required and sufficient. If this is already possible with minor modifications of the code, why isn't that an official functionality that can be switched on or off?

rmhrisk commented 4 years ago

The problem with displaying the signature if it is invalid is that you give users the impression it is valid.

Digital signatures, unlike their synthetic wet counterparts, are intended to denote both authenticity of a signature and the intent associated with it.

By displaying the signature image without validating it you are suggesting to the user it is authentic when it could be just a copy of an image.

tuelle commented 4 years ago

But not all valid digital signatures will have a visual representation in a PDF, right? PDF also allows to sign without a visual representation as far as I know.

Shouldn‘t the user of the library decide whether his application/use case allows display of valid/invalid signatures or if additional measures are required like warnings? One use case I have in mind is marking regions in PDFs while considering also signature regions. It can still be of an informative character although other tools are required for final validation. I don‘t see the disadvantage of offering display as an optional feature.

rmhrisk commented 4 years ago

But not all valid digital signatures will have a visual representation in a PDF, right? PDF also allows to sign without a visual representation as far as I know.

Both statements are correct 1) not all PDFs contain a visual representation (most do though). 2) PDF does allow a document wide signature. In this bug, however, what I have seen is interest in showing the visual signature associated with a digital signature and not a document wide signature.

There could be another bug to file for document wide signature support which has no visual representation but I do not recall a single request for this in any of the PDFjs related bugs that exist on digital signatures.

Shouldn‘t the user of the library decide whether his application/use case allows display of valid/invalid signatures or if additional measures are required like warnings? I personally believe an application developer should be able to choose to do whatever they want with their application.

However, there is also the question of what should a library like PDF.js choose to do also. In my opinion, exposing an option that is insecure, easily misunderstood, and will result in bad security outcomes for the ultimate end-user of the library is not something that library producers should make easy.

lexcorp commented 4 years ago

Imagine if this feature were complete it would have been of great help during this quarantine by COVID-19, imagine how many transactions, contracts, etc.

They could have been carried out from home, however I have witnessed that this functionality has been stagnant for years, I do not know the reason but I consider that in combination with other tools it could be of great help for collaborative work, home office, etc.

tuelle commented 4 years ago

I totally agree. Digital signatures will become more and more of great value in the coming years. My use case is a tool used in medical device development. Without digital signatures our daily work from home office would be really much more difficult. That’s the reason why I would leave it to the project using the library to find a trade-off between risks and customer value or to take additional measures that are appropriate for their specific use case.

Fabsky commented 4 years ago

I also totally agree that digital signature is indeed a big missing feature.

However, there is also the question of what should a library like PDF.js choose to do also. In my opinion, exposing an option that is insecure, easily misunderstood, and will result in bad security outcomes for the ultimate end-user of the library is not something that library producers should make easy.

The library is implemented by developers, which should be aware of security. On my part, if a I had the feature, I'll of course display the signature but also check & validate the signature server side so that I can show a warning if the signature is not valid.

Fabsky commented 4 years ago

@rmhrisk Do you plan to open source to community ? Because I don't have a single case where I could 1/ Allow docs to be available on internet 2/ Allow a third party to access docs 3/ Allow a 3rd party to inject javascript in user browser. That would be a great addition to pdfjs.

rmhrisk commented 4 years ago

@rmhrisk Do you plan to open source to community ? Because I don't have a single case where I could 1/ Allow docs to be available on internet 2/ Allow a third party to access docs 3/ Allow a 3rd party to inject javascript in user browser. That would be a great addition to pdfjs.

We open-source every libraries we used to create our viewer, and there is a lot of them and many are quite complicated; For example look at PKIjs piece that handles certificate validation for the viewer. We also offer commercial licenses with support.

We will not be open-sourcing the viewer, making this work took a significant amount of time and investment and that time has value. We are happy to support others in using the open-source libraries we created to make this possible though.

Re: 1; the viewer doesn't require docs to be on the internet.

Re: 2; the viewer doesn't require letting a third-party access the docs.

Re: 3; it is possible to host the web component so you can review and control updates to the component.

rmhrisk commented 4 years ago

I also totally agree that digital signature is indeed a big missing feature.

However, there is also the question of what should a library like PDF.js choose to do also. In my opinion, exposing an option that is insecure, easily misunderstood, and will result in bad security outcomes for the ultimate end-user of the library is not something that library producers should make easy.

The library is implemented by developers, which should be aware of security. On my part, if a I had the feature, I'll of course display the signature but also check & validate the signature server side so that I can show a warning if the signature is not valid.

"Should be" and "are" are two different things. Displaying the signature image when the signature is invalid or untrusted is a great example of the kind of decision someone might make without fully understanding the consequences.

rmhrisk commented 4 years ago

Imagine if this feature were complete it would have been of great help during this quarantine by COVID-19, imagine how many transactions, contracts, etc.

They could have been carried out from home, however I have witnessed that this functionality has been stagnant for years, I do not know the reason but I consider that in combination with other tools it could be of great help for collaborative work, home office, etc.

I totally agree this is why we created and open-sourced all the libraries that made our viewer possible. It is also why we let people use our viewer for free.

Thanks to the work we have done someone could certainly re-create the viewer work we did with far less effort and submit the associated PRs to PDFjs, we would even be happy to code review those PRs.

Epsiom commented 4 years ago

I need to display pdfs in my Angular CLI app, in a context where the validity of the signature isn't relevant, and the only important part is to have an accurate display. My test case was the sample pdf with a digital signature from Adobe. As I've tried many answers already, I will condense the results of my researchs below.

The most common answer I've seen is to comment the following lines in pdf.worker.js (lines 48353 to 48355):

if (data.fieldType === 'Sig') {
      //this.setFlags(AnnotationFlag.HIDDEN);
 }

This, however, didn't work.

Commenting the following lines in annotation.js directly in pdfjs-dist didn't work either (lines 285 to 287):

case 0:
        this.color = null;
        break;

This didn't work either, even though I didn't know how to place line of code given: (<any>window).pdfWorkerSrc = '<path_to_file>/pdf.worker.js';

I have tried to at least get the annotations in the page, but every page returned an empty array:

page.getAnnotations().then(function(annotations) {
     console.log('annotations loaded');
     console.log(annotations);
     for (let i = 0; i < annotations.length; i++) {
          console.log(annotations[i].subtype);
      }
 }, function (reason) {
     console.log(reason);
}); 

It is important for my app to display the pdf as is. At the very least, I would like to be able to get the bounding rectangles of the signature to display a placeholder in their stead. Could anybody help me ?

vlastimilmaca commented 4 years ago

I need to display pdfs in my Angular CLI app, in a context where the validity of the signature isn't relevant, and the only important part is to have an accurate display. My test case was the sample pdf with a digital signature from Adobe. As I've tried many answers already, I will condense the results of my researchs below.

Hi, I think you almost had it with your first try ... have you tried this https://github.com/mozilla/pdf.js/issues/1076#issuecomment-446959325 ?

Epsiom commented 4 years ago

I just tried it : nothing changed. Any other idea?

nick-keller commented 4 years ago

This issue has been opened for quite some time now, what is the current plan for tackling it, and how can we help?

Epsiom commented 4 years ago

If I cannot display the signature, at the very least, I would like to display a placeholder rectangle where it should be. (Simply knowing the x,y coordinates as well as the width and length of the signature)

Of course, displaying the signature would still be the best scenario (once again, I don't need to verify it in my specific use case).

PSpSynedra commented 4 years ago

Would it be an option to add a render option for displaying the unverified signatures? This way the users of pdf.js could decide if they want to take the risk of displaying them or not.

rmhrisk commented 4 years ago

Displaying a invalidated cryptographic signature is as bad as displaying one that is incorrectly validated: https://www.pdf-insecurity.org/

PSpSynedra commented 4 years ago

What if the signature has been validated correctly before by lets say a backend-service? This would mean that the signature was OK but still could not be displayed in a client-application.

A render option to display the signature or not would enable users of pdf.js to validate the signature somehow and then decide on their own to display it or not. It would also remove the burden from the developers of pdf.js developers to provide signature verification at all as this should probably not be part of pdf a rendering library. Strictly not displaying the signature at all limits the use-cases of pdf.js.

rmhrisk commented 4 years ago

What if the signature has been validated correctly before by lets say a backend-service? This would mean that the signature was OK but still could not be displayed in a client-application.

A render option to display the signature or not would enable users of pdf.js to validate the signature somehow and then decide on their own to display it or not. It would also remove the burden from the developers of pdf.js developers to provide signature verification at all as this should probably not be part of pdf a rendering library. Strictly not displaying the signature at all limits the use-cases of pdf.js.

Doing the validation between server and client is fine. Exposing a flag to display the signature as valid and validated would be a foot gun.

PSpSynedra commented 4 years ago

Doing the validation between server and client is fine. Exposing a flag to display the signature as valid and validated would be a foot gun.

We are dealing with verified signatures but cannot display them (without hacking) in the clients browser using pdf.js So what other option to render PDFs in the clients browser would you suggest to render the visual representation of the verified signature?

rmhrisk commented 4 years ago

You can patch your PDFjs prior to deployment to have whatever behavior you need?

PSpSynedra commented 4 years ago

That's what I meant by "hacking" and that's exactly what we are currently forced to do :-(

Epsiom commented 4 years ago

I don't see why we are still asking questions about the issue itself: the "hacks" didn't even work for me, and I'm still in the need.

In my use case, the validity of the signatures are not in question. However, I need to display them, or at least let the user know that there is "something there" instead of just that blank part of the canvas. I don't care if the API comes with a huge red warning paragraph about unverified signatures, or if it forces me legally to say it can't be verified, or if it warns me that it is at my own risks. ...I just need to display the signature.

At the very least, I'd really want to have the position and size of the signatures on the document, so that I can display a gray box in their place with "hey, user, there is supposed to be a signature there" written on them.

Currently, the user doesn't have the ability to know that the document is signed at this spot. Isn't that an even worse way of tempering?

Epsiom commented 4 years ago

If there was a boolean that allowed to display all digital signatures of the document as transparent gray template boxes, that would be satisfying enough, and that feature wouldn't raise any ethic/security problem.

(I'd also like to say that the problem has apparently been pending since 2012 with more than a hundred comment, in this thread alone. I don't think I am the only one waiting for this feature)

PSpSynedra commented 4 years ago

Gray boxes would rather seem like a rendering error and very likely overload a provided support-hotline :-) We have a working hack in place, that works fine for now but is admittedly very ugly:

  1. Download the current, transpiled and minified version of pdfjs-dist
  2. Patch the lines in question in the transpiled version.
  3. Release as new private package to internal npm-repo.
  4. Use patched package instead of original pdfjs-dist package.

Ugliy right? But it works and renders the embedded signatures just fine.

Epsiom commented 4 years ago

Gray boxes would rather seem like a rendering error and very likely overload a provided support-hotline :-)

Yes, yes, yes, I meant any template/image/message that could be complimented by *the pdf contains digital signatures that couldn't be verified, and as such, were not displayed. Anything that could be understood by the user if a message explained it.

  1. Patch the lines in question in the transpiled version.

I'm currently using Angular CLI with pdfjs-dist installed in my node_modules, but any solution that I've written a few posts ago didn't work on my side, and neither did this:

Hi, I think you almost had it with your first try ... have you tried this #1076 (comment) ?

Did I miss something, or is my case too specific for that fix?

PSpSynedra commented 4 years ago

We followed the explanation in this thread. https://github.com/mozilla/pdf.js/issues/4743#issuecomment-163953288

We basically changed this part:

// Hide unsupported Widget signatures.
if (data.fieldType === 'Sig') {
   warn('unimplemented annotation type: Widget signature');
   this.setFlags(AnnotationFlag.HIDDEN);
}

To this:

// Hide unsupported Widget signatures.
if (data.fieldType === 'Sig') {
   warn('unimplemented annotation type: Widget signature');
}

I know you could remove the whole 'if' but we wanted the smallest possible patch.

Epsiom commented 4 years ago

Yikes. That is indeed the fix that didn't work on my side. I'll try again when I go back to the pdf displaying part of my app. I didn't create my own package yet, but changing the file directly in node_modules/pdfjs-dist didn't change anything last time I tried.

PSpSynedra commented 4 years ago

Did you change both files pdf.worker.js and pdf.worker.min.js This was necessary in our approach.

Epsiom commented 4 years ago

Did you change both files pdf.worker.js and pdf.worker.min.js This was necessary in our approach.

You raise an excellent point that I may have overlooked ! I'll try that quickly today, and see if it works.

ll-priva commented 4 years ago

Hi I like your approach, but unfortunately it didnt work for me I changed the lines like this:

We followed the explanation in this thread. #4743 (comment)

We basically changed this part:

// Hide unsupported Widget signatures.
if (data.fieldType === 'Sig') {
   warn('unimplemented annotation type: Widget signature');
   this.setFlags(AnnotationFlag.HIDDEN);
}

To this:

// Hide unsupported Widget signatures.
if (data.fieldType === 'Sig') {
   warn('unimplemented annotation type: Widget signature');
}

I know you could remove the whole 'if' but we wanted the smallest possible patch.

Then I built it with gulp generic and used the built resources.

Did you change both files pdf.worker.js and pdf.worker.min.js This was necessary in our approach.

The pdf.worker.js was built but you mention pdf.worker.min.js, how is that built and where is it stored? What am I missing?

Thanks a lot in advance

PSpSynedra commented 4 years ago

@ll-priva We didn't build pdf.js ourselves. Like I said in Comment https://github.com/mozilla/pdf.js/issues/1076#issuecomment-658601553 we actually downloaded the already built version of pdfjs-dist and patched the bundled versions of pdf.worker.js and pdf.worker.min.js.

My explanation in https://github.com/mozilla/pdf.js/issues/1076#issuecomment-658609803 was probably a bit unclear, sorry. We implemented the described solution by patching the prebuilt package https://www.npmjs.com/package/pdfjs-dist. Then we used these patched versions of pdf.worker.js and pdf.worker.min.js to push a private pdfjs-dist package to our internal npm-repository. Last but not least we used this patched version in our production code instead of the official pdfjs-dist package.

I hope this makes our approach a bit clearer.

ll-priva commented 4 years ago

@PSpSynedra Thank you very much. That worked for me as well

Epsiom commented 4 years ago

I'm back on this task for the first time in a few weeks, but it still doesn't work on my side. I haven't made my own private package for the moment : as long as I didn't rebuild, modifying directly the files in node_modules\pdfjs-dist should have worked (locally, then I would have to indeed import the modified pdf.js as an asset or package).

Searching "Sig" in the folder gives 4 different file results :

I edited all of those 4 occurences to remove the content of the "if" which cleared the signature field and set a flag to hide it, as mentioned above. Nothing different happened : getAnnotations() returns an empty array, and the existing signatures are still not displayed.

I also still get this message in the console, which is not even an error or warn (pdf.worker.js:2965:14) :

Warning: Unimplemented widget field type "Sig", falling back to base field type.

By looking at the code, it means annotation.js wraps it in a "base" WidgetAnnotation, which means the message doesn't appear to be a problem, only the flags that I removed.

Am I missing something? I edited the min.js file as well as the js file, which are in the build folder and as such should be the ones used, so everything should have worked... What exactly did you do @ll-priva and @PSpSynedra ?

kjhangiani commented 4 years ago

@Epsiom this is what I just did, and it worked for me in about 5 minutes: https://github.com/mozilla/pdf.js/issues/1076#issuecomment-446959325

You need to both comment out the this.setFlags(AnnotationFlag.HIDDEN); as well as add data.fieldValue=null. The only file I modified was pdf.worker.js, which in our case is from the pdfjs-dist library so is minified already

konum commented 4 years ago

@Epsiom and others that may end up here. I had the same issue, edited pdf worker files to no result.

In my case I am using https://github.com/VadimDez/ng2-pdf-viewer to display pdf in an angular app. This module was directly loading pdf worker from cloudflare, not local file. So check if the web app is really using the modified pdf.worker.js file. You can check by clicking in the Unimplemented widget field type "Sig" warning in the console and move the mouse to the file name.