Salta ai contenuti
getnextpdf.com

Enterprise edizione

Steganografia — Riferimento approfondito

Questo riferimento approfondito documenta il canale steganografico di NextPDF Enterprise. Il canale nasconde un payload cifrato all’interno delle regolazioni numeriche di crenatura di un array di visualizzazione del testo TJ. Espone quattro simboli pubblici: SteganographyEncoder, SteganographyDecoder, SteganographyConfig e SteganographyCapacity. L’encoder deriva una chiave con HKDF-SHA-256, cifra il payload con una cifratura AEAD e restituisce gli offset di crenatura per posizione. Il decoder inverte il processo a partire dalle regolazioni osservate o da un content stream grezzo.

Il canale è progettato per la tracciatura interna delle fughe di documenti. Non è steganografia di livello adversarial. I dati codificati possono essere distrutti da stampa-e-scansione, conversione PDF, ri-linearizzazione, riscrittura del content stream o qualsiasi operazione che normalizzi la crenatura. NextPDF non detiene alcuna certificazione per questo canale e non ne concede alcuna. Questa pagina dichiara una capacità, non una conformità.

Questa funzionalità è distribuita in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di livello Enterprise. Un deployment privo di tale abilitazione non carica le classi della funzionalità. Confronta le edizioni e ottieni una licenza.

Il canale espone quattro classi final. Tutti i punti di ingresso sono public static, tranne il costruttore di SteganographyConfig e il suo accessor effectiveMaxOffset. La classe di supporto NextPDF\Enterprise\Security\Steganography\SteganographyEncryptionException viene lanciata dall’encoder; non è un tipo costruibile dal chiamante.

SimboloParametriComportamento predefinitoRestituisceLancia o fallisce conNote
SteganographyEncoder::encode$payload, $text, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig)Un $payload vuoto restituisce []; verifica la robustezza della chiave; cifra; calcola gli offset di crenatura per posizione.array<int, float> (posizione => regolazione in 1/1000 em, convenzione AFM)InvalidArgumentException (chiave sotto la soglia); OverflowException (testo con meno di 2 caratteri, o payload oltre la capacità); SteganographyEncryptionException (fallimento AEAD)Passa il risultato a NextPDF\Content\TextRenderer::buildTjArrayOperator(). L’API restituisce regolazioni in convenzione AFM; buildTjArrayOperator() esegue la conversione numerica TJ del PDF (ISO 32000-2 sottrae il numero dalla posizione corrente). Chi scrive manualmente i content stream deve preservare quella convenzione di segno.
SteganographyEncoder::assertSecretKeyStrength$secretKeyRifiuta una chiave più corta della soglia.voidInvalidArgumentException (chiave sotto la soglia)Protezione condivisa del percorso di scrittura, replicata sul percorso di lettura.
SteganographyEncoder::MIN_SECRET_KEY_LENGTHcostanteLa soglia di lunghezza chiave di 128 bit in byte.int (16)Non applicabileLa libreria impone la lunghezza, non l’entropia.
SteganographyDecoder::decode$observedAdjustments, $text, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig)Verifica la robustezza della chiave; quantizza le deviazioni; ricostruisce il blob; decifra in modalità AEAD.`stringnull(payload, oppurenull` in caso di chiave errata o assenza di payload)InvalidArgumentException (chiave sotto la soglia)
SteganographyDecoder::decodeFromContentStream$contentStream, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig)Tokenizza lo stream, ricostruisce testo e regolazioni dagli array TJ, poi delega a decode.`stringnull(payload, oppurenullquando non c'è testoTJ` o la decifratura fallisce)InvalidArgumentException (chiave sotto la soglia, tramite decode)
SteganographyConfig::__construct$bitDepth, $maxAdjustmentEmRatio, $cipher, $requirePdfACompatibilityValida il dominio di ciascun argomento; produce un value object immutabile.Istanza di SteganographyConfigInvalidArgumentException ($bitDepth, $maxAdjustmentEmRatio o $cipher non validi)Classe readonly; i quattro argomenti sono proprietà pubbliche promosse.
SteganographyConfig::effectiveMaxOffsetnessunoRestituisce $maxAdjustmentEmRatio * 1000, dimezzato quando è richiesta la compatibilità PDF/A.float (offset in 1/1000 em)Non applicabileIl dimezzamento riduce il rischio di rilevamento di discrepanze di larghezza.
SteganographyConfig::CRYPTO_OVERHEADcostanteL’overhead fisso di cifratura per payload, in byte.int (32)Non applicabileLunghezza a 4 byte, nonce a 12 byte, tag a 16 byte.
SteganographyCapacity::calculate$text, $config (SteganographyConfig)Calcola i byte di payload utilizzabili per il testo, dopo l’overhead.int (0 quando il testo è troppo corto)Non applicabileLa capacità è positions * bitDepth / 8 meno l’overhead.
SteganographyCapacity::minimumTextLength$payloadBytes, $config (SteganographyConfig)Calcola il numero minimo di caratteri UTF-8 per un payload.int (numero di caratteri)Non applicabileInverso di calculate.

Seguono le firme verbatim, ciascuna con la propria provenienza dal sorgente.

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

L’encoder suddivide $text in caratteri UTF-8 e forma una posizione per ciascuna coppia di caratteri consecutivi. Ogni posizione trasporta $config->bitDepth bit, cioè uno o due. Il payload viene prima cifrato, poi serializzato in un blob, quindi convertito in una sequenza di bit. Ogni posizione codifica i propri bit come un piccolo offset non negativo aggiunto al valore di crenatura naturale di quella coppia di caratteri.

L’offset è una frazione dell’offset massimo effettivo. L’offset massimo effettivo è $maxAdjustmentEmRatio * 1000 unità di progetto, dimezzato quando $requirePdfACompatibility è true. La crenatura naturale viene letta da $metrics tramite FontMetrics::getKernPair. La mappa restituita è sparsa: una posizione la cui regolazione finale è esattamente zero viene omessa.

La cifratura usa HKDF-SHA-256 per derivare una chiave da 32 byte. Il salt di HKDF è il $fontKey non segreto e l’etichetta info è una costante fissa. Pertanto il $secretKey del chiamante è l’unico confine di riservatezza. La cifratura AEAD è aes-256-gcm o chacha20-poly1305, selezionata da $config->cipher, eseguita tramite openssl_encrypt con un nonce fresco da 12 byte e un tag da 16 byte. Il blob serializzato è una lunghezza big-endian da 4 byte, il nonce da 12 byte, il testo cifrato e il tag da 16 byte; questo overhead fisso è CRYPTO_OVERHEAD, ovvero 32 byte.

Il decoder inverte la trasformazione. Calcola la deviazione di ciascuna regolazione osservata rispetto alla crenatura naturale, la normalizza rispetto all’offset massimo effettivo e la quantizza al livello più vicino. Riassembla il blob, valida l’header di lunghezza e chiama openssl_decrypt. Una chiave errata, un payload mancante o regolazioni corrotte fanno fallire l’autenticazione AEAD, e il decoder restituisce null. decodeFromContentStream prima tokenizza lo stream grezzo con NextPDF\Pro\Projection\ContentProjectionWriter::tokenize, ricostruisce il testo e le regolazioni numeriche da ciascun array TJ, e poi delega a decode.

SteganographyCapacity::calculate riporta la dimensione di payload utilizzabile per un testo e una configurazione, dopo aver sottratto CRYPTO_OVERHEAD; restituisce zero quando il testo è troppo corto. SteganographyCapacity::minimumTextLength è l’inverso: il minimo numero di caratteri UTF-8 che ammette un payload della dimensione richiesta.

  • Un $payload vuoto restituisce una mappa vuota da encode; non viene scritto alcun byte, e la protezione sulla robustezza della chiave non viene raggiunta.
  • Per un payload non vuoto, un $text con meno di due caratteri solleva OverflowException in encode (un payload vuoto va in corto circuito a [] prima del controllo di lunghezza); lo stesso testo produce null in decode e zero in SteganographyCapacity::calculate.
  • Un $payload più grande della capacità del testo solleva OverflowException prima che venga emessa qualsiasi regolazione.
  • Un $secretKey più corto di MIN_SECRET_KEY_LENGTH (16 byte) solleva InvalidArgumentException sia sul percorso di scrittura sia su quello di lettura. Questa è una violazione del contratto, distinta da un normale insuccesso da chiave errata.
  • Una chiave errata, un insieme di regolazioni corrotto o un blob troncato fanno sì che decode restituisca null tramite il fallimento dell’autenticazione AEAD, non un’eccezione.
  • Le posizioni assenti da una mappa $observedAdjustments sparsa vengono trattate come deviazione zero durante l’estrazione.
  • decodeFromContentStream restituisce null quando lo stream non contiene testo TJ.
  • Il canale è fragile per progettazione. Stampa-e-scansione, conversione PDF, ri-linearizzazione, riscrittura del content stream o normalizzazione della crenatura possono distruggere i dati codificati. Non è adatto a un uso adversarial o archivistico.

Il canale usa HKDF-SHA-256 per la derivazione della chiave e una cifratura AEAD per riservatezza e integrità. NextPDF non detiene alcuna validazione FIPS per questo canale e non ne rivendica alcuna. Il modulo non impone un profilo FIPS; la selezione della cifratura è una decisione del chiamante tramite $config->cipher. aes-256-gcm è AES in modalità Galois/Counter, una modalità di cifratura autenticata costruita su un cifrario a blocchi a 128 bit approvato la cui conformità è validata nell’ambito del CMVP, secondo NIST SP 800-38D §2. chacha20-poly1305 non è definito da una raccomandazione NIST sulle modalità operative, quindi un provider OpenSSL vincolato a FIPS lo rifiuta; openssl_encrypt restituisce allora false e l’encoder solleva SteganographyEncryptionException. Se un deployment soddisfi un requisito FIPS è una determinazione dell’operatore rispetto al proprio provider validato, non un’asserzione di NextPDF.

L’incorporamento scrive elementi numerici in un array di visualizzazione del testo TJ. Secondo ISO 32000-2:2020 §9.4.3, un array TJ mostra il testo e consente a un elemento numerico di regolare la posizione del glifo; il numero è espresso in millesimi di un’unità di spazio-testo ed è sottratto dalla posizione corrente. Dopo che un glifo è stato disegnato, la matrice del testo viene traslata dello spostamento combinato, così un numero di posizionamento sposta la collocazione dei glifi successivi — ISO 32000-2:2020 §9.4.4. Il canale aggiunge i propri offset ai valori di crenatura naturale nella stessa convenzione 1/1000 em (AFM), dove un valore negativo restringe la spaziatura.

Il fondamento AEAD si limita alla selezione della primitiva: aes-256-gcm corrisponde alla modalità GCM di NIST SP 800-38D §2. Quel riferimento identifica un algoritmo; non è una validazione di questo canale.

Tutte le clausole sono parafrasate; NextPDF non riproduce testo normativo. NextPDF non avanza alcuna rivendicazione di conformità steganografica, crittografica o PDF per questo canale. L’allineamento strutturale con il modello di posizionamento TJ è una dichiarazione di capacità, non una certificazione. La comunicazione sulla robustezza resta valida: il canale è destinato alla tracciatura interna delle fughe e non è di livello adversarial.

  • I punti di ingresso sono metodi public static in NextPDF\Enterprise\Security\Steganography, tranne il costruttore di SteganographyConfig ed effectiveMaxOffset.
  • SteganographyConfig è un value object final readonly. Le sue quattro proprietà sono immutabili dopo la costruzione, e i domini dei suoi argomenti sono validati nel costruttore: $bitDepth è 1 o 2, $maxAdjustmentEmRatio è in (0, 0.05], e $cipher è aes-256-gcm o chacha20-poly1305.
  • L’output di encode è consumato da NextPDF\Content\TextRenderer::buildTjArrayOperator. Le coppie di crenatura provengono da NextPDF\Typography\FontMetrics. La decodifica del content stream legge tramite NextPDF\Pro\Projection\ContentProjectionWriter e non muta lo stream.
  • La soglia di lunghezza chiave è imposta al punto di ingresso e riasserita al confine crittografico privato, così nessun percorso interno può raggiungere HKDF con una chiave debole. La libreria impone la lunghezza, non l’entropia; fornire materiale di chiave ad alta entropia è responsabilità dell’integratore.
  • CRYPTO_OVERHEAD (32 byte) è il costo fisso per payload ed è già sottratto da SteganographyCapacity::calculate.
  • La versione since documentata è 3.1.0 per la superficie Enterprise aggregata. SteganographyEncryptionException estende RuntimeException, così i call site che catturano il tipo runtime generico continuano a funzionare.

Questa pagina documenta esclusivamente il comportamento osservabile esternamente e la superficie dell’API pubblica supportata. Percorsi di namespace interni, classi di supporto, tabelle di meccanismi, nomi di file di runbook e prefissi di ticket sono fuori ambito.