Để làm cho một tệp PDF đã ký có thể xác thực nhiều năm sau, sau khi chứng thư ký hết hạn và CA của nó luân chuyển, PDFium Component có thể tạo ra các chữ ký PAdES dài hạn trên Windows: một dấu thời gian RFC 3161 cho thời gian đáng tin cậy, một Kho Bảo mật Tài liệu (Document Security Store - DSS) nhúng tài liệu xác thực, và một dấu thời gian lưu trữ DocTimeStamp trên toàn bộ tệp tin. Ba thành phần bổ sung đó là các cấp độ cơ sở PAdES B-T, B-LT và B-LTA, và PDFium Component đạt được tất cả chúng chỉ từ một lệnh gọi ký duy nhất. Đây là khả năng chỉ dành cho Windows, được chốt giữ bởi PadesCryptoAvailable
Bài viết này là phần thứ ba trong loạt bài. Phần đầu tiên, ký tài liệu PDF bằng PAdES B-B sử dụng PDFium VCL, bao quát chữ ký cơ bản; phần thứ hai, kiểm tra chữ ký số PDF và các cấp độ PAdES, bao quát việc đọc ngược chữ ký và cho biết nó đạt đến cấp độ nào. Ở đây, mối quan tâm là lưu trữ: các chữ ký phải tồn tại qua thời hạn hết hạn chứng thư và giữ nguyên khả năng xác thực trong khoảng thời gian lưu giữ tính bằng năm, chứ không phải bằng tuần
Tại sao một chữ ký PDF hợp lệ lại ngừng xác thực theo thời gian?
Một chữ ký cơ bản chỉ trả lời một câu hỏi duy nhất: các byte dữ liệu này có bị thay đổi sau khi ký hay không. Bản thân nó không chứng minh được thời điểm việc ký diễn ra, và khoảng trống đó là thứ làm hỏng nó sau này. Cấu trúc CMS mang một thuộc tính thời gian ký (signing-time), nhưng người ký ghi giá trị đó từ đồng hồ của chính họ, vì vậy bộ xác thực không có lý do để tin cậy nó. Khi chứng thư ký hết hạn sau đó hoặc CA thu hồi nó, một bộ xác thực nghiêm ngặt không còn có thể phân biệt một chữ ký được thực hiện khi chứng thư còn hiệu lực với một chữ ký giả mạo sau khi nó đã mất hiệu lực. Chữ ký vẫn tốt vào ngày nó được tạo ra và trở thành không thể xác thực mà không có lỗi của chính nó
Lưu trữ dài hạn khắc phục điều này bằng hai bước đi. Thứ nhất, một bên thứ ba đáng tin cậy, một Tổ chức cấp dấu thời gian (Time Stamping Authority - TSA), xác nhận thời gian bằng mật mã để nó không còn phụ thuộc vào tính trung thực của người ký. Thứ hai, mọi chứng thư, phản hồi thu hồi và CRL cần thiết để xây dựng và kiểm tra chuỗi tin cậy đều được nhúng vào bên trong chính tệp PDF, giúp việc xác thực không phụ thuộc vào các máy chủ có thể đã biến mất tại thời điểm có ai đó xem xét. Tiêu chuẩn PAdES, được tiêu chuẩn hóa dưới dạng ETSI EN 319 142-1, phân lớp các yếu tố này thành các cấp độ cơ sở, và PDFium Component ghi lại các cấu trúc mà mỗi cấp độ yêu cầu
Chữ ký PDF LTV hoặc dấu thời gian lưu trữ là gì?
PAdES định nghĩa bốn cấp độ cơ sở xây dựng tiếp nối nhau, và PDFium Component phơi bày them qua kiểu liệt kê TPadesLevel (plB_B, plB_T, plB_LT, plB_LTA). B-B là chữ ký thuần túy. B-T thêm một dấu thời gian đáng tin cậy đè lên giá trị chữ ký. B-LT (dài hạn) thêm tài liệu xác thực được nhúng, đặc tính mà hầu hết mọi người ám chỉ khi nói "LTV". B-LTA (dài hạn với dấu thời gian lưu trữ) bao bọc mọi thứ trong một dấu thời gian nữa bao phủ toàn bộ tệp tin, giúp chính tài liệu được nhúng được chứng minh là nguyên vẹn kể từ thời điểm lưu trữ
Cách hiểu thực tế là một chiếc cầu thang. B-T chứng minh khi nào. B-LT chứng minh bằng cái gì chữ ký vẫn có thể được kiểm tra. B-LTA chứng minh toàn bộ gói tài liệu đã không bị can thiệp kể từ khi nó được niêm phong, và đó là cấp độ bạn gia hạn, bằng cách thêm một dấu thời gian DocTimeStamp mới trước khi dấu thời gian trước đó hết hạn, để kéo dài thời gian lưu trữ vô hạn. Đối với một hợp đồng hoặc một hồ sơ tuân thủ có nghĩa vụ lưu giữ dài hạn, B-LTA là mục tiêu; B-LT là mức sàn thực tế
Thêm thời gian đáng tin cậy: PAdES B-T với RFC 3161
Thành phần PDFium Component chuyển đổi một chữ ký B-B thành B-T bằng cách thiết lập hai trường trên TPadesSignOptions: nâng Level thành plB_T và cung cấp một TsaUrl. Khi cả hai hiện diện, đường ống ký sẽ băm các octet chữ ký thô bằng SHA-256, đóng gói dữ liệu băm đó thành RFC 3161 messageImprint, thực hiện gửi yêu cầu POST tới TSA qua WinHttp, và nhúng mã thông báo (token) trả về dưới dạng thuộc tính không ký signature-time-stamp (OID 1.2.840.113549.1.9.16.2.14) trong cấu trúc SignerInfo unsignedAttrs [1], tuân theo tiêu chuẩn EN 319 142-1 §6.3. Dấu thời gian bao phủ cụ thể giá trị chữ ký, đây là thứ liên kết thời gian đáng tin cậy vào chính chữ ký đó
uses
PDFium, FPdfPades;
procedure SignWithTimestamp;
var
Pdf: TPdf;
Options: TPadesSignOptions;
begin
Pdf := TPdf.Create(nil);
try
if not Pdf.PadesCryptoAvailable then
raise Exception.Create('PAdES signing backend is Windows-only');
Pdf.FileName := 'contract.pdf';
Pdf.Active := True;
Options := TPadesSignOptions.Default;
Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
Options.Level := plB_T;
Options.TsaUrl := 'http://timestamp.example-tsa.com/tsr';
Options.Reason := 'Contract execution';
// Nonce left at 0: the component derives a unique anti-replay value.
Pdf.SignPades('contract-bt.pdf', Options);
finally
Pdf.Free;
end;
end;
CertificateThumbprint là mã băm SHA-1, dưới dạng thập lục phân, của một chứng thư trong kho "MY" của Người dùng Hiện tại (Current User) có khóa riêng bạn có thể sử dụng. Trường Nonce là giá trị chống phát lại RFC 3161; hãy để nó bằng không và thành phần sẽ tự rút ra một giá trị duy nhất cho mỗi yêu cầu từ một phép gập SHA-256 của một bộ đếm, đồng hồ, số lượng tick và id tiến trình, để hai yêu cầu phát ra trong cùng một mili giây không bị va chạm. Chỉ truyền giá trị riêng của bạn khi bạn có một bộ tạo số ngẫu nhiên mật mã (RNG) mà bạn muốn tin cậy hơn. Một lưu ý thực tế: B-T cần một TSA có thể tiếp cận được, do đó việc ký số giờ đây sẽ thực hiện một cuộc gọi mạng và kế thừa tính khả dụng cùng độ trễ của dịch vụ TSA
Nhúng tài liệu xác thực: B-LT và B-LTA trong một lệnh gọi duy nhất
Bước tiến lên xác thực dài hạn là một thay đổi duy nhất: đặt Level thành plB_LTA và giữ nguyên TsaUrl. PDFium Component sau đó sẽ chạy toàn bộ các bậc thang bên trong một cuộc gọi SignPades duy nhất. Nó thực hiện ký B-B, đóng dấu thời gian cho B-T, tiêm Kho Bảo mật Tài liệu (DSS) cho B-LT, và thêm dấu thời gian lưu trữ cho B-LTA, mỗi bước là một bản cập nhật lũy tiến riêng biệt để các byte trước đó giữ nguyên vẹn từng byte
procedure SignForArchive;
var
Pdf: TPdf;
Options: TPadesSignOptions;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'contract.pdf';
Pdf.Active := True;
Options := TPadesSignOptions.Default;
Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
Options.Level := plB_LTA; // drives B-B -> B-T -> B-LT -> B-LTA
Options.TsaUrl := 'http://timestamp.example-tsa.com/tsr';
Options.Location := 'Head Office';
// One call writes the timestamp, the DSS and the archive DocTimeStamp.
Pdf.SignPades('contract-lta.pdf', Options);
finally
Pdf.Free;
end;
end;
Đối với giai đoạn B-LT, PDFium Component xây dựng chuỗi chứng thư bằng CertGetCertificateChain và ghi một từ điển /DSS mang chứng thư của người ký cộng với mọi CA trung gian trong một mảng /Certs (với các mảng /OCSPs and /CRLs song song), bên cạnh dấu hiệu /Extensions /ESIC ở Cấp độ 1, chính xác như EN 319 142-1 §5.4.2 quy định. Chứng thư gốc tự ký (self-signed root) được chủ ý bỏ qua, vì RFC 5652 §10.2.3 cho phép điều đó và chứng thư gốc đã là một mỏ neo tin cậy mà bộ xác thực nắm giữ. Kết quả thu được là một chữ ký mà người đọc có thể xác thực chỉ với tệp tin có trong tay
Đối với B-LTA, thành phần này thêm một Dấu thời gian tài liệu (Document Time-stamp): một từ điển chữ ký với /SubFilter /ETSI.RFC3161 có /ByteRange bao phủ toàn bộ tệp tin, /Contents của nó giữ một mã thông báo RFC 3161 trên phạm vi đó, và nó nâng cấp dấu hiệu ESIC lên Cấp độ 2. Đây là bước lưu trữ theo §5.4.3 và TS 119 142-3. Bởi vì dấu thời gian DocTimeStamp bao phủ cả cấu trúc DSS cũng như chữ ký, nó chứng minh tài liệu xác thực được nhúng đã hiện diện và không bị thay đổi tại thời điểm lưu trữ, đây chính xác là những gì một chính sách lưu trữ dài hạn bắt buộc phải hiển thị được
Bổ sung cho một chữ ký đã tồn tại
Đôi khi chữ ký đã có sẵn trên tài liệu và bạn chỉ cần thêm hoặc làm mới kho xác thực, ví dụ để nâng một chữ ký B-B của bên thứ ba lên B-LT cho mục đích lưu trữ của bạn. PDFium Component phơi bày bộ tiêm DSS trực tiếp thông qua SaveAsPadesDss, vốn sẽ thêm các cấu trúc /DSS và /Extensions dưới dạng một bản cập nhật lũy tiến mà không chạm tới các byte chữ ký hiện có
procedure AddValidationStore;
var
Pdf: TPdf;
DssOpts: TPadesDssOptions;
Cert: TPadesDssMaterial;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'already-signed.pdf';
Pdf.Active := True;
DssOpts := TPadesDssOptions.Default;
DssOpts.EsicExtensionLevel := 1; // 1 for B-LT, 2 for B-LTA
Cert.DerBytes := LoadSignerCertDer; // your DER-encoded certificate
SetLength(DssOpts.Certs, 1);
DssOpts.Certs[0] := Cert;
Pdf.SaveAsPadesDss('already-signed-lt.pdf', DssOpts);
finally
Pdf.Free;
end;
end;
Bạn cung cấp các chứng thư được mã hóa DER, và tùy chọn các phản hồi OCSP cùng CRL mà bộ xác thực sẽ cần. Đặt EsicExtensionLevel thành 1 cho kho lưu trữ B-LT hoặc 2 khi một DocTimeStamp sẽ tiếp nối. Hãy để IncludeVri ở giá trị mặc định là False: tiêu chuẩn EN 319 142-1 §5.4.2.3 coi từ điển /VRI cho mỗi chữ ký là tùy chọn và khuyên không nên dùng trừ khi một trình đọc cụ thể bạn hướng tới yêu cầu nó
Chi phí và ranh giới đáng để lập kế hoạch
Ba giới hạn thực tế định hình nơi các cấp độ này hoạt động phù hợp. Thứ nhất, phần mật mã bên dưới chỉ dành cho Windows: việc ký và đóng dấu thời gian đi qua các kho lưu trữ CNG và WinHttp của nền tảng, do đó PadesCryptoAvailable trả về False trên các nền tảng khác và SignPades sẽ báo lỗi. Việc kiểm tra phía đọc được bao trùm trong bài viết đi kèm vẫn giữ tính đa nền tảng; chỉ có việc ghi chữ ký là ràng buộc với Windows. Thứ hai, B-T và B-LTA phụ thuộc vào một Tổ chức cấp dấu thời gian, nghĩa là có một lượt truyền nhận qua mạng tại thời điểm ký và một dịch vụ bên ngoài có thời gian hoạt động (uptime) cùng giới hạn tần suất (rate limits) trở thành một phần trong đường dẫn ký của bạn
Thứ ba, mỗi cấp độ đều tiêu tốn dung lượng lưu trữ. Mỗi giai đoạn thêm một bản cập nhật lũy tiến thay vì viết lại tệp tin, cấu trúc DSS nhúng một chuỗi chứng thư đầy đủ, và dấu thời gian DocTimeStamp lưu trữ dự phòng không gian cho mã thông báo của nó, do đó một tệp B-LTA lớn hơn đáng kể so với tệp B-B gốc. Đó là sự đánh đổi có chủ ý: bạn chi tiêu các byte bây giờ để mua khả năng xác thực sau này. Đối với hầu hết các lưu trữ hợp đồng và tuân thủ, đó là sự đánh đổi đúng đắn, nhưng đáng để đo lường trên chính tài liệu của bạn thay vì giả định. Khi bạn cần xác nhận một tệp thành phẩm thực sự đạt đến cấp độ bạn mong muốn, hãy xác minh nó bằng các kỹ thuật trong bài viết kiểm tra chữ ký số PDF và các cấp độ PAdES, và nếu bạn đang tăng cường tính bảo mật của một đường ống tài liệu rộng hơn, các ghi chú về kiểm toán các rủi ro bảo mật PDF sẽ bao quát các phép kiểm tra xung quanh
Các tính năng ký PAdES, DSS và dấu thời gian lưu trữ hiển thị ở đây là một phần của PDFium Component dành cho Delphi và C++Builder, trang sản phẩm của nó mang đầy đủ tài liệu tham khảo ký số cùng các yêu cầu hệ thống