amagovpt / autenticacao.gov

Middleware Oficial de Identificação Eletrónica em Portugal - Cartão de Cidadão, da Chave Móvel Digital e Sistema de Certificação de atributos profissionais
https://www.autenticacao.gov.pt
European Union Public License 1.2
168 stars 33 forks source link

Assinatura em lote com recurso a KeyStore/PKCS11 #144

Open lflobo opened 1 year ago

lflobo commented 1 year ago

Boa tarde,

Até à data temos estado a usar o projeto POReID na assinatura digital de documentos, com algumas modificações para permitir a assinatura em lote de documentos, nomeadamente com a KeyStore provider do tipo POReID. Porque se baseia numa versão desatualizada do libPCSC4Java, não conseguimos migrar a nossa plataforma para dispositivos mais recentes (Apple Silicon e Windows 11 based...).

Com o novo SDK/bibliotecas fornecidas conseguimos assinar um documento sem problemas com o método pkcs11 em Java usando o java.security com algo como:

Provider p = Security.getProvider("SunPKCS11");
// ...
KeyStore ks = KeyStore.getInstance("PKCS11", provider);
ks.load(null, null /* ignored password */);
// ...
PdfSigner signer = ...;
signer.signDetached(...) // passando as chaves extraídas da KeyStore

No entanto, como a vossa implementação ignora a password (PIN?) no método KeyStore.load(...) cada assinatura digital implica um popup, tornando a keyStore não viável para assinaturas em lote!

Reparei que o tema da cache do PIN já veio à discussão (#11), para o SDK.

Calculo que haja preocupações de segurança para não expor o PIN na memória, mas o processo de assinatura em lote (PTEID_PDFSignature.addToBatchSigning(...)) terá que fazer algum tipo de caching... Calculo também que os hacks que estão a ser usados pelos developers para dar a volta à limitação são bem piores do que fazer a cache local do PIN.

A questão é - existe alguma forma de assinar em lote usando a KeyStore do tipo PKCS11 exposta pela biblioteca pteidpkcs11 sem alterar o código original, recompilar e fornecer os .dll/.dylib/.so junto com a nossa solução?

Obrigado desde já, Cumprimentos, LL

agrr commented 1 year ago

Pedimos desde já desculpa pelo atraso na resposta.

Não existe de facto forma de utilizar a funcionalidade de assinatura em lote através do módulo pteid-pkcs11. O módulo PKCS#11 implementa a assinatura de blocos de dados sem qualquer trade-off de segurança, ou seja, exige uma introdução do PIN para cada operação criptográfica tal como o smartcard do Cartão de Cidadão está desenhado.

A nossa sugestão se pretende utilizar a assinatura em lote é mesmo de usar a classe PTEID_PDFSignature com o método addToBatchSigning que guarda de facto o PIN em memória apenas durante a execução das N assinaturas do lote.

lflobo commented 1 year ago

Obrigado pela resposta.

O método PTEID_PDFSignature::addToBatchSigning seria facilmente utilizável se permitisse adição de byte[] ao batch em vez de paths. No nosso cenário, e na maioria dos cenários heterogéneos em termos de S.O, a criação de um ficheiro {x}.pdf por cada item na batch e a recolha dos ficheiros {x}_signed.pdf é problemática/errática.

Seria ideal ter a opção de o batch signing poder também ocorrer completamente em memória.

Protótipos do tipo:

void PTEID_PDFSignature::addInMemoryBatchSigning(byte[] data)
// para não quebrar o flow atual
void PTEID_PDFSignature::addInMemoryListener(SignListener listener)

Na impossibilidade de implementar desta forma:

// disparado sempre que a assinatura de um ficheiro é terminada
void PTEID_PDFSignature::addSignListener(FileSignListener listener)

Neste último, o FileSignListener receberia um handle que permitiria obter e descartar o ficheiros original e o assinado.

À vossa superior consideração...

Obrigado mais uma vez, Cumprimentos, LL