Comment sécuriser et signer des documents PDF en TypeScript

Comment sécuriser et signer des documents PDF en TypeScript

Ce guide montre comment chiffrer, certifier, signer et vérifier des documents PDF avec Aspose.PDF FOSS pour TypeScript. Document.Save() et Document.Open() gèrent le chiffrement à clé publique vers les certificats des destinataires, tandis que Document.Certify(), Document.Sign() et Document.VerifySignatures() gèrent les signatures numériques de type PAdES. Il nécessite Node.js 22 ou une version ultérieure.

Guide étape par étape

Étape 1: Installer le paquet

git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-TypeScript.git
cd Aspose.PDF-FOSS-for-TypeScript
npm install
npm run build

Vérifiez l’installation en important la classe Document dans un nouveau fichier TypeScript — cette ligne devrait se résoudre sans erreur une fois le package installé:

import { Document } from '@asposefoss/pdf';

Étape 2: Importer les classes requises

Importez Document pour ouvrir, enregistrer, signer et vérifier le fichier; les étapes de signature et de chiffrement ci-dessous passent des objets d’options simples, donc aucun import supplémentaire n’est nécessaire :

import { Document } from '@asposefoss/pdf';

Étape 3: Chiffrer un document avec les certificats des destinataires

Document.Save() accepte une option encrypt contenant un ou plusieurs recipients, chacun identifié par un certificat (chaîne PEM ou octets DER), un algorithm, et des permissions partagés:

const doc = Document.OpenFile('report.pdf');

const bytes = doc.Save({
  encrypt: {
    recipients: [{ certificate: recipientCertPem }],
    algorithm: 'aes256', // 'aes256' (default) | 'aes128' | 'rc4'
    permissions: { copying: false }, // shared across all recipients
  },
});

Étape 4: Ouvrir un document chiffré

Passez une option recipient à Document.Open() avec soit la clé privée correspondante et le certificat, soit un paquet PKCS#12 :

const opened = Document.Open(bytes, {
  recipient: { privateKey, certificate: recipientCertPem },
  // or: recipient: { pkcs12: p12Bytes, passphrase: '…' },
});

console.log(opened.Permissions); // recovered permission flags (not enforced)

Étape 5: Certifier et signer un document

Document.Certify() et Document.Sign() sont tous deux asynchrones et prennent une identité (certificate + privateKey) ainsi que des options décrivant le champ de signature, l’apparence et le motif. La certification doit se faire en premier, sur l’ensemble du fichier; d’autres signatures d’approbation sont ajoutées de façon incrémentielle par la suite:

async function certifyAndSign(sourcePath: string, signaturePageIndex: number): Promise<void> {
  const certifying = Document.OpenFile(sourcePath);
  await certifying.Certify(
    { certificate: authorCert, privateKey: authorKey },
    {
      permissions: 'form-fill',
      reason: 'Certifying the document',
      fieldName: 'Certification',
      appearance: { page: signaturePageIndex, rect: [400, 100, 550, 140] },
    },
  );
  const certifiedBytes = certifying.Save();

  const approving = Document.Open(certifiedBytes);
  await approving.Sign(
    { certificate: approverCert, privateKey: approverKey },
    { reason: 'Approved for publication', fieldName: 'Approval', subFilter: 'PAdES' },
  );
  approving.WriteTo('signed.pdf');
}

Étape 6: Vérifier les signatures

Document.VerifySignatures() est asynchrone et renvoie un SignatureReport par champ de signature, chacun rapportant les integrity cryptographiques, la validité signature, et si elle coversWholeFile:

async function verify(path: string): Promise<void> {
  const doc = Document.OpenFile(path);
  const reports = await doc.VerifySignatures();
  for (const r of reports) {
    console.log(`${r.name}: integrity=${r.integrity} signature=${r.signature} `
      + `coversWholeFile=${r.coversWholeFile} docMDP=${r.docMDP}`);
  }
}

Problèmes courants et solutions

Document.Sign() / Document.Certify() throw ou hang. Les deux sont asynchrones — await l’appel. Oublier await laisse la promise retournée non résolue et l’écriture se produit avant que la signature ne se termine.

Une signature d’approbation ultérieure invalide la certification. Signer incrémentiellement : enregistrer d’abord les octets certifiés (certifying.Save()), les rouvrir avec Document.Open(), puis appeler Sign() sur ce document rouvert — écrire une réécriture complète au lieu d’un ajout incrémentiel rompt la certification /ByteRange empreinte.

VerifySignatures() reports coversWholeFile: false pour la première signature mais true pour la dernière. Ceci est attendu pour une chaîne certifier-puis-signer : la certification a été signée avant que l’approbation ne soit ajoutée, de sorte que seule celle de la signature la plus récente /ByteRange s’étend jusqu’à la fin du fichier.

Le déchiffrement échoue avec la bonne clé privée. Confirmez le certificate passé à recipient correspond exactement au certificat avec lequel le document a été chiffré dans Document.Save()’s recipients liste — un certificat réémis avec une nouvelle paire de clés ne déchiffrera pas les données chiffrées avec l’ancienne.

Foire aux questions

Un document peut-il être chiffré pour plus d’un destinataire?

Oui — recipients dans l’option encrypt de Document.Save() accepte un tableau; la clé privée correspondante de n’importe quel destinataire peut ouvrir le fichier résultant.

Quel format de signature Document.Sign() produit?

Passer subFilter: 'PAdES' dans les options de signature produit une signature compatible PAdES; l’omettre utilise le sous-filtre de signature par défaut de la bibliothèque.

Comment vérifier si un document est certifié ou simplement signé?

Inspectez le champ docMDP sur le SignatureReport renvoyé par Document.VerifySignatures() — une signature de certification indique un verdict de permission DocMDP; une signature d’approbation uniquement ne le fait pas.

Les Permissions récupérés après Document.Open() sont-ils appliqués par la bibliothèque?

Non — opened.Permissions rapporte les indicateurs de permission enregistrés dans le fichier chiffré pour inspection; leur application dans une application relève de la responsabilité de l’appelant.

Voir aussi

 Français