Skip to content

Commit

Permalink
📝 Updated README to reflect on the new structure
Browse files Browse the repository at this point in the history
  • Loading branch information
vbuch committed Oct 5, 2023
1 parent 96be0b1 commit 83590c9
Showing 1 changed file with 39 additions and 28 deletions.
67 changes: 39 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
# ![@signpdf](https://raw.githubusercontent.com/vbuch/node-signpdf/master/resources/logo-horizontal.svg?sanitize=true)

[![npm version](https://badge.fury.io/js/node-signpdf.svg)](https://badge.fury.io/js/node-signpdf)
[![Coverage Status](https://coveralls.io/repos/github/vbuch/node-signpdf/badge.svg?branch=master)](https://coveralls.io/github/vbuch/node-signpdf?branch=master)
[![Known Vulnerabilities](https://snyk.io/test/npm/node-signpdf/badge.svg)](https://snyk.io/test/npm/node-signpdf)
[![Donate to this project using Buy Me A Coffee](https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg)](https://buymeacoffee.com/vbuch)
![GitHub last commit](https://img.shields.io/github/last-commit/vbuch/node-signpdf?color=red)

Simple signing of PDFs in node.
A family of packages to make signing of PDFs simple in Node.js.

* [@signpdf](#signpdf)
* [Purpose](#purpose)
Expand All @@ -24,25 +18,29 @@ Simple signing of PDFs in node.

The main purpose of this package is **to demonstrate** the way signing can be achieved **in a piece of readable code** as it can take a lot of hours to figure out.

## Usage
## Packages

Install with `npm i -S node-signpdf node-forge`.
### [signpdf](./packages/signpdf)

In practice we expect that most people will just read through the code we've written in the testing part of this package and figure it out themselves. If that's your case, you should read the [[Signing PDF in simple steps]](#signing-pdf-in-simple-steps) section.
With the help of `node-forge` provides the actual cryptographic signing of a well-prepared PDF document. A PDF document is well-prepared if it has a signature placeholder - that is the e-signature aquivallent of the label "Signature:......." in your paper document. If your PDF does not have that, you may want to add one using one of our placeholder helpers (see the other packages).

### With pdfkit-created document
### [placeholder-pdfkit010](./packages/placeholder-pdfkit010)

You have already created a PDF using foliojs/pdfkit and you want to sign that. Before saving (writing to fs, or just converting to `Buffer`) your file, you need to a add a signature placeholder to it. We have a helper for that. This is demonstrated in [the `signs input PDF` test](./src/signpdf.test.js#L125).
Works on top of `PDFKit 0.10.0` and given a PDFDocument that is in the works, adds an e-signature placeholder. When the PDF is ready you can pass it to `@signpdf/signpdf` to complete the process.

Once you have the placeholder, just [[sign the document]](#sign-the-document).
### [placeholder-plain](./packages/placeholder-plain)

### With any PDF document
Uses the process and knowledge of adding e-signature placeholder from `placeholder-pdfkit010` but implements it with plain string operations (.indexOf(), .replace(), .match(), etc.). Because of the lack of semantics it is rather fragile. Additionally it doesn't support streams and only works on PDF version <= 1.3. Regardless of those disadvantages this helper seems to be the most popular among the users of @signpdf.

## Usage

Yes. This is new since version 1.0. We have a helper that can add a signature placeholder in at least the most basic PDFs without depending on pdfkit. You can see how this is done in [the `signs a ready pdf` test](./src/signpdf.test.js#L167).
When this repo was started we really wanted people to understand the signing flow. If that's your case, you should read the [[Signing PDF in simple steps]](#signing-pdf-in-simple-steps) section. If you are here with "Give me the code", you should maybe go to [our packages/examples](./packages/examples).

Once you have the placeholder, just [[sign the document]](#sign-the-document).
Depending on your usecase you may need different combinations of packages.

### Sign the document
### I am getting PDFs that already have placeholders

This is the most simple case of them all. You only need the signer. `$ npm i -S @signpdf/signpdf node-forge`. Then have a look at the [with-placeholder.js example](./packages/examples/with-placeholder.js). It should be as simple as:

```javascript
import signer from 'node-signpdf';
Expand All @@ -53,14 +51,19 @@ const signedPdf = signer.sign(
);
```

### I am generating a PDF with PDFKit

This is how the library was started as we needed to sign a document that we were generating on the fly. You will need `$ npm i -S @signpdf/signpdf @signpdf/placeholder-pdfkit010 node-forge` and a look at the [pdfkit010.js example](./packages/examples/pdfkit010.js).

### I have a .pdf file and I want to sign it

This seems to be the most common usecase - people work with PDF documents coming from different sources and they need to digitally sign them. The [placeholder-plain](#placeholder-plain) helper can help here. Start with `$ npm i -S @signpdf/signpdf @signpdf/placeholder-plain node-forge`. Head over to either [the JS example](./packages/examples/javascript.js) or [the TS one](./packages/examples/typescript.ts). And note that the process may look simple on the surface but it is very fragile inside. Should you need some help go stright to [our GitHub Issues](https://github.com/vbuch/node-signpdf/issues?q=is%3Aissue).

## Notes

* The process of signing a document is described in the [Digital Signatures in PDF](https://www.adobe.com/devnet-docs/etk_deprecated/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf) document. As Adobe's files are deprecated, [here is the standard as defined by ETSI](<https://ec.europa.eu/digital-building-blocks/wikis/display/DIGITAL/Standards+and+specifications#Standardsandspecifications-PAdES(PDFAdvancedElectronicSignature)BaselineProfile>).
* This lib:
* requires the [signature placeholder](#append-a-signature-placeholder) to already be in the document (There are helpers included that can try to add it);
* requires the `Contents` descriptor in the `Sig` be placed after the `ByteRange` one;
* takes `Buffer`s of the PDF and a P12 certificate to use when [signing](#generate-and-apply-signature);
* does cover only basic scenarios of signing a PDF. If you have suggestions, ideas or anything, please [CONTRIBUTE](#contributing);
* The @signpdf/signpdf lib requires the [signature placeholder](#append-a-signature-placeholder) to already be in the document. See the placeholder packages for assistance with that;
* We cover only basic scenarios of signing a PDF. If you have suggestions, ideas or anything, please [CONTRIBUTE](#contributing);
* Feel free to copy and paste any part of this code. See its defined [Purpose](#purpose).

## Signing PDF in simple steps
Expand All @@ -73,10 +76,10 @@ See the [unit-testing code](https://github.com/vbuch/node-signpdf/blob/master/sr

What's needed is a `Sig` element and a `Widget` that is also linked in a `Form`. The form needs to be referenced in the root descriptor of the PDF as well. A (hopefully) [readable sample](https://github.com/vbuch/node-signpdf/blob/master/src/helpers/pdfkitAddPlaceholder.js) is available in the helpers. Note the `Contents` descriptor of the `Sig` where zeros are placed that will later be replaced with the actual signature.

This package provides two [helpers](https://github.com/vbuch/node-signpdf/blob/master/src/helpers/index.js) for adding the signature placeholder:
This package provides two helpers for adding the signature placeholder:

* pdfkitAddPlaceholder
* plainAddPlaceholder
* [`@signpdf/placeholder-pdfkit010`](#placeholder-pdfkit010)
* [`@signpdf/placeholder-plain`](#placeholder-plain)

**Note:** Signing in detached mode makes the signature length independent of the PDF's content length, but it may still vary between different signing certificates. So every time you sign using the same P12 you will get the same length of the output signature, no matter the length of the signed content. It is safe to find out the actual signature length your certificate produces and use it to properly configure the placeholder length.

Expand All @@ -87,7 +90,8 @@ To produce PAdES compliant signatures, the ETSI Signature Dictionary SubFilter v
This can be declared using the subFilter option argument passed to `pdfkitAddPlaceholder` and `plainAddPlaceholder`.

```js
import { SUBFILTER_ETSI_CADES_DETACHED, pdfkitAddPlaceholder } from 'node-signpdf';
import { pdfkitAddPlaceholder } from '@signpdf/placeholder-pdfkit010';
import { SUBFILTER_ETSI_CADES_DETACHED } from '@signpdf/utils';

const pdfToSign = pdfkitAddPlaceholder({
...,
Expand All @@ -97,13 +101,20 @@ const pdfToSign = pdfkitAddPlaceholder({

### Generate and apply signature

That's where the Signer kicks in. Given a PDF and a P12 certificate a signature is generated in detached mode and is replaced in the placeholder. This is best demonstrated in [the tests](https://github.com/vbuch/node-signpdf/blob/master/src/signpdf.test.js#L122).
That's where the Signer kicks in. Given a PDF and a P12 certificate a signature is generated in detached mode and is replaced in the placeholder.

```js
import signer from '@signpdf/signpdf';

...
const signedPdf = signer.sign(pdfBuffer, certificateBuffer);
```

## Dependencies

[node-forge](https://github.com/digitalbazaar/forge) is used for working with signatures.

[PDFKit](https://github.com/foliojs/pdfkit) is used in the tests for generating a PDF with a signature placeholder.
[PDFKit](https://github.com/foliojs/pdfkit) is extensively used for generating PDFs with a signature placeholder and additionally its flows are used in `placeholder-plain`.

## Credits

Expand Down

0 comments on commit 83590c9

Please sign in to comment.