Skip to content

Commit

Permalink
📝 Go through the main README one last time
Browse files Browse the repository at this point in the history
  • Loading branch information
vbuch committed Oct 6, 2023
1 parent 71bc0c1 commit 76f46b3
Showing 1 changed file with 36 additions and 28 deletions.
64 changes: 36 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
![GitHub last commit](https://img.shields.io/github/last-commit/vbuch/node-signpdf?color=red)
[![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)

`@signpdf` is a family of packages trying to make signing of PDFs simple in Node.js. Formerly known as [`node-signpdf`](https://www.npmjs.com/package/node-signpdf).
Formerly known as [`node-signpdf`](https://www.npmjs.com/package/node-signpdf) `@signpdf` is a family of packages trying to make signing of PDFs simple in Node.js.

* [@signpdf](#signpdf)
* [Purpose](#purpose)
Expand All @@ -16,7 +16,6 @@
* [Generate a PDF](#generate-a-pdf)
* [Append a signature placeholder](#append-a-signature-placeholder)
* [Generate and apply signature](#generate-and-apply-signature)
* [Dependencies](#dependencies)
* [Credits](#credits)
* [Contributing](#contributing)

Expand All @@ -32,7 +31,7 @@ Depending on your usecase you may need different combinations of packages.

### 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:
This is the most simple case of them all. `$ npm i -S @signpdf/signpdf @signpdf/signer-p12 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 signpdf from '@signpdf/signpdf';
Expand All @@ -44,56 +43,65 @@ const signedPdf = await signpdf.sign(fs.readFileSync(PATH_TO_PDF_FILE), signer);

### 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).
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 @signpdf/signer-p12 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).
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 @signpdf/signer-p12 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).

## Packages

### [signpdf](/packages/signpdf)
`@signpdf` is split into multiple packages. In the case where you are already working with the PDF-generating library PDFKit, this is the command you will start with once you want to start signing these documents: `$ npm i -S @signpdf/signpdf @signpdf/placeholder-pdfkit010 @signpdf/signer-p12 node-forge`. So what are all these packages and why do you need them?

### [@signpdf/signpdf](/packages/signpdf)

[![npm version](https://badge.fury.io/js/@signpdf%2Fsignpdf.svg)](https://badge.fury.io/js/@signpdf%2Fsignpdf)

Uses a Signer implementation (see the `@signpdf/signer-` packages) that provides cryptographic signing to sign 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 `@signpdf/placeholder-` packages).
This is the main package, the integrating one, the one that wraps everything up. It uses a [Signer](#signers) implementation that provides cryptographic signing to sign a well-prepared PDF document. A PDF document is well-prepared if it has a signature placeholder. If your PDF does not have that, you may want to add one using one of our [placeholder helpers](#placeholder-helpers).

### Signers

Signers are small libraries that `@signpdf/signpdf` will call with a PDF and they will know how to provide an e-signature in return. Their output is then fed as the signature in the resulting document.

### [signer-p12](./packages/signer-p12)
#### [@signpdf/signer-p12](./packages/signer-p12)

[![npm version](https://badge.fury.io/js/@signpdf%2Fsigner-p12.svg)](https://badge.fury.io/js/@signpdf%2Fsigner-p12)

With the help of `node-forge` provides the actual cryptographic signing of a Buffer using a P12 certificate bundle in detached mode as required for PDF.
With the help of its [peerDependency `node-forge`](#node-forge) the P12 signer provides the actual cryptographic signing of a Buffer using a P12 certificate bundle. This is done in detached mode as required for PDF.

### Placeholder helpers

A placeholder is the e-signature equivallent of the label "Sign here:......." in your paper document. They are a required part of the process of [Signing PDFs](#signing-pdf-in-simple-steps). Different projects acquire their PDFs differently so we try to support some helpers that know how to add e-signature placeholders.

### [placeholder-pdfkit010](/packages/placeholder-pdfkit010)
#### [@signpdf/placeholder-pdfkit010](/packages/placeholder-pdfkit010)

[![npm version](https://badge.fury.io/js/@signpdf%2Fplaceholder-pdfkit010.svg)](https://badge.fury.io/js/@signpdf%2Fplaceholder-pdfkit010)

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.
Works on top of `PDFKit 0.10.0` and given a `PDFDocument` that is in the works (*not yet ended*), adds an e-signature placeholder. When the placeholder is in place `@signpdf/signpdf` can complete the process.

### [placeholder-plain](/packages/placeholder-plain)
#### [@signpdf/placeholder-plain](/packages/placeholder-plain)

[![npm version](https://badge.fury.io/js/@signpdf%2Fplaceholder-plain.svg)](https://badge.fury.io/js/@signpdf%2Fplaceholder-plain)

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.
Uses the process and knowledge from `placeholder-pdfkit010` on how to add e-signature placeholder 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`. When the placeholder is in place `@signpdf/signpdf` can complete the process.

## 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>).
* 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

### Generate a PDF or read a ready one

We examples of PDFKit generation of documents and we also have some where a ready .pdf file is read. Browse through [our example](/packages/examples).
We have examples of PDFKit generation of documents and we also have some where a ready .pdf file is read. Browse through [our examples](/packages/examples).

### Append a signature placeholder

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](/packages/placeholder-pdfkit010/src/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.
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](/packages/placeholder-pdfkit010/src/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 for adding the signature placeholder:
We provides two helpers for adding the signature placeholder:

* [`@signpdf/placeholder-pdfkit010`](#placeholder-pdfkit010)
* [`@signpdf/placeholder-plain`](#placeholder-plain)
Expand All @@ -102,9 +110,7 @@ This package provides two helpers for adding the signature placeholder:

#### PAdES compliant signatures

To produce PAdES compliant signatures, the ETSI Signature Dictionary SubFilter value must be `ETSI.CAdES.detached` instead of the standard Adobe value.

This can be declared using the subFilter option argument passed to `pdfkitAddPlaceholder` and `plainAddPlaceholder`.
To produce PAdES compliant signatures, the ETSI Signature Dictionary SubFilter value must be `ETSI.CAdES.detached` instead of the standard Adobe value. This can be declared using the subFilter option argument passed to `pdfkitAddPlaceholder` and `plainAddPlaceholder`.

```js
import { pdfkitAddPlaceholder } from '@signpdf/placeholder-pdfkit010';
Expand All @@ -118,7 +124,7 @@ const pdfToSign = pdfkitAddPlaceholder({

### Generate and apply signature

That's where the Signer kicks in. Given a PDF and a signer implementation a signature is generated and replaced in the placeholder.
That's where the `@signpdf/signpdf` kicks in. Given a PDF and a [signer implementation](#signers) a signature is generated and replaced in the placeholder.

```js
import signpdf from '@signpdf/signpdf';
Expand All @@ -127,17 +133,19 @@ import signpdf from '@signpdf/signpdf';
const signedPdf = await signpdf.sign(pdfBuffer, signer);
```

## Dependencies
## Credits

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

[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`.
[node-forge](https://github.com/digitalbazaar/forge) is used for working with signatures. It is an awesome package written in pure JavaScript and [supports signing in detached mode](https://github.com/digitalbazaar/forge/pull/605). Many thanks to all the guys who wrote and maintain it.

## Credits
### PDFKit

[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`. Thanks to the guys of [PDFKit](https://github.com/foliojs/pdfkit) as they've made PDF generation incredibly easy.

### pdfsign.js

* The whole signing flow is a rework of what's already [in pdfsign.js](https://github.com/Communication-Systems-Group/pdfsign.js/blob/master/src/js/main.js#L594) so thanks go to [@tbocek](https://github.com/tbocek)
* [node-forge](https://github.com/digitalbazaar/forge) is an awesome package written in pure JavaScript and [supports signing in detached mode](https://github.com/digitalbazaar/forge/pull/605). Many thanks to all the guys who wrote and maintain it.
* Thanks to the guys of [PDFKit](https://github.com/foliojs/pdfkit) as well. They've made PDF generation incredibly easy.
The signing flow of `@signpdf/signpdf` and `@signpdf/signer-p12` is a rework of what was already [in pdfsign.js](https://github.com/Communication-Systems-Group/pdfsign.js/blob/master/src/js/main.js#L594) so thanks go to [@tbocek](https://github.com/tbocek).

## [Contributing](/CONTRIBUTING.md)

Expand Down

0 comments on commit 76f46b3

Please sign in to comment.