FrameworkDemoiselle.gov.brCommunity Documentation
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);
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:
chain;
Lista X509Certificate com a cadeia completa do certificado do Assinante
signDate
A data do equipamento onde foi gerada a assinatura, e serve apenas como referência, não tem nenhuma validade legal
timeStampSigner
É o carimbo do Tempo (Timestamp) incluído na Assinatura, é a prova legal da data e hora que a Assinatura foi gerada.
signaturePolicy;
A política (SignaturePolicy) que foi usada para gerar a Assinatura
notAfter;
A data de validade do Certificado do Assinante
validatorWarnins
Lista de Avisos. A assinatura pode estar correta mas não foi possível verificar algum atributo exigido por uma política da ICP-Brasil, que serão listados aqui
validatorErrors
Lista de Erros. A assinatura pode estar correta mas não foi possível verificar alguma condição de validação exigida pela ICP-Brasil
invalidSignature
valor booleano, que indica que Assinatura não está válida
icpBrasilcertificate
BasicCertificate do Assinante
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);
}
}