FrameworkDemoiselle.gov.brCommunity Documentation

Capítulo 5. Funcionalidades

5.1. Assinatura Digital no Formato PKCS1
5.2. Assinatura Digital no Formato PKCS#7/CAdES sem o conteúdo anexado (detached)
5.3. Assinatura Digital no Formato PKCS#7/CAdES com conteúdo anexado (attached)
5.4. Criação de Assinatura Digital enviando apenas o resumo (hash) do conteúdo
5.5. Co-Assinatura em arquivo único de assinatura .
5.5.1. Com envio de conteúdo
5.5.2. Enviando apenas o Hash do conteúdo
5.6. Validação de assinatura PKCS7 sem o conteúdo anexado (dettached)
5.7. Validação de assinatura PKCS7 com o conteúdo anexado (attached)
5.8. Validação de assinatura PKCS7 enviando apenas o resumo (Hash) do conteúdo
5.9. Leitura do conteúdo anexado (Attached) a uma assinatura PKCS7
5.10.

Este componente provê mecanismos de assinatura digital baseado nas normas ICP-Brasil e implementa mecanismos de assinatura digital em dois formatos: PKCS1 e PKCS7. A maior diferença entre esses dois mecanismos está na forma de envelopamento da assinatura digital, onde o PKCS1 não possui um formato de envelope, sendo o resultado da operação de assinatura a própria assinatura, já o PKCS7 possui um formato de retorno que pode ser binário (especificado na RFC5126) ou XML.

A interface org.demoiselle.signer.policy.impl.cades.Signer especifica o comportamento padrão dos mecanismos de GERAÇÃO de assinatura digital. O componente especializa essa interface em mais duas, são elas: org.demoiselle.signer.policy.impl.cades.pkcs1.PKCS1Signer para implementações de mecanismos PKCS1 e org.demoiselle.signer.policy.impl.cades.pkcs7.PKCS7Signer para implementações de mecanismos de envelopamento PKCS7.

Para as funções de VALIDAÇÃO A interface org.demoiselle.signer.policy.impl.cades.Checker especifica as funções de validação de assinatura digital. O componente especializa essa interface em mais duas, são elas: org.demoiselle.signer.policy.impl.cades.pkcs1.PKCS1Checker para implementações de mecanismos PKCS1 e org.demoiselle.signer.policy.impl.cades.pkcs7.PKCS7Checker para implementações de mecanismos de envelopamento PKCS7.

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, por exemplo, a aplicação deverá montar um array de bytes com o conteúdo do arquivo e enviar este para o componente poder assiná-lo. Também é possível enviar apenas o Hash já calculado deste arquivo. Veja nas sessões abaixo como fazê-los.

Para assinar um dado através do componente demoiselle-signer é preciso executar alguns passos.

A seguir temos um fragmento de código que demonstra uma assinatura no formato PKCS1.



/* conteudo a ser assinado */
byte[] content = "conteudo a ser assinado".getBytes();
/* chave privada */
PrivateKey chavePrivada = getPrivateKey(); /* implementar metodo para pegar chave privada */
/* construindo um objeto PKCS1Signer atraves da fabrica */
PKCS1Signer signer = PKCS1Factory.getInstance().factory();
/* Configurando o algoritmo */
signer.setAlgorithm(SignerAlgorithmEnum.SHA1withRSA);
/* Configurando a chave privada */
signer.setPrivateKey(chavePrivada);
/* Assinando um conjunto de bytes */
byte[] signature = signer.doSign(content);

O formato PKCS#7 define o tipo de arquivo para assinatura. Já a ICP-Brasil define um conjunto mínimo de informações básicas para as assinaturas digitais para o padrão CAdES. São elas: Tipo de conteúdo, data da assinatura, algoritmo de resumo aplicado e a política de assinatura. O componente policy-impl-cades já monta o pacote final com três atributos obrigatórios: tipo de conteúdo, data da assinatura e o algoritmo de resumo. Então, para montar um PKCS7 padrão CAdEs ICP-Brasil é necessário informar ao objeto PKCS7Signer qual a política de assinatura a ser aplicada. Uma das formas de gerar a assinatura digital é criar um novo arquivo com a extensão .p7s (PKCS#7) que contém apenas a assinatura, assim independente do arquivo original. Porém para validação da assinatura, será necessário informar tanto o arquivo de assinatura quanto o conteúdo original.

A seguir temos um fragmento de código que demonstra a utilização do pacote PKCS7 padrão.



byte[] content = readContent("texto.txt"); /* implementar metodo de leitura de arquivo */
PKCS7Signer signer = PKCS7Factory.getInstance().factoryDefault();
signer.setCertificates(certificateChain);
signer.setPrivateKey(privateKey);
byte[] signature = signer.doDetachedSign(this.content);

A seguir temos um fragmento de código que demonstra a utilização do pacote PKCS7 padrão 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 CADES.



byte[] content = readContent("texto.txt"); /* implementar metodo de leitura de arquivo */
PKCS7Signer signer = PKCS7Factory.getInstance().factoryDefault();
signer.setCertificates(certificateChain);
signer.setPrivateKey(privateKey);
signer.setSignaturePolicy(PolicyFactory.Policies.AD_RB_CADES_2_2);
byte[] signature = signer.doDetachedSign(this.content);

Identica ao formato apresentado anteriormente, outra das formas de gerar a assinatura digital é incluir todo o conteúdo assinado no novo arquivo com a extensão .p7s (PKCS#7) Desta forma, tanto a assinatura quanto o conteúdo estarão dentro deste arquivo. A sua vantagem é que para validação da assinatura, basta enviar somente este arquivo. Porém, caso o arquivo original seja descartado, para ter acesso ao mesmo, será necessário o uso de um software especializado(como o próprio Demoiselle-Signer)

A seguir temos um fragmento de código que demonstra a utilização do pacote PKCS7 com o conteúdo anexado.



byte[] content = readContent("texto.txt"); /* implementar metodo de leitura de arquivo */
PKCS7Signer signer = PKCS7Factory.getInstance().factoryDefault();
signer.setCertificates(certificateChain);
signer.setPrivateKey(privateKey);
byte[] signature = signer.doAttachedSign(fileToSign);

Este procedimento visa facilitar a geração de assinaturas digitais em aplicações onde pode haver restrição de trafegar todo o conteúdo do arquivo pela rede, sendo necessário apenas o tráfego dos bytes do resumo do conteúdo original (HASH). Neste caso, é necessário gerar o HASH do conteúdo a ser assinado e passar para o assinador. Ao gerar o HASH, é importante dar atenção ao algoritmo a ser usado, pois na validação da assinatura será considerado o algoritmo da política escolhida. Então, para que esse procedimento funcione corretamente, é necessário escolher o algoritmo do HASH igual ao algoritmo da assinatura digital.




byte[] content = readContent("texto.txt"); /* implementar metodo de leitura de arquivo */
/* Gerando o HASH */
java.security.MessageDigest md = java.security.MessageDigest
                    .getInstance(DigestAlgorithmEnum.SHA_256.getAlgorithm());
byte[] hash = md.digest(content);
/* Gerando a assinatura a partir do HASH gerado anteriormente */
PKCS7Signer signer = PKCS7Factory.getInstance().factoryDefault();
signer.setCertificate(certificate);
signer.setPrivateKey(privateKey);
signer.setSignaturePolicy(PolicyFactory.Policies.AD_RB_CADES_2_2);
byte[] signature = signer.doHashSign(hash);

Como foi visto nas seções anteriores, um do modos de gerar a assinatura é criando um arquivo separado do conteúdo original, e a forma de validação está no fragmento de código abaixo.



byte[] content = readContent("texto.txt"); /* implementar metodo de leitura de arquivo */
byte[] signature = readContent("texto.pkcs7"); /* implementar metodo de leitura de arquivo */
CAdESChecker checker = new CAdESChecker();
List<SignatureInformations> signaturesInfo = checker.checkDetattachedSignature(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
    
    

A seguir temos um fragmento de código que demonstra a validação uma assinatura PKCS7 com o conteúdo anexado.



byte[] signature = readContent("texto.pkcs7"); /* implementar metodo de leitura de arquivo */
CAdESChecker checker = new CAdESChecker();
List<SignatureInformations> signaturesInfo = checker.checkAttachedSignature(signature);

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 = readContent("texto.txt"); /* implementar metodo de leitura de arquivo */
byte[] signature = readContent("texto.pkcs7"); /* implementar metodo de leitura de arquiv
CAdESChecker checker = new CAdESChecker();
// 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);

A seguir temos um fragmento de código que demonstra a extração (recuperação) do conteúdo de um arquivo anexado a uma assinatura PKCS7. Essa funcionalidade pode ser útil quando é necessário mostrar o conteúdo assinado, pois no formato anexado (attached) o conteúdo está empacotado na assinatura. Esta funcionalidade também permite que seja feita a validação da assinatura no momento da extração.



byte[] signed = readContent("texto.pkcs7"); /* implementar metodo de leitura de arquivo */
PKCS7Signer signer = PKCS7Factory.getInstance().factoryDefault();
/* Para extrair o conteudo original validando a assinatura */
byte[] content = signer.getAttached(signed, true);
/* Para extrair o conteudo original sem validar a assinatura */
byte[] content = signer.getAttached(signed, false);