Bài viết kỹ thuật

Phân loại những gì thay đổi trong PDF sau khi được ký

Một chữ ký trên PDF không cấm các thay đổi về sau. Nó đóng băng một khoảng byte, và một cập nhật gia tăng nối các byte mới phía sau nó, nên chữ ký vẫn hợp lệ về mặt toán học trong khi tài liệu có thêm nội dung mới. Nội dung đó có được chấp nhận hay không là câu hỏi chính sách, và DocMDP là nơi tác giả tuyên bố chính sách: không thay đổi gì cả, chỉ điền biểu mẫu và ký, hoặc những cái đó cộng thêm chú thích. Thi hành nó nghĩa là phân loại cái thực sự đã thay đổi, và đó là việc AnalyzeModifications làm. Trỏ nó vào một bản sửa đổi trước, rồi đọc GetModificationLevel để có phán quyết tổng thể và các accessor từng phát hiện để biết cấp, số object và mô tả của mỗi khác biệt

Có sẵn thứ đó, thi hành DocMDP thu gọn thành một phép so sánh: cấp tính được có nằm ở hoặc dưới cấp mà chính sách cho phép hay không

Sơ đồ thang cấp sửa đổi của PDFlibPas từ mlNone đến mlUnclassified cho thấy thi hành chính sách DocMDP như một phép so sánh trong Delphi
Thang TPLModificationLevel chạy từ mlNone đến mlUnclassified, và thi hành DocMDP rút gọn thành việc so cấp tính được với chính sách

Vì sao một PDF đã ký được kỳ vọng là sẽ thay đổi

Ba trường hợp hợp pháp, và chúng phủ phần lớn những gì bạn sẽ gặp. Người ký thứ hai thêm chữ ký của họ. Người nhận điền các trường biểu mẫu mà tác giả để mở. Và vật liệu xác thực dài hạn được nối thêm: các phản hồi OCSP và CRL được ghi vào kho bảo mật tài liệu để chữ ký vẫn xác minh được sau khi các responder biến mất. Trường hợp cuối không chỉ được phép, nó chính là điều một kho lưu trữ quản lý tốt chủ đích làm với các tài liệu đã ký

Vậy "tệp lớn lên sau khi ký" không mang thông tin gì. Câu hỏi luôn luôn là cái gì đã được thêm, và câu trả lời phải đến từ việc so sánh các trạng thái tài liệu chứ không phải từ việc dõi từng byte. Cơ chế nối thêm tự thân được đề cập trong bài viết về cập nhật gia tăng

Phân loại theo hình dạng của object, không theo đường dẫn đã tạo ra nó

Bộ phân loại nhìn vào object là gì sau thay đổi, chứ không nhìn lệnh gọi thư viện nào đã tạo ra nó. Điều đó là có chủ đích, vì phân tích chạy trên các tệp do phần mềm khác tạo ra, nơi không có đường gọi nào để kiểm tra

Bốn hình dạng được nhận diện. Từ điển thông tin kho bảo mật tài liệu và thông tin liên quan xác thực, các object luồng tham chiếu chéo, mục metadata của catalog, và các từ điển chữ ký mang một khoảng byte là vật liệu lưu trữ dài hạn. Một object mang đồng thời kiểu trường và giá trị trường là điền biểu mẫu. Một object có kiểu là chú thích, hoặc có subtype nằm trong danh sách tại Bảng 168 của ISO 32000-2, là một thay đổi chú thích. Mọi thứ còn lại là unclassified

Cây quyết định PDFlibPas áp dụng cho từng object PDF đã thay đổi, xếp các cập nhật vào các cấp lưu trữ, điền biểu mẫu, chú thích hoặc unclassified
Mỗi object đã thay đổi được phân loại theo nó là gì — kho bảo mật, xref stream, trường, chú thích — chứ không theo lệnh gọi đã tạo ra nó

Các trường hợp bị xóa được đối xử nghiêm ngặt hơn các trường hợp thêm vào. Một object bị xóa chỉ được đưa vào danh sách trắng khi object phía cũ tự thân là vật liệu lưu trữ, điều này phủ trường hợp bình thường của một kho bảo mật được thay bằng cái mới hơn. Mọi lần xóa khác đều là unclassified, vì xóa nội dung khỏi một tài liệu đã ký không phải là điều một cấp quyền nào cho phép. Khác biệt ở cấp tài liệu còn nghiêm ngặt hơn nữa: thay đổi số trang đi thẳng đến unclassified mà không cần kiểm từng object, vì không cấp DocMDP nào cho phép thêm hay bớt trang

Danh sách trắng nghiêng về phía từ chối

Đây là quy tắc thiết kế chi phối mọi quyết định ranh giới. Một thay đổi bị phân loại sai thành được phép là một chữ ký xác thực trên nội dung mà tác giả chưa từng cho phép. Một thay đổi bị phân loại sai thành unclassified là một tài liệu bị gắn cờ và được một con người rà soát. Hai lỗi đó không đối xứng, nên danh sách trắng giữ hẹp và các hình dạng không nhận diện được rơi xuống unclassified thay vì bị đoán mò

Điều đó có một hệ quả thực tiễn đáng lường trước: các tệp từ những trình tạo khác thường sẽ thỉnh thoảng báo các thay đổi unclassified mà khi kiểm tra thì vô hại. Phản ứng đúng là nhìn vào chi tiết phát hiện và số object chứ không phải nới rộng danh sách trắng, vì một danh sách trắng lớn dần lên để làm im các báo cáo riêng lẻ thì ngừng là một kiểm soát an ninh

uses
  PDFlibrary, PDFlibCompare;

var
  Pdf: TPDFlib;
  I, Level: Integer;
begin
  Pdf := TPDFlib.Create(nil);
  try
    Pdf.LoadFromFile('contract-countersigned.pdf', '');
    if Pdf.AnalyzeModifications('contract-as-signed.pdf', '') < 0 then
      raise Exception.Create('the earlier revision could not be loaded');

    // TPLModificationLevel theo thứ tự mlNone, mlLTAUpdates, mlFormFilling,
    // mlAnnotations, mlUnclassified; getter trả về ordinal của nó
    Level := Pdf.GetModificationLevel;
    // Thi hành DocMDP giờ là một phép so sánh với chính sách
    if Level > Ord(mlFormFilling) then
      for I := 0 to Pdf.GetModificationFindingCount - 1 do
        Report.Add(Format('object %d, level %d: %s',
          [Pdf.GetModificationFindingObjNum(I),
           Pdf.GetModificationFindingLevel(I),
           Pdf.GetModificationFindingDetail(I)]));
  finally
    Pdf.Free;
  end;
end;

Cấp tổng thể là giá trị lớn nhất trên mọi phát hiện, cách tổng hợp duy nhất có thể bảo vệ được: một tài liệu chứa chín mươi chín lần thêm vật liệu lưu trữ và một thay đổi unclassified là một thay đổi unclassified

Bên dưới: vân tay, không phải hàm băm mật mã

Cỗ máy so sánh mà CompareWith phơi ra, và mà phân tích sửa đổi được dựng trên đó, nhận diện object bằng một vân tay của phần thân đã chuẩn hóa của chúng dùng một hàm băm 64-bit phi mật mã thay vì SHA-256. Đó là một lựa chọn đã được cân nhắc. Điều so sánh cấu trúc cần là tính xác định: cùng một phần thân object phải luôn sinh ra cùng một vân tay trong một lần chạy. Nó không cần khả năng chống va chạm, vì kẻ tấn công kiểm soát cả hai phía của phép so sánh đã thắng bằng phương tiện khác từ trước rồi, và việc trả giá cho một hàm băm mật mã đầy đủ trên mọi object trong một tài liệu triệu object là chi phí thật mà chẳng có lợi gì

Hai quy tắc chuẩn hóa quan trọng hơn lựa chọn hàm băm. Tham chiếu gián tiếp gập thành một token giữ chỗ thay vì được mở rộng thành nội dung được tham chiếu: mở rộng sẽ sao chép phần thân của một object dùng chung vào mọi nơi tham chiếu nó, nên một chỉnh sửa nhỏ lên một font descriptor dùng chung sẽ làm mất hiệu lực vân tay của mọi object chạm tới nó, và bản báo cáo sẽ không thể đọc nổi. Và bản thân các số object bị loại khỏi vân tay, vì một lần viết lại có thể đánh lại số thứ tự object mà không đổi gì về ngữ nghĩa

Việc khớp sau đó chạy trong hai lượt, căn theo vân tay trước và ghép phần còn lại theo số object để nhận diện thay đổi thay vì một lần thêm cộng một lần xóa. Các kiểm tra rẻ luôn đi trước suốt quá trình: khác biệt số trang được báo trước khi bất kỳ cuộc duyệt object nào bắt đầu

Diff bản sửa PDF hai lượt trong PDFlibPas: kiểm tra số trang trước, vân tay 64-bit, căn theo vân tay rồi ghép số object
Cỗ máy so sánh lấy vân tay phần thân object đã chuẩn hóa, báo khác biệt số trang trước, rồi khớp theo vân tay và số object

Một cái bẫy: so tài liệu với chính nó không bảo đảm cho kết quả giống hệt

Phép thử đầu tiên tự nhiên với một cỗ máy diff là so một tệp với chính nó và khẳng định kết quả giống hệt. Khẳng định đó không giữ đúng ở đây, và lý do rất đáng học. Con đường nạp công khai và con đường nạp tài liệu cấp thấp hơn không cấu hình giải mã giống hệt nhau, nên cùng một tệp nạp qua hai lộ trình có thể sinh ra các vân tay khác nhau với một số object. Cỗ máy không sai; hai lần nạp thực sự tạo ra các trạng thái trong bộ nhớ khác nhau

Thay vì ép hai con đường vào với nhau, ngữ nghĩa so sánh được tuyên bố hẹp: phân tích so trạng thái tài liệu hiện tại với một bản sửa đổi trước, và báo identical chỉ khi hai tập vân tay trùng khớp tuyệt đối. Đó là câu hỏi người dùng thực sự hỏi, và nó không đòi hỏi hai loader phải hoán đổi cho nhau được. Khi bạn thiết kế một tính năng so sánh, việc định nghĩa "giống nhau" nghĩa là gì chiếm nhiều công hơn cả việc tính ra nó

Dùng nó ở đâu

Hai nơi. Trong một báo cáo xác thực, cạnh phần kiểm tra chữ ký, để người rà soát thấy không chỉ chữ ký có nguyên vẹn về mặt mật mã hay không mà cả những gì xảy ra với tài liệu sau đó; phía chữ ký được đề cập trong ký và xác thực PAdES. Và trong một cổng tiếp nhận, nơi một tài liệu đến từ bên ngoài được đối chiếu với bản bạn đã gửi, để một hợp đồng trả về kèm chú thích thêm vào được đối xử khác với một bản có trang bị sửa

Một lưu ý về phạm vi. Phân tích này cho bạn biết cái gì đã thay đổi giữa hai bản sửa của cùng một dòng dõi tài liệu. Nó không cho biết nội dung hiển thị có gây hiểu lầm hay không, luồng hiển thị của một trường biểu mẫu có khớp với giá trị của nó hay không, hay văn bản bị giấu dưới một lớp phủ có còn hiện diện trong content stream hay không. Những cái đó cần xử lý riêng, và phía xóa nội dung được đề cập trong bài viết về redaction thực sự. Các điểm vào phân tích và so sánh được ghi tài liệu trên trang sản phẩm losLab PDF Developer Library