Documentation
Encryption
Protect a PDF with a password and jasy encrypts it with AES-256 (V5/R6, the newest handler in the PDF spec). It runs on the platform's WebCrypto, so there are no native dependencies and no Java - the same code encrypts in Node and right in the browser.
Set a password
Pass an encrypt option to renderToBytes (or renderPdf). A userPassword is all you need - any viewer
asks for it before it opens the document.
import { Document, Page, Text, renderToBytes } from "@jasy/pdf";
const doc = Document([Page([Text("Confidential")])]);
const bytes = await renderToBytes(doc, {
encrypt: { userPassword: "secret" },
});
Owner password and permissions
Add an ownerPassword for full rights, and permissions to allow or deny actions. The owner password
defaults to the user password when you leave it out, and every permission defaults to allowed.
const bytes = await renderToBytes(doc, {
encrypt: {
userPassword: "secret", // to open the document
ownerPassword: "owner", // full rights
permissions: {
printing: false, // disallow printing
copying: false, // disallow text/content extraction
modifying: true,
annotating: true,
},
},
});
Opening one
The other half: jasy reads encrypted PDFs too, which is what makes filling a protected form possible. Pass the password and everything downstream stays ordinary:
import { PdfDocument, fillForm } from "@jasy/pdf/edit";
const doc = await PdfDocument.open(bytes, { password: "secret" });
const { bytes: filled } = await fillForm(bytes, { name: "Ada" }, { password: "secret" });
Reading is broad, writing is narrow. jasy opens AES-256 (R6, R5), AES-128 (R4) and RC4 (R2/R3), because those files exist and you may have to open one. It writes only AES-256 R6: handing someone protection that is known to be broken is not a feature, so the legacy handler refuses to encrypt.
Worth knowing when you compare: PDFKit and react-pdf both default to 40-bit RC4 when you ask for a password, and neither can emit R6 at all. Ghostscript 10 refuses anything past R3.
The errors are named, never generic: no password, wrong password, or a revision jasy does not implement - three different things a caller can act on differently.
Good to know
- AES-256, R6. The current ISO 32000-2 handler - not the older revisions some libraries still ship.
- Pure JS, isomorphic. WebCrypto under the hood: no native crypto, zero extra dependencies, identical in Node and the browser.
- Vue and Nuxt too. In
@jasy/vuepass it as the third argument -renderToPdf(Doc, props, { encrypt: { userPassword: "secret" } }). In@jasy/nuxtuserenderOptions. - Not for PDF/A. PDF/A (and therefore ZUGFeRD / Factur-X invoices) forbids encryption, so encrypting one is rejected with a clear error.