การอัปเดตแบบเพิ่มหน่วยและเหตุผลที่สำคัญ
ISO 32000-2 §7.5.6 Evidence: Standard-backed
ภาพรวมโดยสังเขป
หัวข้อที่มีชื่อว่า “ภาพรวมโดยสังเขป”เมื่อ PDF มีการเปลี่ยนแปลงหลังจากเขียนเสร็จแล้ว วิธีบันทึกที่ปลอดภัยคือไม่เขียนไฟล์ใหม่ทั้งหมด แต่จะ ต่อท้าย วัตถุที่เปลี่ยนแปลงและส่วน cross-reference ใหม่ไว้ที่ท้ายไฟล์แทน โดยปล่อยให้ไบต์เดิมทุกไบต์อยู่ที่ตำแหน่งเดิมทุกประการ หน้านี้อธิบายว่ากลไกนี้ทำงานอย่างไร และเหตุใดลายเซ็นดิจิทัลจึงยังคงอยู่ได้แม้มีการแก้ไขในภายหลัง
เหตุใดเรื่องนี้จึงสำคัญ
หัวข้อที่มีชื่อว่า “เหตุใดเรื่องนี้จึงสำคัญ”ลายเซ็นปกป้องช่วงไบต์หนึ่งช่วง หากการบันทึกการแก้ไขเพียงคำเดียวทำให้ต้องเขียนไฟล์ใหม่ ตำแหน่ง byte offset ทุกตำแหน่งก็จะเลื่อน ช่วงที่ถูกเซ็นจะไม่อธิบายเนื้อหาเดิมอีกต่อไป ลายเซ็นจะใช้การไม่ได้ แม้ว่าเนื้อหาที่ถูกเซ็นเองจะไม่ถูกแตะต้องก็ตาม
การอัปเดตแบบเพิ่มหน่วยมีไว้เพื่อป้องกันเหตุการณ์เช่นนั้น ไบต์เดิม รวมถึงไบต์ที่ลายเซ็นครอบคลุม จะคงอยู่ที่เดิม ผู้ตรวจสอบสามารถนำเอกสารที่ถูกเซ็นแล้วและมีการแก้ไขภายหลังมาตรวจสอบลายเซ็นแรกเทียบกับการแก้ไขฉบับดั้งเดิมได้ ผู้ตรวจสอบจะเห็นได้อย่างแม่นยำว่าสิ่งใดถูกเซ็น และเห็นแยกต่างหากว่าสิ่งใดเปลี่ยนแปลงไปในภายหลัง หากจัดการเรื่องนี้ผิดพลาด อาจทำให้ลายเซ็นที่ถูกต้องใช้การไม่ได้ หรือที่แย่กว่านั้นคือสูญเสียความสามารถในการพิสูจน์ว่าลายเซ็นนั้นรับรองสิ่งใดไว้จริง
ฉบับย่อ
หัวข้อที่มีชื่อว่า “ฉบับย่อ”- การอัปเดตแบบเพิ่มหน่วยจะ ต่อท้าย วัตถุที่เพิ่มใหม่และที่เปลี่ยนแปลง ตามด้วยส่วน cross-reference ใหม่และ trailer ใหม่ ทั้งหมดอยู่ที่ท้ายไฟล์
- เนื้อหาไฟล์เดิมจะ คงสภาพเดิมไว้ และไม่ถูกแก้ไขในตำแหน่งเดิม
- trailer ใหม่จะมีรายการ
/Prevซึ่งคือ byte offset ของส่วน cross-reference ก่อนหน้า ส่วนต่าง ๆ เหล่านี้ประกอบกันเป็นห่วงโซ่ที่ชี้ย้อนหลัง - โปรแกรมอ่านจะสร้างดัชนีโดยไล่ตามห่วงโซ่นั้นจากรายการใหม่ที่สุดก่อน สำหรับหมายเลขวัตถุใด ๆ รายการที่ ใหม่ที่สุด จะเป็นรายการที่ใช้
- เนื่องจากไม่มีสิ่งใดถูกเขียนทับ ช่วงไบต์ที่ลายเซ็นก่อนหน้าครอบคลุมจึงยังคงเหมือนเดิมแบบไบต์ต่อไบต์ ลายเซ็นจึงยังตรวจสอบผ่าน และสามารถกู้คืนเอกสารในสภาพเดียวกับตอนที่ถูกเซ็นได้อย่างแม่นยำ
NextPDF จัดการเรื่องนี้อย่างไร
หัวข้อที่มีชื่อว่า “NextPDF จัดการเรื่องนี้อย่างไร”NextPDF เขียนเอกสารฐานตามที่อธิบายไว้ในหน้าก่อนหน้า จากนั้นจึงเปิดเผยข้อมูลสามอย่างที่การอัปเดตแบบเพิ่มหน่วยต้องใช้
หลังจาก build() โปรแกรมเขียน (src/Writer/PdfWriter.php) จะเก็บสิ่งต่อไปนี้ไว้
- บัฟเฟอร์เอาต์พุตที่ดึงได้ผ่าน
getBuffer()เพื่อให้สามารถต่อท้ายการอัปเดตไว้ที่ตำแหน่งท้ายสุดของไบต์ที่มีอยู่ได้อย่างแม่นยำ - byte offset ของส่วน cross-reference ล่าสุด ผ่าน
getLastXrefOffset()ซึ่งจะกลายเป็นค่า/Prevของส่วนใหม่ - รายการใน catalog dictionary ผ่าน
getCatalogEntries()เพื่อให้การอัปเดตที่ต้องเขียน catalog ใหม่ (เช่น เพื่อแนบการอ้างอิงลายเซ็น) ไม่สูญเสียคีย์เดิมใด ๆ
การแก้ไขที่ถูกต่อท้ายจะจัดสรรหมายเลขวัตถุใหม่ (หรือนำหมายเลขเดิมกลับมาใช้สำหรับวัตถุที่แทนที่) โดยใช้ ObjectRegistry ตัวเดียวกัน การกำหนดหมายเลขวัตถุจึงสอดคล้องกันตลอดทุกการแก้ไข ส่วน cross-reference ใหม่จะแสดงรายการเฉพาะวัตถุที่การแก้ไขครั้งนี้แตะต้องเท่านั้น trailer ใหม่จะคงรายการจาก trailer ก่อนหน้าไว้ และเพิ่ม /Prev ที่ชี้ย้อนกลับไปยังส่วนก่อนหน้า ห่วงโซ่นี้คือสิ่งที่โปรแกรมอ่านไล่ตาม
ประเด็นนี้เห็นชัดที่สุดในการเซ็น NextPDF ใช้ ByteRangeCalculator (src/Security/Signature/ByteRangeCalculator.php) คำนวณอาร์เรย์ /ByteRange เป็นสองช่วง ได้แก่ทุกอย่างก่อนค่าลายเซ็นและทุกอย่างหลังค่าลายเซ็น ลายเซ็นจึงครอบคลุมการแก้ไขทั้งหมด ยกเว้นไบต์ของตัวลายเซ็นเอง เนื่องจากการแก้ไขในภายหลังถูกต่อท้ายแทนที่จะเขียนทับไบต์เหล่านั้น ช่วงดังกล่าวจึงไม่เคยเลื่อน
- Write base revision Header, body, xref section, trailer — the original bytes.
- Sign A /ByteRange digest covers the whole revision except the signature value itself.
- Edit and save Changed objects + a new xref section are appended; originals are untouched.
- New trailer chains back The appended trailer carries /Prev = offset of the previous xref section.
- Verify The first signature still covers the same unchanged bytes; the chain shows what came after.
หลักฐานบอกอะไรไว้บ้าง
หัวข้อที่มีชื่อว่า “หลักฐานบอกอะไรไว้บ้าง”กฎแบบต่อท้ายเท่านั้นเป็นข้อกำหนดเชิงบรรทัดฐาน Spec: ISO 32000-2, §7.5.6 ISO 32000-2 §7.5.6 ระบุว่าเนื้อหาของ PDF สามารถอัปเดตแบบเพิ่มหน่วยได้โดยไม่ต้องเขียนไฟล์ใหม่ทั้งหมด และเมื่อทำเช่นนั้น การเปลี่ยนแปลง ต้อง ถูกต่อท้ายไว้ที่ท้ายไฟล์ โดยปล่อยให้เนื้อหาเดิมคงสภาพไว้ Evidence: Standard-backed
ข้อกำหนดเดียวกันนี้นิยามกลไกการทำงานไว้ ส่วน cross-reference สำหรับการอัปเดตแบบเพิ่มหน่วยจะมีรายการเฉพาะวัตถุที่ถูกเปลี่ยนแปลง แทนที่ หรือลบเท่านั้น วัตถุที่ถูกลบจะยังคงอยู่ในไฟล์ แต่ถูกทำเครื่องหมายว่าลบแล้วผ่านรายการ cross-reference ของวัตถุนั้น trailer ที่ถูกเพิ่มเข้ามา ต้อง มีรายการ /Prev ที่ระบุตำแหน่งของส่วน cross-reference ก่อนหน้า รายการ cross-reference ของการอัปเดตสำหรับวัตถุที่เปลี่ยนแปลงจะมี byte offset ของสำเนา ใหม่ ซึ่งจะแทนที่ offset เดิม โปรแกรมอ่านจะสร้างข้อมูล cross-reference ขึ้นมาเพื่อให้เข้าถึงสำเนาล่าสุดของแต่ละวัตถุ
ผลที่เกิดกับลายเซ็นระบุไว้โดยตรงใน
Spec: ISO 32000-2, §12.8.1 ISO 32000-2 §12.8.1 กล่าวคือ ค่า digest ของช่วงไบต์
จะถูกคำนวณจากช่วงหนึ่งของไฟล์ ซึ่งโดยปกติคือทั้งไฟล์ ยกเว้น
ค่าลายเซ็น (รายการ /Contents) จากนั้นมาตรฐานระบุไว้ว่า
หากเอกสารที่ถูกเซ็นถูกแก้ไขและบันทึกด้วยการอัปเดตแบบเพิ่มหน่วย ข้อมูล
ที่สอดคล้องกับช่วงไบต์ของลายเซ็นดั้งเดิมจะถูกรักษาไว้ ดังนั้นหาก
ลายเซ็นนั้นถูกต้อง สถานะของเอกสาร ณ เวลาที่เซ็นก็สามารถ
สร้างขึ้นใหม่ได้ การต่อท้ายเท่านั้นไม่ใช่เพียงคุณสมบัติเสริมที่ดี แต่เป็นคุณสมบัติที่แบบจำลองลายเซ็น
ต้องพึ่งพา
ตัวอย่างเชิงปฏิบัติ
หัวข้อที่มีชื่อว่า “ตัวอย่างเชิงปฏิบัติ”เมื่อมอง PDF ที่ถูกเซ็นแล้วและแก้ไขภายหลังในเชิงโครงสร้าง การแก้ไขฉบับดั้งเดิมจะสิ้นสุดที่ %%EOF ของตัวเอง การแก้ไขครั้งที่สองถูกต่อท้ายไว้ด้านล่าง
%PDF-2.0... original objects, including the signature dictionary ...xref0 8... entries for the original revision ...trailer<< /Size 8 /Root 1 0 R >>startxref920%%EOF <-- end of revision 1: the signed bytes stop here9 0 obj <-- revision 2, appended<< /Type /Annot /Subtype /Text /Contents (added after signing) >>endobjxref0 19 0 obj-entry...8 90000001740 00000 ntrailer<< /Size 10 /Root 1 0 R /Prev 920 >>startxref1980%%EOFตัวตรวจสอบจะอ่าน trailer สุดท้าย เห็น /Prev 920 และจึงได้ห่วงโซ่ทั้งหมด ตัวตรวจสอบสามารถตรวจสอบลายเซ็นเทียบกับไบต์จนถึง %%EOF แรก ซึ่งไม่มีการเปลี่ยนแปลง จากนั้นจึงรายงานแยกต่างหากได้ว่าการแก้ไขครั้งที่ 2 เพิ่ม annotation เข้ามา ประวัติทั้งหมดอยู่ในไฟล์ ไม่มีสิ่งใดถูกซ่อนด้วยการเขียนทับ
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”ความเข้าใจผิดที่พบบ่อยคือ “การอัปเดตแบบเพิ่มหน่วยหมายความว่าการเปลี่ยนแปลงมีขนาดเล็ก จึงไม่เป็นอันตราย” การต่อท้ายเกี่ยวข้องกับ การรักษาไบต์ ไม่ใช่ขนาด การอัปเดตแบบเพิ่มหน่วยสามารถเพิ่มเนื้อหาได้เป็นจำนวนมาก สิ่งที่ทำให้เป็นการอัปเดตแบบเพิ่มหน่วยคือการไม่แตะต้องไบต์ที่มีอยู่แล้ว ผลที่ตามมาข้อนี้ทำให้หลายคนพลาดเช่นกัน เครื่องมือที่ “เพิ่มประสิทธิภาพ” หรือ “linearize” PDF ที่ถูกเซ็นโดยเขียนใหม่ตั้งแต่ต้นจะได้ไฟล์ที่เล็กลงและสะอาดขึ้น และลายเซ็นที่ใช้การไม่ได้ เพราะช่วงไบต์ที่ถูกเซ็นไม่มีอยู่อีกต่อไป การบันทึก PDF ที่ถูกเซ็นแล้วกับการบันทึกซ้ำไม่ใช่การดำเนินการเดียวกัน
ข้อจำกัดและขอบเขต
หัวข้อที่มีชื่อว่า “ข้อจำกัดและขอบเขต”การต่อท้ายเท่านั้นปกป้อง ไบต์ แต่การต่อท้ายเพียงลำพังไม่ได้บอกว่าการเปลี่ยนแปลงที่ต่อท้ายเข้ามานั้นได้รับ การอนุญาต หรือไม่ การแก้ไขครั้งที่สองอาจเพิ่มลายเซ็นที่สองอย่างถูกต้องตามกฎ หรืออาจเพิ่มเนื้อหาที่ผู้เซ็นรายแรกไม่เคยตั้งใจก็ได้ การตัดสินว่าเป็นกรณีใดเป็นหน้าที่ของการตรวจสอบลายเซ็นและนโยบายการตรวจจับการแก้ไข (DocMDP) การต่อท้ายเป็นรากฐานที่ทำให้การวิเคราะห์นั้น เป็นไปได้ ไม่ใช่ตัวการวิเคราะห์เอง
หน้านี้ยังไม่ครอบคลุมถึง วิธี คำนวณและประกอบช่วงไบต์สองช่วงของลายเซ็น และไม่ครอบคลุมถึงสิ่งที่การตรวจสอบฉบับสมบูรณ์ต้องตรวจ เรื่องเหล่านั้นเป็นหัวข้อแยกต่างหาก และการรับประกันในที่นี้เป็นเรื่องของไฟล์ที่เขียนและอัปเดตโดยโปรแกรมเขียนที่สอดคล้องกับมาตรฐาน ไฟล์ที่การแก้ไขก่อนหน้ามีรูปแบบผิดพลาดอยู่แล้วจะไม่กลายเป็นไฟล์ที่มีรูปแบบถูกต้องเพียงเพราะถูกต่อท้าย
คำถามที่พบบ่อยฉบับย่อ
หัวข้อที่มีชื่อว่า “คำถามที่พบบ่อยฉบับย่อ”จะรู้ได้อย่างไรว่า PDF มีการแก้ไขกี่ครั้ง นับเครื่องหมาย %%EOF และไล่ตามห่วงโซ่ /Prev จาก trailer สุดท้าย แต่ละส่วน cross-reference ที่ไล่ไปถึงคือการแก้ไขหนึ่งครั้งที่ถูกบันทึก
การลบวัตถุจะนำวัตถุนั้นออกจากไฟล์หรือไม่ ไม่ การอัปเดตแบบเพิ่มหน่วยจะทำเครื่องหมายว่าวัตถุถูกลบในรายการ cross-reference ของวัตถุนั้น แต่ไบต์ของวัตถุยังคงอยู่ในการแก้ไขก่อนหน้า “ลบ” หมายถึง “ไม่ถูกอ้างอิงโดยการแก้ไขปัจจุบัน” ไม่ใช่ “ถูกลบล้างทิ้ง”
การอัปเดตแบบเพิ่มหน่วยสามารถเปลี่ยนเวอร์ชัน PDF ได้หรือไม่ ได้ ด้วยการกำหนดรายการ /Version ใน catalog ในการแก้ไขที่ต่อท้าย ส่วนหัวจะคงสภาพเดิมตามที่เขียนไว้ /Version ใน catalog จะมีลำดับความสำคัญเหนือกว่าเมื่อระบุเวอร์ชันที่ใหม่กว่า
เอกสารที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “เอกสารที่เกี่ยวข้อง”- PDF คืออะไรกันแน่ โมเดลวัตถุและส่วน cross-reference เดียวที่การอัปเดตใช้ขยายต่อ
- ลายเซ็นอยู่ใน PDF อย่างไร กลไกช่วงไบต์ที่การอัปเดตแบบเพิ่มหน่วยมีไว้เพื่อปกป้อง
- การตรวจสอบลายเซ็นอย่างถูกต้อง สิ่งที่กระบวนการตรวจสอบที่ถูกต้องต้องตรวจตลอดประวัติการแก้ไขของไฟล์
อภิธานศัพท์
หัวข้อที่มีชื่อว่า “อภิธานศัพท์”- Incremental update (การอัปเดตแบบเพิ่มหน่วย) การบันทึกการเปลี่ยนแปลงด้วยการต่อท้ายวัตถุที่เปลี่ยนแปลง ส่วน cross-reference ใหม่ และ trailer ใหม่ไว้ที่ท้ายไฟล์ โดยไม่เปลี่ยนแปลงไบต์เดิมที่มีอยู่
/Prevรายการใน trailer (หรือ cross-reference stream) ที่เก็บ byte offset ของส่วน cross-reference ก่อนหน้า รายการนี้เชื่อมโยงการแก้ไขต่าง ๆ เข้าเป็นห่วงโซ่ที่ชี้ย้อนหลัง- Revision (การแก้ไข) สถานะของไฟล์ที่บันทึกไว้โดยส่วน cross-reference หนึ่งส่วนและ trailer ของส่วนนั้น ไฟล์ที่มีส่วน cross-reference จำนวน N ส่วนจะมีการแก้ไข N ครั้ง
/ByteRangeอาร์เรย์ใน signature dictionary ที่ระบุช่วงไบต์สองช่วงที่ digest ของลายเซ็นครอบคลุม (ทุกอย่างยกเว้นค่าลายเซ็นเอง)- Signed byte range (ช่วงไบต์ที่ถูกเซ็น) ไบต์ที่ digest ของลายเซ็นถูกคำนวณจากไบต์เหล่านั้นโดยตรง การอัปเดตแบบเพิ่มหน่วยมีไว้เพื่อให้ไบต์เหล่านี้ไม่เคยถูกย้ายหรือเขียนทับ