Enterprise edição
Esteganografia — Referência Profunda
Visão geral
Seção intitulada “Visão geral”Esta referência detalhada documenta o canal esteganográfico do NextPDF Enterprise. O canal esconde um payload criptografado dentro dos ajustes numéricos de kern de uma array de exibição de texto TJ. Ele tem quatro símbolos públicos: SteganographyEncoder, SteganographyDecoder, SteganographyConfig e SteganographyCapacity. O codificador deriva uma chave com HKDF-SHA-256, criptografa o payload com uma cifra AEAD e retorna deslocamentos de kern por posição. O decodificador reverte o processo a partir de ajustes observados ou de um content stream bruto.
O canal foi projetado para rastreamento interno de vazamento de documentos. Ele não é esteganografia de grau adversarial. Dados codificados podem ser destruídos por impressão-e-digitalização, conversão de PDF, relinearização, reescrita de content stream ou qualquer operação que normalize o kerning. O NextPDF não possui nenhuma certificação para este canal e não concede nenhuma. Esta página declara capacidade, não conformidade.
Disponibilidade e licenciamento
Seção intitulada “Disponibilidade e licenciamento”Este recurso é distribuído no NextPDF Enterprise (nextpdf/enterprise) e é ativado com um envelope de licença de nível Enterprise. Uma implantação sem essa habilitação não carrega as classes do recurso. Compare as edições e obtenha uma licença.
Superfície da API pública
Seção intitulada “Superfície da API pública”O canal expõe quatro classes final. Todos os pontos de entrada são public static, exceto o construtor de SteganographyConfig e seu acessador effectiveMaxOffset. A classe de suporte NextPDF\Enterprise\Security\Steganography\SteganographyEncryptionException é lançada pelo codificador; ela não é um tipo construído pelo chamador.
| Símbolo | Parâmetros | Comportamento padrão | Retorna | Lança ou falha com | Notas |
|---|---|---|---|---|---|
SteganographyEncoder::encode | $payload, $text, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig) | Um $payload vazio retorna []; verifica a força da chave; criptografa; calcula deslocamentos de kern por posição. | array<int, float> (posição => ajuste em 1/1000 em, convenção AFM) | InvalidArgumentException (chave abaixo do piso); OverflowException (texto com menos de 2 caracteres, ou payload acima da capacidade); SteganographyEncryptionException (falha AEAD) | Passe o resultado para NextPDF\Content\TextRenderer::buildTjArrayOperator(). A API retorna ajustes na convenção AFM; buildTjArrayOperator() realiza a conversão numérica do TJ do PDF (a ISO 32000-2 subtrai o número da posição atual). Escritores manuais de content stream devem preservar essa convenção de sinal. |
SteganographyEncoder::assertSecretKeyStrength | $secretKey | Rejeita uma chave mais curta que o piso. | void | InvalidArgumentException (chave abaixo do piso) | Proteção compartilhada do caminho de escrita, espelhada no caminho de leitura. |
SteganographyEncoder::MIN_SECRET_KEY_LENGTH | constante | O piso de comprimento de chave de 128 bits em bytes. | int (16) | Não aplicável | A biblioteca impõe comprimento, não entropia. |
SteganographyDecoder::decode | $observedAdjustments, $text, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig) | Verifica a força da chave; quantiza desvios; reconstrói o blob; decripta com AEAD. | `string | null(payload, ounull` em chave errada ou sem payload) | InvalidArgumentException (chave abaixo do piso) |
SteganographyDecoder::decodeFromContentStream | $contentStream, $fontKey, $metrics (FontMetrics), $secretKey, $config (SteganographyConfig) | Tokeniza o stream, reconstrói texto e ajustes a partir de arrays TJ, e então delega para decode. | `string | null(payload, ounullquando não há textoTJ` ou a decriptação falha) | InvalidArgumentException (chave abaixo do piso, via decode) |
SteganographyConfig::__construct | $bitDepth, $maxAdjustmentEmRatio, $cipher, $requirePdfACompatibility | Valida o domínio de cada argumento; produz um value object imutável. | Instância de SteganographyConfig | InvalidArgumentException ($bitDepth, $maxAdjustmentEmRatio ou $cipher inválidos) | Classe readonly; os quatro argumentos são propriedades públicas promovidas. |
SteganographyConfig::effectiveMaxOffset | nenhum | Retorna $maxAdjustmentEmRatio * 1000, reduzido à metade quando a compatibilidade com PDF/A é solicitada. | float (deslocamento em 1/1000 em) | Não aplicável | A redução à metade diminui o risco de detecção por incompatibilidade de largura. |
SteganographyConfig::CRYPTO_OVERHEAD | constante | O overhead fixo de criptografia por payload em bytes. | int (32) | Não aplicável | 4 bytes de comprimento, 12 bytes de nonce, 16 bytes de tag. |
SteganographyCapacity::calculate | $text, $config (SteganographyConfig) | Calcula os bytes de payload utilizáveis para o texto, após o overhead. | int (0 quando o texto é curto demais) | Não aplicável | A capacidade é positions * bitDepth / 8 menos o overhead. |
SteganographyCapacity::minimumTextLength | $payloadBytes, $config (SteganographyConfig) | Calcula a contagem mínima de caracteres UTF-8 para um payload. | int (contagem de caracteres) | Não aplicável | Inverso de calculate. |
As assinaturas verbatim seguem, cada uma com a proveniência do código-fonte.
public static function encode( string $payload, string $text, string $fontKey, FontMetrics $metrics, string $secretKey, SteganographyConfig $config = new SteganographyConfig(),): arraypublic static function assertSecretKeyStrength(string $secretKey): voidpublic 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(),): ?stringpublic static function decodeFromContentStream( string $contentStream, string $fontKey, FontMetrics $metrics, string $secretKey, SteganographyConfig $config = new SteganographyConfig(),): ?stringpublic function __construct( public int $bitDepth = 1, public float $maxAdjustmentEmRatio = 0.02, public string $cipher = 'aes-256-gcm', public bool $requirePdfACompatibility = false,)public function effectiveMaxOffset(): floatpublic const int CRYPTO_OVERHEAD = 32;public static function calculate( string $text, SteganographyConfig $config = new SteganographyConfig(),): intpublic static function minimumTextLength( int $payloadBytes, SteganographyConfig $config = new SteganographyConfig(),): intContrato de comportamento
Seção intitulada “Contrato de comportamento”O codificador divide $text em caracteres UTF-8 e forma uma posição por par consecutivo de caracteres. Cada posição carrega $config->bitDepth bits, que é um ou dois. O payload é primeiro criptografado, depois serializado em um blob e então convertido em uma sequência de bits. Cada posição codifica seus bits como um pequeno deslocamento não negativo adicionado ao valor de kern natural daquele par de caracteres.
O deslocamento é uma fração do deslocamento máximo efetivo. O deslocamento máximo efetivo é $maxAdjustmentEmRatio * 1000 unidades de design, reduzido à metade quando $requirePdfACompatibility é verdadeiro. O kern natural é lido de $metrics através de FontMetrics::getKernPair. O mapa retornado é esparso: uma posição cujo ajuste final é exatamente zero é omitida.
A criptografia usa HKDF-SHA-256 para derivar uma chave de 32 bytes. O salt do HKDF é o $fontKey não secreto e o rótulo de info é uma constante fixa. Portanto, a $secretKey do chamador é a única fronteira de confidencialidade. A cifra AEAD é aes-256-gcm ou chacha20-poly1305, selecionada por $config->cipher, executada através de openssl_encrypt com um novo nonce de 12 bytes e uma tag de 16 bytes. O blob serializado é um comprimento big-endian de 4 bytes, o nonce de 12 bytes, o ciphertext e a tag de 16 bytes; esse overhead fixo é CRYPTO_OVERHEAD, que é 32 bytes.
O decodificador reverte a transformação. Ele calcula o desvio de cada ajuste observado em relação ao kern natural, normaliza pelo deslocamento máximo efetivo e quantiza para o nível mais próximo. Ele reagrupa o blob, valida o cabeçalho de comprimento e chama openssl_decrypt. Uma chave errada, um payload ausente ou ajustes corrompidos fazem a autenticação AEAD falhar, e o decodificador retorna null. decodeFromContentStream primeiro tokeniza o stream bruto com NextPDF\Pro\Projection\ContentProjectionWriter::tokenize, reconstrói o texto e os ajustes numéricos de cada array TJ, e então delega para decode.
SteganographyCapacity::calculate informa o tamanho de payload utilizável para um texto e uma configuração, após subtrair CRYPTO_OVERHEAD; retorna zero quando o texto é curto demais. SteganographyCapacity::minimumTextLength é o inverso: a menor contagem de caracteres UTF-8 que admite um payload do tamanho solicitado.
Casos extremos e modos de falha
Seção intitulada “Casos extremos e modos de falha”- Um
$payloadvazio retorna um mapa vazio deencode; nenhum byte é escrito, e a proteção de força da chave não é alcançada. - Para um payload não vazio, um
$textcom menos de dois caracteres levantaOverflowExceptionemencode(um payload vazio faz curto-circuito para[]antes da verificação de comprimento); o mesmo texto resulta emnullemdecodee zero emSteganographyCapacity::calculate. - Um
$payloadmaior que a capacidade do texto levantaOverflowExceptionantes que qualquer ajuste seja emitido. - Uma
$secretKeymais curta queMIN_SECRET_KEY_LENGTH(16 bytes) levantaInvalidArgumentExceptiontanto no caminho de escrita quanto no de leitura. Isso é uma violação de contrato, distinta de um erro normal de chave errada. - Uma chave errada, um conjunto de ajustes corrompido ou um blob truncado fazem
decoderetornarnullpor falha de autenticação AEAD, não uma exceção. - Posições ausentes de um mapa
$observedAdjustmentsesparso são tratadas como um desvio zero durante a extração. decodeFromContentStreamretornanullquando o stream não contém textoTJ.- O canal é frágil por design. Impressão-e-digitalização, conversão de PDF, relinearização, reescrita de content stream ou normalização de kerning podem destruir os dados codificados. Ele é inadequado para uso adversarial ou de arquivamento.
Comportamento em modo FIPS
Seção intitulada “Comportamento em modo FIPS”O canal usa HKDF-SHA-256 para derivação de chave e uma cifra AEAD para confidencialidade e integridade. O NextPDF não possui nenhuma validação FIPS para este canal e não faz tal alegação. O módulo não impõe um perfil FIPS; a seleção da cifra é a decisão do chamador através de $config->cipher. aes-256-gcm é AES em Galois/Counter Mode, um modo de criptografia autenticada construído sobre uma cifra de bloco de 128 bits aprovada, cuja conformidade é validada sob o CMVP, conforme NIST SP 800-38D §2. chacha20-poly1305 não é definido por uma recomendação de modo de operação do NIST, então um provedor OpenSSL restrito a FIPS o rejeita; openssl_encrypt então retorna false e o codificador levanta SteganographyEncryptionException. Se uma implantação atende a um requisito FIPS é a determinação do operador contra o seu provedor validado, não uma afirmação do NextPDF.
Conformidade
Seção intitulada “Conformidade”A incorporação escreve elementos numéricos em uma array de exibição de texto TJ. Conforme a ISO 32000-2:2020 §9.4.3, uma array TJ mostra texto e permite que um elemento numérico ajuste a posição do glifo; o número é expresso em milésimos de uma unidade de espaço de texto e é subtraído da posição atual. Depois que um glifo é pintado, a matriz de texto é transladada pelo deslocamento combinado, de modo que um número de posicionamento desloca a colocação dos glifos subsequentes — ISO 32000-2:2020 §9.4.4. O canal adiciona seus deslocamentos aos valores de kern natural na mesma convenção de 1/1000 em (AFM), onde um valor negativo aperta o espaçamento.
O embasamento AEAD limita-se à seleção da primitiva: aes-256-gcm corresponde ao modo GCM do NIST SP 800-38D §2. Essa referência identifica um algoritmo; ela não é uma validação deste canal.
Todas as cláusulas são parafraseadas; o NextPDF não reproduz texto normativo. O NextPDF não faz nenhuma alegação de conformidade de esteganografia, criptografia ou PDF para este canal. O alinhamento estrutural com o modelo de posicionamento TJ é uma declaração de capacidade, não uma certificação. A divulgação de robustez permanece: o canal é para rastreamento interno de vazamento, e não é de grau adversarial.
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”- Os pontos de entrada são métodos
public staticemNextPDF\Enterprise\Security\Steganography, exceto o construtor deSteganographyConfigeeffectiveMaxOffset. SteganographyConfigé um value objectfinal readonly. Suas quatro propriedades são imutáveis após a construção, e os domínios de seus argumentos são validados no construtor:$bitDepthé 1 ou 2,$maxAdjustmentEmRatioestá em(0, 0.05], e$cipheréaes-256-gcmouchacha20-poly1305.- A saída do encode é consumida por
NextPDF\Content\TextRenderer::buildTjArrayOperator. Os pares de kern vêm deNextPDF\Typography\FontMetrics. A decodificação de content stream lê através deNextPDF\Pro\Projection\ContentProjectionWritere não muta o stream. - O piso de comprimento de chave é imposto no ponto de entrada e reafirmado na fronteira criptográfica privada, de modo que nenhum caminho interno pode alcançar o HKDF com uma chave fraca. A biblioteca impõe comprimento, não entropia; fornecer material de chave de alta entropia é responsabilidade do integrador.
CRYPTO_OVERHEAD(32 bytes) é o custo fixo por payload e já é subtraído porSteganographyCapacity::calculate.- O
sincedocumentado é3.1.0para a superfície agregada do Enterprise.SteganographyEncryptionExceptionestendeRuntimeException, então os call sites que capturam o tipo runtime genérico continuam a funcionar.
Veja também
Seção intitulada “Veja também”- Esteganografia (página de capacidade) — a visão geral orientada a tarefas do canal de rastreamento de vazamento.
- Segurança — Referência Detalhada — a superfície de segurança irmã do Enterprise.
- Licenciamento e ativação — como o envelope de licença do Enterprise é aplicado.
Fronteira de publicação
Seção intitulada “Fronteira de publicação”Esta página documenta apenas o comportamento observável externamente e a superfície da API pública suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de tickets estão fora de escopo.