Representação visual PAdES - Rest PKI Core
A representação visual de uma assinatura PAdES é a sua aparência visível no PDF: um texto, uma imagem ou os dois, desenhados dentro de um retângulo em uma das páginas. Ela é opcional: sem ela, a assinatura é invisível, mas continua válida, e os leitores de PDF a listam no painel de assinaturas.
A representação visual tem três partes: o texto, a imagem e a posição do retângulo na página. Somente a posição é obrigatória.
"visualRepresentation": {
"text": { ... },
"image": { ... },
"position": { ... }
}
A partir daqui descreveremos chamadas ao Rest PKI Core. Certifique-se de ter lido o artigo Primeiros passos para acompanhar.
Onde definir
A representação visual faz parte das opções de assinatura de PDF, pdfSignatureOptions, no campo visualRepresentation:
| API | Onde |
|---|---|
Sessões de assinatura: POST {endpoint}/api/signature-sessions | pdfSignatureOptions.visualRepresentation, que vale para todos os PDFs assinados na sessão |
| Sessões de assinatura, documentos predefinidos | documents[].pdfSignatureOptions.visualRepresentation, para um documento |
Assinaturas em duas etapas: POST {endpoint}/api/signature | pdfSignatureOptions.visualRepresentation |
Carimbos em PDF: POST {endpoint}/api/pdf/stamp | visualRepresentation, no nível principal da requisição. Usa o mesmo modelo descrito aqui, mas as tags do texto não são substituídas: não há signatário, então elas permanecem como foram escritas |
Quando um documento predefinido de uma sessão de assinatura tem pdfSignatureOptions próprio, ele substitui por completo o pdfSignatureOptions da
sessão: os dois não são combinados, então repita o visualRepresentation no documento. A exceção é convertToPdfA, que o documento herda da sessão
(veja Conversão para PDF/A).
As APIs legadas do Rest PKI que o Rest PKI Core ainda atende (veja Migração do Rest PKI) usam o
mesmo modelo no campo visualRepresentation da requisição.
Texto
O objeto text desenha um texto no retângulo:
| Campo | Descrição |
|---|---|
text | O texto, que pode ter {{tags}} (veja abaixo) e quebras de linha. Obrigatório sempre que text é enviado: um objeto text sem ele falha |
includeSigningTime | Quando true, acrescenta uma linha com o horário da assinatura, formatado com as configurações de data e hora da organização. Padrão: false |
fontSize | O tamanho máximo da fonte, em pontos: o texto diminui, quando necessário, para caber no retângulo. Padrão: 12 |
horizontalAlign | Left (padrão) ou Right |
container | A região do retângulo da assinatura onde o texto é desenhado, como um retângulo relativo ao retângulo da assinatura (e não à página). Se omitido, o texto pode usar todo o retângulo da assinatura. O texto é alinhado ao topo da região |
Por exemplo, para deixar uma margem de 0,2 em volta do texto:
"text": {
"text": "Assinado digitalmente por {{name}}",
"fontSize": 9,
"includeSigningTime": true,
"horizontalAlign": "Left",
"container": { "left": 0.2, "top": 0.2, "right": 0.2, "bottom": 0.2 }
}
Tags
Em uma assinatura, as tags em text são substituídas por dados do certificado do signatário (em um carimbo, elas permanecem como foram escritas). Elas diferenciam maiúsculas de minúsculas, e uma tag desconhecida permanece no
texto como foi escrita. As mais usadas:
| Tag | Valor |
|---|---|
{{name}} | O nome completo do signatário |
{{national_id}} | O número de identidade nacional do signatário (em certificados ICP-Brasil, o CPF do titular) |
{{email}} | O endereço de e-mail do signatário |
{{issuer_cn}} | O nome comum (CN) do emissor do certificado |
{{br_cpf_formatted}} | O CPF do titular, formatado como 000.000.000-00 (certificados ICP-Brasil) |
{{br_cpf_masked}} | O CPF do titular, mascarado (certificados ICP-Brasil) |
Veja a lista completa de tags, que são as mesmas do Rest PKI.
Imagem
O objeto image desenha uma imagem no retângulo, atrás do texto:
| Campo | Descrição |
|---|---|
resource | A imagem, como url (um link de onde o servidor baixa a imagem; a imagem fica em cache por cerca de 5 minutos) ou content (os bytes em Base64). Um dos dois é obrigatório, e content prevalece quando os dois são enviados |
opacity | De 0 a 100. Padrão: 100 |
horizontalAlign | Left, Center (padrão) ou Right |
verticalAlign | Top, Center (padrão) ou Bottom |
A imagem é redimensionada para caber no retângulo, mantendo a proporção. Quando o retângulo é mais largo que a imagem redimensionada, quem a posiciona é
horizontalAlign; caso contrário, é verticalAlign.
"image": {
"resource": { "url": "https://example.com/seal.png" },
"opacity": 40,
"horizontalAlign": "Right",
"verticalAlign": "Center"
}
Posição
O objeto position diz em que página a assinatura fica e em que lugar dela. Ele tem a página, a unidade de medida e uma das duas formas de escolher o
retângulo: manual ou auto.
| Campo | Descrição |
|---|---|
pageNumber | A página: 1 é a primeira página; números negativos contam a partir do fim (-1 é a última página); 0 acrescenta uma nova página ao final do PDF, mas somente se o PDF ainda não tiver assinatura visível (caso contrário, usa a última página). Se omitido, vale 0. Um número de página além do número de páginas faz a assinatura falhar |
measurementUnits | Centimeters ou PdfPoints (1/72 de polegada). Se omitido, usa-se o valor de measurementUnits em pdfSignatureOptions e, sem ele, Centimeters. Vale para todas as medidas da posição e para o container do texto |
manual | Um retângulo fixo na página: veja Posicionamento manual |
auto | Uma região da página onde as assinaturas são colocadas uma após a outra: veja Posicionamento automático |
pageOptimization | Obsoleto. Também existe em pdfSignatureOptions, e o da posição tem precedência. As medidas em centímetros são escalonadas para um tamanho de papel de referência que o Rest PKI Core estima a partir das proporções da página (Letter, Legal ou, caso contrário, A4), a menos que pageOptimization informe o tamanho do papel (paperSize, como A4 ou Letter, ou Custom com customPaperSize) e a orientação (pageOrientation). Assim, em páginas de tamanho fora do padrão, como A3, os tamanhos acompanham a página: para ter tamanhos absolutos, use PdfPoints |
Se manual e auto forem enviados juntos, vale auto. Se nenhum dos dois for, a assinatura falha.
Retângulos
Os retângulos, como o retângulo de manual, o container de auto e o container do texto, são definidos pelos parâmetros left, top, right,
bottom, width e height, que são margens relativas ao que contém o retângulo (a página ou o retângulo da assinatura). Você não preenche todos: o que
você define decide como o retângulo se comporta.
O retângulo, em vermelho, tem as suas margens relativas ao que o contém. Não defina left, right e width juntos: na horizontal, dois dos três (ou só width)
bastam, e o resto ocupa o espaço restante. Na vertical funciona do mesmo jeito, com top, bottom e height no lugar de left, right e
width. Os exemplos abaixo mostram as formas de definir as dimensões horizontais. Para saber mais sobre como os retângulos funcionam, veja
Definindo um container, do PKI SDK.
Fluido
Se você define apenas left e right, o retângulo mantém as duas margens e a largura se estica para preencher o espaço restante.
Ancorado à esquerda
Se você define apenas left e width, o retângulo mantém a margem esquerda e a largura. A margem direita ocupa o espaço restante.
Ancorado à direita
Se você define apenas right e width, o retângulo mantém a margem direita e a largura. A margem esquerda ocupa o espaço restante.
Centralizado
Se você define apenas width, o retângulo é centralizado horizontalmente com a largura dada.
Posicionamento manual
Em manual, o retângulo da assinatura é fixo, relativo à página. Por exemplo, um retângulo de 7 por 3 cm, com margem de 2,5 cm das bordas esquerda e
inferior:
"position": {
"pageNumber": 1,
"measurementUnits": "Centimeters",
"manual": { "left": 2.5, "bottom": 2.5, "width": 7, "height": 3 }
}
Posicionamento automático
Em auto, você define um container, uma região da página, e o tamanho de cada assinatura, e o Rest PKI Core coloca as assinaturas uma após a outra
dentro do container. Serve para documentos com vários signatários, já que você não sabe a posição de cada um.
| Campo | Descrição |
|---|---|
container | A região da página que recebe as assinaturas, como um retângulo. Obrigatório |
signatureRectangleSize | A largura (width) e a altura (height) do retângulo de cada assinatura. Obrigatório |
rowSpacing | O espaço entre as linhas. Padrão: 0 |
horizontalDirection | LeftToRight (padrão) ou RightToLeft: a direção em que uma linha é preenchida |
verticalDirection | TopDown (padrão) ou BottomUp: a direção em que as linhas se empilham |
Para escolher a posição de uma assinatura, o Rest PKI Core olha a última assinatura visível que já está na página, não importa quem a fez nem com
qual ferramenta. Se a linha ainda tiver espaço para outro retângulo do mesmo tamanho, a nova assinatura vai para essa linha. Caso contrário, vai para uma nova
linha, abaixo (TopDown) ou acima (BottomUp) da anterior, separada dela por rowSpacing. Cabem em uma linha tantas assinaturas quanto o número
inteiro de vezes que a largura da assinatura cabe na largura do container. As linhas são justificadas: as colunas de uma linha se distribuem por igual pela largura do container, a primeira
encostada em uma borda e a última na outra, então há espaços entre as assinaturas (cerca de 0,73 cm com o preset Footnote, em A4 em
retrato).
Quando o container está cheio, a assinatura é feita mesmo assim, mas sem representação visual, e nenhum erro é retornado. Dimensione o container para o número de signatários esperado. O Rest PKI Core não procura espaços livres no container nem confere o restante do conteúdo da página.
Presets
Os presets devolvem um objeto position com a geometria usual, pronto para ser usado como está, no campo position da representação visual. São rotas
GET que não precisam de autenticação:
| Rota | Parâmetros | Posição |
|---|---|---|
GET {endpoint}/Api/PadesVisualPositioningPresets/Footnote | pageNumber (padrão -1, a última página); rows (padrão 1) | Um rodapé: as assinaturas ficam no fim da página, em um container com margens de 1 cm à esquerda, à direita e embaixo e altura para o número de linhas dado, preenchido de cima para baixo, da esquerda para a direita |
GET {endpoint}/Api/PadesVisualPositioningPresets/FootnoteBottomUp | pageNumber (padrão -1, a última página) | O container é a página inteira, menos uma margem de 1 cm em cada lado, e as linhas se empilham de baixo para cima |
GET {endpoint}/Api/PadesVisualPositioningPresets/NewPage | Nenhum | As assinaturas vão em uma nova página, com margem de 1 cm, como em pageNumber 0 |
Os três presets usam retângulos de assinatura de 4,2 x 1,8 cm, com espaço de 0,3 cm entre as linhas. Em uma página A4 em retrato, isso dá 4 assinaturas por linha.
Por exemplo, GET {endpoint}/Api/PadesVisualPositioningPresets/Footnote?pageNumber=-1&rows=2 devolve uma posição para duas linhas de assinaturas no fim
da última página, o que comporta até 8 assinaturas em A4 em retrato.
Exemplos
Rodapé com uma única linha
As assinaturas ficam no fim da última página, em uma única linha: em A4 em retrato, até 4 assinaturas. É o preset Footnote com uma linha, com texto e
imagem. Em uma sessão de assinatura:
POST {endpoint}/api/signature-sessions
{
...
"pdfSignatureOptions": {
"visualRepresentation": {
"text": {
"text": "Assinado digitalmente por {{name}}\nCPF: {{br_cpf_formatted}}",
"fontSize": 9,
"includeSigningTime": true,
"horizontalAlign": "Left",
"container": { "left": 0.2, "top": 0.2, "right": 0.2, "bottom": 0.2 }
},
"image": {
"resource": { "url": "https://example.com/seal.png" },
"opacity": 40,
"horizontalAlign": "Right",
"verticalAlign": "Center"
},
"position": {
"pageNumber": -1,
"measurementUnits": "Centimeters",
"auto": {
"container": { "left": 1.0, "right": 1.0, "bottom": 1.0, "height": 1.8 },
"signatureRectangleSize": { "width": 4.2, "height": 1.8 },
"rowSpacing": 0.3,
"horizontalDirection": "LeftToRight",
"verticalDirection": "TopDown"
}
}
}
}
}
Um quinto signatário não teria representação visual: veja o aviso acima.
Os PKI Suite Samples usam esse tipo de representação visual, com posicionamento automático na última página e um retângulo de assinatura maior:
Duas linhas, para até 8 signatários
Para duas linhas, a altura do container é a altura de duas linhas mais o espaço entre elas: 2 x 1,8 + 0,3 = 3,9 cm. O restante é igual ao exemplo
anterior, então só a position é mostrada:
"position": {
"pageNumber": -1,
"measurementUnits": "Centimeters",
"auto": {
"container": { "left": 1.0, "right": 1.0, "bottom": 1.0, "height": 3.9 },
"signatureRectangleSize": { "width": 4.2, "height": 1.8 },
"rowSpacing": 0.3,
"horizontalDirection": "LeftToRight",
"verticalDirection": "TopDown"
}
}
Um retângulo fixo, em uma assinatura em duas etapas
Uma assinatura em uma posição fixa da primeira página, só com o texto:
POST {endpoint}/api/signature
{
"file": {
"content": "JVBERi0x...",
"name": "document.pdf"
},
"certificate": {
"content": "MIIG..."
},
"signatureType": "Pdf",
"pdfSignatureOptions": {
"visualRepresentation": {
"text": {
"text": "Assinado por {{name}}",
"includeSigningTime": true
},
"position": {
"pageNumber": 1,
"measurementUnits": "Centimeters",
"manual": { "left": 2.5, "bottom": 2.5, "width": 7, "height": 3 }
}
}
}
}
No .NET
O cliente .NET não tem auxiliares dedicados para a representação visual: você a monta com os modelos da API, no namespace Lacuna.RestPki.Api.PadesSignature,
e a define na propriedade VisualRepresentation de PdfSignatureOptions (ou de StampPdfOptions, em um carimbo). As classes são
PadesVisualRepresentationModel, com PadesVisualTextModel, PadesVisualImageModel (cujo Resource é um ResourceContentOrReference) e
PadesVisualPositioningModel, que por sua vez tem um PadesVisualAutoPositioningModel ou, no posicionamento manual, um PadesVisualRectangleModel. As
propriedades têm os nomes dos campos JSON descritos acima, em PascalCase. Veja como o exemplo em .NET monta uma.
Veja também
- Assinaturas em duas etapas
- Sessões de assinatura
- Carimbos em PDF
- Tags da representação visual
- Marcas de validação em PDF, que não fazem parte da representação visual de uma assinatura