FrameworkDemoiselle.gov.brCommunity Documentation

Capítulo 9. Funcionalidades

9.1. Assinatura enviando contédo
9.2. Validação de assinatura com contéudo
9.3. Validação de assinatura enviando apenas o resumo (Hash) do conteúdo
9.4. Tratando os resultados da valiação
9.5.

Este componente provê mecanismos de assinatura digital baseado nas normas ICP-Brasil e implementa mecanismos de assinatura digital para serem incorparadas em arquivo PDF

A interface org.demoiselle.signer.policy.impl.pades.pkcs7.PCKS7Signer provê as funcionalidades de Assinatura.

Para as funções de VALIDAÇÃO temos a interface org.demoiselle.signer.policy.impl.pades.PCKS7Checker

Este componente, até a presente versão, permite assinar dados representados por um array de bytes. Então se for necessário a assinatura de um arquivo PDF, por exemplo, a aplicação deverá montar um array de bytes com o conteúdo a ser assinado e enviar este para o componente poder assiná-lo. Também é possível enviar apenas o Hash já calculado deste conteúdo. A manipulação do arquivo PDF pode ser feito com ferramentas como o Apache PDFBox®

Para assinar um dado através do componente policy-impl-pades é preciso executar alguns passos.

O formato PAdES define o formato para assinatura. Já a ICP-Brasil define um conjunto próprio de informações básicas para as assinaturas digitais chamado PBAD-PAdES. Esse tipo de Assinatura não é reconhecido automaticamente pelos leitores de PDF como o Adobe Reader. No caso do Adobe há um plugin desenvolvido pelo ITI que permite que esse formato seja reconhecido, o plugin está disponível neste link (clique aqui)

A seguir temos um fragmento de código que demonstra a utilização do componente



 byte[] content = // implentar leitura do cont�udo do arquivo em PDF
 KeyStore ks = getKeyStoreToken();
 String alias = getAlias(ks);
 PAdESSigner signer = new PAdESSigner();
 signer.setCertificates(ks.getCertificateChain(alias));
 // para token
 signer.setPrivateKey((PrivateKey) ks.getKey(alias, null));
 byte [] assinatura =signer.doDetachedSign(content);

A seguir temos um fragmento de código que demonstra a utilização do componente com informação da política de assinatura. Neste caso podemos escolher uma das políticas (em vigor) que já acompanham o componente e referem-se à Assinatura Digital padrão PAdES.

  • AD_RB_PADES_1_1 Refere-se à Assinatura Digital de Referência Básica versão 1.1;
  • AD_RT_PADES_1_1 Refere-se à Assinatura Digital de Referência Temporal (com carimbo de tempo) versão 1.1;


 byte[] content = // implentar leitura do cont�udo do arquivo em PDF
 KeyStore ks = getKeyStoreToken();
 String alias = getAlias(ks);
 PAdESSigner signer = new PAdESSigner();
 signer.setCertificates(ks.getCertificateChain(alias));
 // para token
 signer.setPrivateKey((PrivateKey) ks.getKey(alias, null));
 signer.setSignaturePolicy(PolicyFactory.Policies.AD_RT_PADES_1_1);
 byte [] assinatura =signer.doDetachedSign(content);

Importante

Caso não seja especificada nenhuma política, o componente assumirá a política padrão AD_RB_PADES_1_1.

Como já foi comentado, o componente até a presente versão não lê o arquivo PDF para validar a Assinatura, por isso é preciso que a aplicação extraia o conteúdo e a Assinatura e envie os dois separados para o componente



byte[] content = /* implementar metodo de leitura do PDF para extrair o conte�do assinado */
byte[] signature = /* implementar metodo de leitura do PDF para extrair a assinatura */
PAdESChecker checker = new PAdESChecker();
List<SignatureInformations> signaturesInfo = checker.checkDetachedSignature(content, signature);

O retorno é um objeto do tipo org.demoiselle.signer.policy.impl.cades.SignatureInformations que possui os seguintes atributos



public class SignatureInformations {
    private LinkedList<X509Certificate> chain; // cadeia do certificado que gerou a assinatura 
    private Date signDate;  // data do equipamento no momento da gera��o das assinatura (n�o tem validade legal)
    private Timestamp timeStampSigner = null; // Carimbo de tempo da assinatura, quando a politica utilizada permitir
    private SignaturePolicy signaturePolicy; // Politica ICP-BRASIL usada para gera��o da assinatura
    private LinkedList<String> validatorErrors = new LinkedList<String>();  // Lista de erros que por ventura possam ter sido encontrados na valida��o da assinatura
    
    

Da mesma forma que possibilitamos a criação da assinatura enviando o resumo (hash) calculado do conteúdo, podemos também fazer a validação da mesma forma. Assim como na geração, é preciso saber qual foi o algoritimo de resumo (hash) que foi usado para gerar a assinatura, pois o mesmo deve ser informado para o método de validação. A seguir temos um fragmento de código que demonstra esta validação.



byte[] content = /* implementar metodo de leitura do PDF para extrair o conte�do assinado */
byte[] signature = /* implementar metodo de leitura do PDF para extrair a assinatura */
PAdESChecker checker = new PAdESChecker();
// gera o hash do arquivo que foi assinado
md = java.security.MessageDigest
            .getInstance(DigestAlgorithmEnum.SHA_256.getAlgorithm());
byte[] hash = md.digest(content);
List<SignatureInformations> signaturesInfo = checker.checkSignatureByHash(SignerAlgorithmEnum.SHA256withRSA.getOIDAlgorithmHash(), hash, signature);

Como é possível que um mesmo arquivo possa contar várias assinaturas (PAdES principalmente), só será gerada exceção quando a assinatura estiver comprometida Nos demais casos, o Demoiselle-Signer irá devolver o resultado numa lista de objetos SignatureInformations. Essa classe contém os seguintes atributos:

Cabe ao sistema com base nos avisos ou erros, aceitar ou não a Assinatura. Apesar de existirem as políticas, qualquer tipo de Assinatura gerada com um certificado ICP-Brasil tem validade legal. A seguir temos um fragmento de código que demonstra esta validação.



List<SignatureInformations> signaturesInfo = checker
                .checkDetachedSignature(fileToVerify, signatureFile);
        if (signaturesInfo != null) {
            System.out.println("A assinatura foi validada. e retornou resultados");
            for (SignatureInformations si : signaturesInfo) {
                System.out.println(si.getSignDate());
                if (si.getTimeStampSigner() != null) {
                    System.out.println("Serial"
                            + si.getTimeStampSigner().toString());
                }
                System.out.println("informa��es do assinante:");
                BasicCertificate certificate = si.getIcpBrasilcertificate();
                if (!certificate.isCACertificate()) {
                    if (certificate.hasCertificatePF()) {
                        System.out.println("CPF: "+certificate.getICPBRCertificatePF().getCPF());
                        System.out.println("Titulo de Eleitor: "+certificate.getICPBRCertificatePF().getElectoralDocument());
                    }
                    if (certificate.hasCertificatePJ()) {
                        System.out.println("CNPJ: "+certificate.getICPBRCertificatePJ().getCNPJ());
                    }
                }
                // Carimbo do tempo
                if(si.getTimeStampSigner()!= null) {
                    
                    System.out.println(si.getTimeStampSigner().toString());
                }
                // A assinatura pode estar correta mas n�o foi poss�vel verificar algum atributo exigido pela ICP-Brasil
                for (String valErr : si.getValidatorErrors()) {
                    System.err.println("++++++++++++++ ERROS ++++++++++++++++++");
                    System.err.println(valErr);
                }
                //A assinatura pode estar correta mas n�o foi poss�vel verificar alguma condi��o de valida��o exigida pela ICP-Brasil
                for (String valWarn : si.getValidatorWarnins()) {
                    System.err.println("++++++++++++++ AVISOS ++++++++++++++++++");
                    System.err.println(valWarn);
                }
            }