demoiselle / signer

Repositório que contém os componentes para facilitar a implementação de assinatura digital nos padrões da ICP-BRASIL
https://www.frameworkdemoiselle.gov.br/v3/signer/
GNU Lesser General Public License v3.0
148 stars 73 forks source link

Obter raw signature de um arquivo PKCS7 #416

Closed TiagoLoose closed 1 week ago

TiagoLoose commented 3 months ago

Olá, se alguém puder me auxiliar na seguinte dúvida.

Estou usando o Assinador SERPRO integrado com minha aplicação web, seguindo a documentação em https://www.assinadorserpro.estaleiro.serpro.gov.br/minimalista/tutorial/.

Pelo que percebi o resultado da assinatura é sempre um arquivo PKCS7.

Minha aplicação precisa enviar para um webservice de terceiro um documento com os seguintes campos: conteúdo, cadeiaCertificado, assinatura, entre outros.

Obter o conteúdo e cadeia do certificado do arquivo PKCS7 eu consegui.

O problema está em obter a assinatura, hash da assinatura ou raw signature.

Alguém sabe como posso conseguir isso?

icemagno commented 3 months ago

Eu estou usando assim:

    public byte[] verify( byte[] signed ) {
        logger.info("Validando a assinatura");
        CAdESChecker checker = new CAdESChecker();
        AttachedContentValidation acv = checker.getAttached(signed, true);
        byte[] content = acv.getExtractedContent();
        List<SignatureInformations> sigData = acv.getSignaturesInfo();
        logger.info("Assinado por: ");
        for (SignatureInformations si : sigData) {
            CertificateManager cm = new CertificateManager( si.getIcpBrasilcertificate().getX509Certificate() );
            CertICPBrasil cert = cm.load(CertICPBrasil.class);
            logger.info("  Nome.........:" + cert.getNome());
            logger.info("  CPF..........:" + cert.getCpf());
            logger.info("  ID...........:" + cert.getId());
            logger.info("  CEI..........:" + cert.getCei());
            logger.info("  BIRTH........:" + cert.getBirthDate());
            logger.info("  E-mail.......:" + cert.getEmail());
            logger.info("  Cert-Level...:" + cert.getCert_level());
            logger.info("  Cert-Type....:" + cert.getCert_type());
            logger.info("  ID Dispacher.:" + cert.getId_dispatcher());
            logger.info("  UF Dispacher.:" + cert.getUf_dispatcher());          
        }
        return content;
    }
esaito commented 3 months ago

A assinatura é um pacote PCKS7. O Assinador devolve o Array de Bytes ( RAW) do PCKS7 codificado em base64 que é melhor forma de trafegar o Array de Bytes via Json. Se esse serviço de um terceiro precisa receber a assinatura (provavelmente para validá-la), é o pacote PCKS7 que ele precisaria. Teria que ver com o terceiro qual o formato exato que ele precisa.

icemagno commented 3 months ago

Bom... para o conteúdo assinado, eu consigo em byte[] content = acv.getExtractedContent(); A cadeia de certificação do assinante acho que tem em List<SignatureInformations> sigData = acv.getSignaturesInfo();

Provavelmente ele tá se referindo ao método "detached" de assinar.

Eu costumo atachar a assinatura, o certificado do assinante e o dado assinado no mesmo pacote.

AttachedContentValidation acv = checker.getAttached(signed, true);

TiagoLoose commented 3 months ago

Olá pessoal, obrigado pelas respostas.

Obter a cadeia do certificado eu consegui usando:

List<SignatureInformations> signaturesInfo = attached.getSignaturesInfo();

LinkedList<X509Certificate> chain = signaturesInfo.get(0).getChain();

Obter o conteúdo assinado:

AttachedContentValidation attached = checker.getAttached(arquivo, true);

byte[] content = attached.getExtractedContent();

Mas a assinatura ainda não obtive sucesso, tentei da seguinte forma abaixo mas parece não ser o que preciso:

CMSSignedData signedData = new CMSSignedData(p7sBytes);

byte[] encodedSignature = null;

Optional<SignerInformation> signerInformation = signedData.getSignerInfos().getSigners().stream().findFirst();

if (signerInformation.isPresent()) {
    encodedSignature = signerInformation.get().getSignature();
}

Explicando um pouco mais, temos um sistema muito utilizado que já armazena os dados das assinaturas dessa forma (cadeiaCertificado, assinatura, conteúdo assinado).

Esse sistema envia os arquivos para o sistema PJe dessa forma também.

O PJe aceita arquivo P7S mas para isso teria que alterar toda implementação existente no nosso sistema.

Sigo aqui investigando, a intenção é não fazer esse refactory no nosso sistema.

icemagno commented 3 months ago

Então.. como eu disse acima, os dados de assinatura eu pego com:

        AttachedContentValidation acv = checker.getAttached(signed, true);
        byte[] content = acv.getExtractedContent();
        List<SignatureInformations> sigData = acv.getSignaturesInfo();
        logger.info("Assinado por: ");
        for (SignatureInformations si : sigData) {
           ... 
        }

Acredito que o que vc quer está na variável "si" do "for" acima ... Eu ainda não entendi bem a razão de vc decompor o PKCS#7 e armazenar a assinatura e os outros componentes separados ( dado assinado, assinatura, assinante, ... ). Eu armazeno o PKCS#7 inteiro e só executo a validação quando necessário....

signer

TiagoLoose commented 3 months ago

Então.. como eu disse acima, os dados de assinatura eu pego com:

        AttachedContentValidation acv = checker.getAttached(signed, true);
        byte[] content = acv.getExtractedContent();
        List<SignatureInformations> sigData = acv.getSignaturesInfo();
        logger.info("Assinado por: ");
        for (SignatureInformations si : sigData) {
           ... 
        }

Acredito que o que vc quer está na variável "si" do "for" acima ... Eu ainda não entendi bem a razão de vc decompor o PKCS#7 e armazenar a assinatura e os outros componentes separados ( dado assinado, assinatura, assinante, ... ). Eu armazeno o PKCS#7 inteiro e só executo a validação quando necessário....

signer

Não @icemagno, o que eu quero não está em SignatureInformations si.

A razão é que o sistema foi desenvolvido assim e agora pretendo integra-lo ao assinador Serpro. Simplesmente isso, não quero saber a melhor forma, queria tirar essa dúvida que postei.