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
164 stars 33 forks source link

Cache do PIN de autenticação em W10 #11

Open Graz21 opened 4 years ago

Graz21 commented 4 years ago

Viva,

Temos um mecanismo de assinatura de hashes de dados da nossa aplicação que precisam de ser assinados com vários certificados, sendo um deles o do CC.

Estamos a ter um problema a fazer cache do PIN em W10. No W7 apenas pede o PIN uma vez, sendo que aparentemente houve uma alteração ao nível do Crypto API do Windows que causa esta diferença de comportamento.

Método que estamos a usar para assinar:

        public static string MSWindowsSignX509(string data, bool chkSignature, string timestampServer, X509Certificate2 selectedCertificate) {

            CmsSigner oSigner = null;
            SignedCms oSignedData = null;
            string signedHash = String.Empty;

            try {

                //Get the certificate from user, if user has only one, 
                //use it else ask user which one to use
                oSigner = new CmsSigner();

                oSigner.Certificate = selectedCertificate;

                byte[] arrDataHashed = HashSHA1(data);

                // hash the text to sign
                ContentInfo info = new ContentInfo(arrDataHashed);

                // put the hashed data into the signedData object
                oSignedData = new SignedCms(info);

                if (string.IsNullOrEmpty(timestampServer)) {
                    oSigner.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
                }
                else {
                    TimeStampToken tsToken = GetTSAToken(arrDataHashed, timestampServer);

                    AsnEncodedData timeData = new Pkcs9AttributeObject(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificate.Id, tsToken.GetEncoded());
                    oSigner.UnsignedAttributes.Add(timeData);
                    oSigner.SignedAttributes.Add(new Pkcs9SigningTime(tsToken.TimeStampInfo.GenTime.ToLocalTime()));
                }

                // sign the data
                oSignedData.ComputeSignature(oSigner, false);

                //oSigner.Certificate.Reset();
                signedHash= Convert.ToBase64String(oSignedData.Encode());

            }
            catch (Exception ex) {
                return ex.Message;
            }

            return signedHash;
        }

Estive a ver se seria possível implementar a assinatura em lote de dados utilizando o SDK, à semelhança do que já têm para os PDF's, mas mesmo assim cada vez que o método Sign é chamado, aparece o dialog de introdução do PIN.

Também tentei adicionar a chave de registo "Computer\HKEY_LOCAL_MACHINE\SOFTWARE\PTEID\general\auth_pin_cache_normal" com o valor 1, mas o comportamento é igual.

Conhecem alguma maneira de dar a volta a este comportamento não utilizando o SDK ou está no vosso roadmap implementar um método de assinatura dados em lote ?

cristiano2lopes commented 4 years ago

Adiciono ao pedido inicial a possibilidade de assinar em lote, com cache do pin the assinatura. Penso que ambos fazem todo o sentido.

Alguma possibilidade de partilharem se faz parte do roadmap próximo ?

cristiano2lopes commented 4 years ago

@Graz21 Como podes ver no PR #26 tenho uma solução no meu fork para o problema que indicas. Já utilizo com sucesso para assinar hashes com o certificado de assinatura.

Se quiseres falar sobre o problema conta.

Graz21 commented 4 years ago

Viva,

Assinar em bulk com o certificado de assinatura faz sentido que não faça cache do PIN, tendo em conta que é um certificado de não repúdio. Isto vai de encontro às normas europeias (apesar de esta cache ser feita quando o método de assinatura de PDFs em bulk do SDK é utilizado).

Com o certificado de autenticação a cache não está mesmo a ser feita no CSP quando não é utilizado o SDK (já testei com a versão 3.1.0).

A opção que tomamos foi forçar a cache, através da CrypoAPI, no método que usamos para assinar hashes em bulk.