ข้ามไปยังเนื้อหา
getnextpdf.com

Enterprise รุ่น

Steganography — เอกสารอ้างอิงเชิงลึก

เอกสารอ้างอิงเชิงลึกนี้อธิบายช่องทาง steganographic ของ NextPDF Enterprise ช่องทางนี้ซ่อนเพย์โหลดที่เข้ารหัสไว้ภายในค่าปรับ kern เชิงตัวเลขของอาร์เรย์แสดงข้อความ TJ โดยมีสัญลักษณ์สาธารณะสี่รายการ ได้แก่ SteganographyEncoder SteganographyDecoder SteganographyConfig และ SteganographyCapacity ตัวเข้ารหัสจะสร้างคีย์ด้วย HKDF-SHA-256 เข้ารหัสเพย์โหลดด้วยไซเฟอร์ AEAD และคืนค่าออฟเซ็ต kern ตามแต่ละตำแหน่ง ส่วนตัวถอดรหัสจะย้อนกระบวนการจากค่าปรับที่สังเกตได้หรือจากคอนเทนต์สตรีมดิบ

ช่องทางนี้ออกแบบมาเพื่อการติดตามการรั่วไหลของเอกสารภายใน ไม่ใช่ steganography ระดับต้านทานผู้ประสงค์ร้าย ข้อมูลที่เข้ารหัสอาจถูกทำลายได้จากการพิมพ์แล้วสแกน การแปลง PDF การทำ re-linearization การเขียนคอนเทนต์สตรีมใหม่ หรือการดำเนินการใดๆ ที่ทำให้ kerning เป็นมาตรฐาน NextPDF ไม่ได้ถือครองการรับรองใดๆ สำหรับช่องทางนี้และไม่ได้มอบการรับรองใด หน้านี้ระบุความสามารถ ไม่ใช่ความสอดคล้องตามมาตรฐาน

ความสามารถนี้มาพร้อมกับ NextPDF Enterprise (nextpdf/enterprise) และเปิดใช้งานด้วยซองไลเซนส์ระดับ Enterprise การนำไปใช้งานที่ไม่มีสิทธิ์ดังกล่าวจะไม่โหลดคลาสของความสามารถนี้ เปรียบเทียบรุ่นและรับไลเซนส์

ช่องทางนี้เปิดเผยคลาส final สี่คลาส จุดเข้าใช้งานทั้งหมดเป็น public static ยกเว้นคอนสตรัคเตอร์ของ SteganographyConfig และแอ็กเซสเซอร์ effectiveMaxOffset ของมัน คลาสสนับสนุน NextPDF\Enterprise\Security\Steganography\SteganographyEncryptionException จะถูกโยนโดยตัวเข้ารหัส ซึ่งไม่ใช่ชนิดที่ผู้เรียกสร้างขึ้นเอง

สัญลักษณ์พารามิเตอร์พฤติกรรมเริ่มต้นคืนค่าโยนหรือล้มเหลวด้วยหมายเหตุ
SteganographyEncoder::encode$payload, $text, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig)$payload ที่ว่างเปล่าจะคืนค่า [] ตรวจสอบความแข็งแรงของคีย์ เข้ารหัส คำนวณออฟเซ็ต kern ตามแต่ละตำแหน่งarray<int, float> (ตำแหน่ง => ค่าปรับหน่วย 1/1000 em ตามแบบแผน AFM)InvalidArgumentException (คีย์ต่ำกว่าขั้นต่ำ) OverflowException (ข้อความน้อยกว่า 2 อักขระ หรือเพย์โหลดเกินความจุ) SteganographyEncryptionException (AEAD ล้มเหลว)ส่งผลลัพธ์ต่อไปยัง NextPDF\Content\TextRenderer::buildTjArrayOperator() API จะคืนค่าปรับตามแบบแผน AFM ส่วน buildTjArrayOperator() จะทำการแปลงตัวเลข TJ ของ PDF (ISO 32000-2 ลบตัวเลขออกจากตำแหน่งปัจจุบัน) ผู้ที่เขียนคอนเทนต์สตรีมด้วยตนเองต้องรักษาแบบแผนเครื่องหมายดังกล่าวไว้
SteganographyEncoder::assertSecretKeyStrength$secretKeyปฏิเสธคีย์ที่สั้นกว่าขั้นต่ำvoidInvalidArgumentException (คีย์ต่ำกว่าขั้นต่ำ)การป้องกันที่ใช้ร่วมกันบนเส้นทางเขียน สะท้อนบนเส้นทางอ่านด้วย
SteganographyEncoder::MIN_SECRET_KEY_LENGTHค่าคงที่ค่าขั้นต่ำความยาวคีย์ 128 บิต หน่วยเป็นไบต์int (16)ไม่เกี่ยวข้องไลบรารีบังคับความยาว ไม่ใช่เอนโทรปี
SteganographyDecoder::decode$observedAdjustments, $text, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig)ตรวจสอบความแข็งแรงของคีย์ ควอนไทซ์ค่าเบี่ยงเบน สร้างบล็อบขึ้นใหม่ ถอดรหัสแบบ AEAD`stringnull(เพย์โหลด หรือnull` เมื่อคีย์ผิดหรือไม่มีเพย์โหลด)InvalidArgumentException (คีย์ต่ำกว่าขั้นต่ำ)
SteganographyDecoder::decodeFromContentStream$contentStream, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig)แปลงสตรีมเป็นโทเคน สร้างข้อความและค่าปรับขึ้นใหม่จากอาร์เรย์ TJ แล้วมอบหมายต่อให้ decode`stringnull(เพย์โหลด หรือnullเมื่อไม่มีข้อความTJ` หรือการถอดรหัสล้มเหลว)InvalidArgumentException (คีย์ต่ำกว่าขั้นต่ำ ผ่าน decode)
SteganographyConfig::__construct$bitDepth, $maxAdjustmentEmRatio, $cipher, $requirePdfACompatibilityตรวจสอบโดเมนของอาร์กิวเมนต์แต่ละตัว สร้างออบเจ็กต์ค่าที่ไม่เปลี่ยนแปลงอินสแตนซ์ SteganographyConfigInvalidArgumentException ($bitDepth, $maxAdjustmentEmRatio หรือ $cipher ไม่ถูกต้อง)คลาส readonly อาร์กิวเมนต์ทั้งสี่เป็นพรอเพอร์ตี้แบบ public promoted
SteganographyConfig::effectiveMaxOffsetไม่มีคืนค่า $maxAdjustmentEmRatio * 1000 โดยลดลงครึ่งหนึ่งเมื่อมีการร้องขอความเข้ากันได้กับ PDF/Afloat (ออฟเซ็ตหน่วย 1/1000 em)ไม่เกี่ยวข้องการลดลงครึ่งหนึ่งช่วยลดความเสี่ยงในการตรวจพบความไม่ตรงกันของความกว้าง
SteganographyConfig::CRYPTO_OVERHEADค่าคงที่ค่าโสหุ้ยการเข้ารหัสคงที่ต่อเพย์โหลด หน่วยเป็นไบต์int (32)ไม่เกี่ยวข้องความยาว 4 ไบต์ nonce 12 ไบต์ แท็ก 16 ไบต์
SteganographyCapacity::calculate$text, $config (SteganographyConfig)คำนวณจำนวนไบต์เพย์โหลดที่ใช้ได้สำหรับข้อความ หลังหักค่าโสหุ้ยint (0 เมื่อข้อความสั้นเกินไป)ไม่เกี่ยวข้องความจุคือ positions * bitDepth / 8 ลบด้วยค่าโสหุ้ย
SteganographyCapacity::minimumTextLength$payloadBytes, $config (SteganographyConfig)คำนวณจำนวนอักขระ UTF-8 ขั้นต่ำสำหรับเพย์โหลดint (จำนวนอักขระ)ไม่เกี่ยวข้องส่วนกลับของ calculate

ลายเซ็นแบบต้นฉบับตามด้านล่างนี้ พร้อมที่มาของซอร์สแต่ละรายการ

public static function encode(
string $payload,
string $text,
string $fontKey,
FontMetrics $metrics,
string $secretKey,
SteganographyConfig $config = new SteganographyConfig(),
): array
public static function assertSecretKeyStrength(string $secretKey): void
public const int MIN_SECRET_KEY_LENGTH = 16;
public static function decode(
array $observedAdjustments,
string $text,
string $fontKey,
FontMetrics $metrics,
string $secretKey,
SteganographyConfig $config = new SteganographyConfig(),
): ?string
public static function decodeFromContentStream(
string $contentStream,
string $fontKey,
FontMetrics $metrics,
string $secretKey,
SteganographyConfig $config = new SteganographyConfig(),
): ?string
public function __construct(
public int $bitDepth = 1,
public float $maxAdjustmentEmRatio = 0.02,
public string $cipher = 'aes-256-gcm',
public bool $requirePdfACompatibility = false,
)
public function effectiveMaxOffset(): float
public const int CRYPTO_OVERHEAD = 32;
public static function calculate(
string $text,
SteganographyConfig $config = new SteganographyConfig(),
): int
public static function minimumTextLength(
int $payloadBytes,
SteganographyConfig $config = new SteganographyConfig(),
): int

ตัวเข้ารหัสจะแยก $text ออกเป็นอักขระ UTF-8 และสร้างหนึ่งตำแหน่งต่อคู่อักขระที่ติดกัน แต่ละตำแหน่งบรรจุ $config->bitDepth บิต ซึ่งเป็นหนึ่งหรือสอง เพย์โหลดจะถูกเข้ารหัสก่อน จากนั้นซีเรียลไลซ์เป็นบล็อบ แล้วแปลงเป็นลำดับบิต แต่ละตำแหน่งจะเข้ารหัสบิตของมันเป็นออฟเซ็ตขนาดเล็กที่ไม่เป็นลบ ซึ่งบวกเข้ากับค่า kern ธรรมชาติของคู่อักขระนั้น

ออฟเซ็ตเป็นเศษส่วนของออฟเซ็ตสูงสุดที่มีผล ออฟเซ็ตสูงสุดที่มีผลคือ $maxAdjustmentEmRatio * 1000 หน่วยออกแบบ โดยลดลงครึ่งหนึ่งเมื่อ $requirePdfACompatibility เป็นจริง ค่า kern ธรรมชาติอ่านมาจาก $metrics ผ่าน FontMetrics::getKernPair แมปที่คืนค่ามีลักษณะเบาบาง ตำแหน่งที่มีค่าปรับสุดท้ายเป็นศูนย์พอดีจะถูกละไว้

การเข้ารหัสใช้ HKDF-SHA-256 เพื่อสร้างคีย์ขนาด 32 ไบต์ ซอลต์ของ HKDF คือ $fontKey ที่ไม่เป็นความลับ และป้ายกำกับ info เป็นค่าคงที่ตายตัว ดังนั้น $secretKey ของผู้เรียกจึงเป็นขอบเขตความลับเพียงอย่างเดียว ไซเฟอร์ AEAD คือ aes-256-gcm หรือ chacha20-poly1305 เลือกโดย $config->cipher ทำงานผ่าน openssl_encrypt ด้วย nonce ใหม่ขนาด 12 ไบต์ และแท็กขนาด 16 ไบต์ บล็อบที่ซีเรียลไลซ์ประกอบด้วยความยาวแบบ big-endian 4 ไบต์ nonce 12 ไบต์ ไซเฟอร์เท็กซ์ และแท็ก 16 ไบต์ ค่าโสหุ้ยคงที่นี้คือ CRYPTO_OVERHEAD ซึ่งเท่ากับ 32 ไบต์

ตัวถอดรหัสจะย้อนการแปลงกลับ โดยคำนวณค่าเบี่ยงเบนของค่าปรับที่สังเกตได้แต่ละค่าจากค่า kern ธรรมชาติ ทำให้เป็นบรรทัดฐานด้วยออฟเซ็ตสูงสุดที่มีผล และควอนไทซ์ไปยังระดับที่ใกล้ที่สุด จากนั้นประกอบบล็อบขึ้นใหม่ ตรวจสอบส่วนหัวความยาว และเรียก openssl_decrypt คีย์ที่ผิด เพย์โหลดที่หายไป หรือค่าปรับที่เสียหายจะทำให้การยืนยันตัวตนของ AEAD ล้มเหลว และตัวถอดรหัสจะคืนค่า null decodeFromContentStream จะแปลงสตรีมดิบเป็นโทเคนก่อนด้วย NextPDF\Pro\Projection\ContentProjectionWriter::tokenize สร้างข้อความและค่าปรับเชิงตัวเลขขึ้นใหม่จากอาร์เรย์ TJ แต่ละชุด แล้วจึงมอบหมายต่อให้ decode

SteganographyCapacity::calculate จะรายงานขนาดเพย์โหลดที่ใช้ได้สำหรับข้อความและการกำหนดค่าหนึ่งๆ หลังหัก CRYPTO_OVERHEAD และคืนค่าศูนย์เมื่อข้อความสั้นเกินไป SteganographyCapacity::minimumTextLength เป็นส่วนกลับ คือจำนวนอักขระ UTF-8 น้อยที่สุดที่รองรับเพย์โหลดขนาดที่ร้องขอได้

  • $payload ที่ว่างเปล่าจะคืนแมปว่างจาก encode ไม่มีการเขียนไบต์ใด และไม่ไปถึงการป้องกันความแข็งแรงของคีย์
  • สำหรับเพย์โหลดที่ไม่ว่างเปล่า $text ที่มีอักขระน้อยกว่าสองตัวจะทำให้เกิด OverflowException ใน encode (เพย์โหลดที่ว่างเปล่าจะลัดวงจรไปเป็น [] ก่อนการตรวจสอบความยาว) ข้อความเดียวกันจะให้ผลเป็น null ใน decode และเป็นศูนย์ใน SteganographyCapacity::calculate
  • $payload ที่ใหญ่กว่าความจุของข้อความจะทำให้เกิด OverflowException ก่อนที่จะมีการปล่อยค่าปรับใดๆ ออกมา
  • $secretKey ที่สั้นกว่า MIN_SECRET_KEY_LENGTH (16 ไบต์) จะทำให้เกิด InvalidArgumentException ทั้งบนเส้นทางเขียนและเส้นทางอ่าน นี่คือการละเมิดสัญญา ซึ่งต่างจากการพลาดเพราะคีย์ผิดตามปกติ
  • คีย์ที่ผิด ชุดค่าปรับที่เสียหาย หรือบล็อบที่ถูกตัดทอนจะทำให้ decode คืนค่า null ผ่านความล้มเหลวในการยืนยันตัวตนของ AEAD ไม่ใช่ข้อยกเว้น
  • ตำแหน่งที่ไม่มีอยู่ในแมป $observedAdjustments แบบเบาบางจะถูกถือว่ามีค่าเบี่ยงเบนเป็นศูนย์ระหว่างการสกัด
  • decodeFromContentStream จะคืนค่า null เมื่อสตรีมไม่มีข้อความ TJ
  • ช่องทางนี้เปราะบางโดยการออกแบบ การพิมพ์แล้วสแกน การแปลง PDF การทำ re-linearization การเขียนคอนเทนต์สตรีมใหม่ หรือการทำให้ kerning เป็นมาตรฐานสามารถทำลายข้อมูลที่เข้ารหัสได้ จึงไม่เหมาะสำหรับการใช้งานที่ต้องต้านทานผู้ประสงค์ร้ายหรือการเก็บถาวร

ช่องทางนี้ใช้ HKDF-SHA-256 สำหรับการสร้างคีย์ และไซเฟอร์ AEAD หนึ่งตัวสำหรับความลับและความสมบูรณ์ NextPDF ไม่ได้ถือครองการตรวจรับรอง FIPS สำหรับช่องทางนี้และไม่ได้อ้างสิทธิ์ใดๆ โมดูลนี้ไม่ได้บังคับใช้โปรไฟล์ FIPS การเลือกไซเฟอร์เป็นการตัดสินใจของผู้เรียกผ่าน $config->cipher aes-256-gcm คือ AES ในโหมด Galois/Counter ซึ่งเป็นโหมดการเข้ารหัสแบบยืนยันตัวตนที่สร้างบนบล็อกไซเฟอร์ 128 บิตที่ได้รับการอนุมัติ โดยความสอดคล้องได้รับการตรวจสอบภายใต้ CMVP ตาม NIST SP 800-38D §2 chacha20-poly1305 ไม่ได้ถูกกำหนดโดยคำแนะนำโหมดการทำงานของ NIST ดังนั้นผู้ให้บริการ OpenSSL ที่ถูกจำกัดด้วย FIPS จะปฏิเสธมัน แล้ว openssl_encrypt จะคืนค่า false และตัวเข้ารหัสจะยก SteganographyEncryptionException ขึ้นมา การที่การนำไปใช้งานหนึ่งๆ จะเป็นไปตามข้อกำหนด FIPS หรือไม่นั้นเป็นการพิจารณาของผู้ดำเนินการเทียบกับผู้ให้บริการที่ผ่านการตรวจรับรอง ไม่ใช่การยืนยันของ NextPDF

การฝังจะเขียนองค์ประกอบเชิงตัวเลขลงในอาร์เรย์แสดงข้อความ TJ ตาม ISO 32000-2:2020 §9.4.3 อาร์เรย์ TJ จะแสดงข้อความและให้องค์ประกอบเชิงตัวเลขปรับตำแหน่งของกลิฟได้ ตัวเลขนี้แสดงเป็นหนึ่งในพันของหน่วยพื้นที่ข้อความ และถูกลบออกจากตำแหน่งปัจจุบัน หลังจากวาดกลิฟแล้ว เมทริกซ์ข้อความจะถูกเลื่อนไปตามการกระจัดรวม ดังนั้นตัวเลขจัดตำแหน่งจึงเลื่อนการวางกลิฟถัดไป — ISO 32000-2:2020 §9.4.4 ช่องทางนี้บวกออฟเซ็ตของมันเข้ากับค่า kern ธรรมชาติในแบบแผน 1/1000 em (AFM) เดียวกัน โดยค่าลบจะทำให้ระยะห่างแคบลง

การอิงกับ AEAD จำกัดอยู่เพียงการเลือกไพรมิทีฟ aes-256-gcm สอดคล้องกับโหมด GCM ของ NIST SP 800-38D §2 การอ้างอิงดังกล่าวระบุถึงอัลกอริทึม ไม่ใช่การตรวจรับรองช่องทางนี้

ทุกข้อกำหนดเป็นการถอดความ NextPDF ไม่ได้คัดลอกข้อความเชิงบรรทัดฐาน NextPDF ไม่อ้างสิทธิ์ความสอดคล้องด้าน steganography การเข้ารหัส หรือ PDF ใดๆ สำหรับช่องทางนี้ การจัดแนวเชิงโครงสร้างกับโมเดลการจัดตำแหน่ง TJ เป็นการระบุความสามารถ ไม่ใช่การรับรอง ข้อเปิดเผยด้านความทนทานยังคงเดิม ช่องทางนี้มีไว้สำหรับการติดตามการรั่วไหลภายใน และไม่ได้อยู่ในระดับต้านทานผู้ประสงค์ร้าย

  • จุดเข้าใช้งานเป็นเมธอด public static ใน NextPDF\Enterprise\Security\Steganography ยกเว้นคอนสตรัคเตอร์ของ SteganographyConfig และ effectiveMaxOffset
  • SteganographyConfig เป็นออบเจ็กต์ค่าแบบ final readonly พรอเพอร์ตี้ทั้งสี่ของมันไม่เปลี่ยนแปลงหลังการสร้าง และโดเมนอาร์กิวเมนต์ของมันถูกตรวจสอบในคอนสตรัคเตอร์ $bitDepth เป็น 1 หรือ 2 $maxAdjustmentEmRatio อยู่ในช่วง (0, 0.05] และ $cipher เป็น aes-256-gcm หรือ chacha20-poly1305
  • ผลลัพธ์ของ encode ถูกใช้โดย NextPDF\Content\TextRenderer::buildTjArrayOperator คู่ kern มาจาก NextPDF\Typography\FontMetrics การถอดรหัสคอนเทนต์สตรีมอ่านผ่าน NextPDF\Pro\Projection\ContentProjectionWriter และไม่เปลี่ยนแปลงสตรีม
  • ค่าขั้นต่ำความยาวคีย์ถูกบังคับที่จุดเข้าใช้งานและถูกยืนยันซ้ำที่ขอบเขตการเข้ารหัสส่วนตัว ดังนั้นจึงไม่มีเส้นทางภายในใดที่จะไปถึง HKDF ด้วยคีย์ที่อ่อนแอได้ ไลบรารีบังคับความยาว ไม่ใช่เอนโทรปี การจัดหาวัสดุคีย์ที่มีเอนโทรปีสูงเป็นความรับผิดชอบของผู้ผสานระบบ
  • CRYPTO_OVERHEAD (32 ไบต์) เป็นต้นทุนคงที่ต่อเพย์โหลดและถูกหักแล้วโดย SteganographyCapacity::calculate
  • เวอร์ชัน since ที่ระบุไว้คือ 3.1.0 สำหรับพื้นผิว Enterprise แบบรวม SteganographyEncryptionException สืบทอดจาก RuntimeException ดังนั้นจุดเรียกที่จับชนิด runtime ทั่วไปจะยังคงทำงานได้

หน้านี้บันทึกเฉพาะพฤติกรรมที่สังเกตได้จากภายนอกและพื้นผิว API สาธารณะที่รองรับเท่านั้น เส้นทาง namespace ภายใน คลาสตัวช่วย ตารางกลไก ชื่อไฟล์ runbook และคำนำหน้าตั๋วอยู่นอกขอบเขต