Jak zabezpieczyć i podpisać dokumenty PDF w TypeScript
Ten przewodnik pokazuje, jak szyfrować, certyfikować, podpisywać i weryfikować dokumenty PDF przy użyciu Aspose.PDF FOSS dla TypeScript. Document.Save() i Document.Open() obsługują szyfrowanie kluczem publicznym do certyfikatów odbiorcy, podczas gdy Document.Certify(), Document.Sign() i Document.VerifySignatures() obsługują cyfrowe podpisy w stylu PAdES. Wymaga Node.js 22 lub nowszego.
Przewodnik krok po kroku
Krok 1: Zainstaluj pakiet
git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-TypeScript.git
cd Aspose.PDF-FOSS-for-TypeScript
npm install
npm run buildZweryfikuj instalację, importując klasę Document w nowym pliku TypeScript — ta linia powinna zostać rozwiązana bez błędu po zainstalowaniu pakietu:
import { Document } from '@asposefoss/pdf';Krok 2: Importuj wymagane klasy
Importuj Document, aby otworzyć, zapisać, podpisać i zweryfikować plik; kroki podpisywania i szyfrowania poniżej przekazują zwykłe obiekty opcji, więc nie są potrzebne dodatkowe importy:
import { Document } from '@asposefoss/pdf';Krok 3: Szyfrowanie dokumentu przy użyciu certyfikatów odbiorcy
Document.Save() przyjmuje opcję encrypt zawierającą jeden lub więcej recipients, z których każdy jest identyfikowany certyfikatem (ciąg PEM lub bajty DER), algorithm oraz współdzielonym permissions:
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
},
});Krok 4: Otwórz zaszyfrowany dokument
Przekaż opcję recipient do Document.Open() z dopasowanym kluczem prywatnym i certyfikatem lub pakietem 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)
Krok 5: Certyfikuj i podpisz dokument
Document.Certify() i Document.Sign() są oba asynchroniczne i przyjmują tożsamość (certificate + privateKey) oraz opcje opisujące pole podpisu, wygląd i powód. Certyfikacja powinna odbywać się najpierw, na całym pliku; dalsze podpisy zatwierdzające są dodawane kolejno po tym:
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');
}Krok 6: Weryfikacja podpisów
Document.VerifySignatures() jest asynchroniczne i zwraca jeden SignatureReport na pole podpisu, każdy raportujący kryptograficzne integrity, ważność signature oraz czy 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}`);
}
}Typowe problemy i rozwiązania
Document.Sign() / Document.Certify() rzucać lub zawieszać. Oba są asynchroniczne — await wywołanie. Zapominając await pozostawia zwróconą obietnicę nierozwiązaną, a zapis odbywa się przed zakończeniem podpisywania.
Późniejszy podpis zatwierdzający unieważnia certyfikację. Podpisuj stopniowo: najpierw zapisz certyfikowane bajty (certifying.Save()), otwórz je ponownie przy użyciu Document.Open(), a następnie wywołaj Sign() w tym ponownie otwartym dokumencie — zapis pełnego przepisania zamiast przyrostowego dopisania psuje certyfikację /ByteRange skrótu.
VerifySignatures() reports coversWholeFile: false dla pierwszego podpisu, ale true dla ostatniego. Jest to oczekiwane w łańcuchu certyfikuj-następnie-podpisz: certyfikacja została podpisana przed dołączeniem zatwierdzenia, więc tylko najnowszy podpis /ByteRange rozciąga się do końca pliku.
Deszyfrowanie nie powodzi się przy prawidłowym kluczu prywatnym. Potwierdź certificate przekazany do recipient odpowiada dokładnemu certyfikatowi, do którego dokument został zaszyfrowany w Document.Save()’s recipients lista — certyfikat ponownie wydany z nową parą kluczy nie odszyfruje danych zaszyfrowanych przy użyciu starego.
Najczęściej zadawane pytania
Czy dokument może być zaszyfrowany dla więcej niż jednego odbiorcy?
Tak — recipients w opcji encrypt Document.Save() przyjmuje tablicę; dowolny prywatny klucz pasujący do odbiorcy może otworzyć powstały plik.
Jaki format podpisu generuje Document.Sign()?
Przekazanie subFilter: 'PAdES' w opcjach podpisu generuje podpis zgodny z PAdES; pominięcie go powoduje użycie domyślnego podfiltru podpisu biblioteki.
Jak sprawdzić, czy dokument jest certyfikowany, a nie tylko podpisany?
Sprawdź pole docMDP w SignatureReport zwróconym przez Document.VerifySignatures() — podpis certyfikujący zgłasza werdykt uprawnienia DocMDP; podpis jedynie zatwierdzający tego nie robi.
Czy odzyskane Permissions po Document.Open() są wymuszane przez bibliotekę?
Nie — opened.Permissions zgłasza flagi uprawnień zapisane w zaszyfrowanym pliku do wglądu; wymuszanie ich w aplikacji jest odpowiedzialnością wywołującego.