Em dezenas de artigos eu vi métodos que adicionam o PIN automaticamente, mas nenhum funcionava, inclusive alguns fizeram eu até perder o certificado do cartão.
Essa parte abaixo costumam usar nos métodos:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); RSACryptoServiceProvider.UseMachineKeyStore = true; rsa.PersistKeyInCsp = false;
Com essas duas propriedades, linha 2 e 3, ela apagava o PIN do cartão ou fazia não funcionar a senha.
Método para adicionar o PIN / Senha no certificado A3 automaticamente.
public static RSACryptoServiceProvider LerDispositivo(RSACryptoServiceProvider key, string PIN) { CspParameters csp = new CspParameters(key.CspKeyContainerInfo.ProviderType, key.CspKeyContainerInfo.ProviderName); SecureString ss = new SecureString(); foreach (char a in PIN) { ss.AppendChar(a); } csp.ProviderName = key.CspKeyContainerInfo.ProviderName; csp.ProviderType = key.CspKeyContainerInfo.ProviderType; csp.KeyNumber = key.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2; csp.KeyContainerName = key.CspKeyContainerInfo.KeyContainerName; csp.KeyPassword = ss; csp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseDefaultKeyContainer; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); return rsa; }
Abaixo coloquei o método que desenvolvi para assinar o arquivo XML e que assina o método de adicionar o PIN no cartão, automaticamente, sem fazer nada manualmente:
public static XmlDocument Assinar(string mensagemXML, X509Certificate2 certificado) { System.Xml.XmlDocument xmlDoc = new XmlDocument(); RSACryptoServiceProvider Key = new RSACryptoServiceProvider(); SignedXml SignedDocument = default(SignedXml); KeyInfo keyInfo = new KeyInfo(); xmlDoc.LoadXml(mensagemXML); Key = (System.Security.Cryptography.RSACryptoServiceProvider)certificado.PrivateKey; keyInfo.AddClause(new KeyInfoX509Data(certificado)); SignedDocument = new SignedXml(xmlDoc); SignedDocument.SigningKey = Key; SignedDocument.KeyInfo = keyInfo; SignedDocument.SigningKey = LerDispositivo(Key, "Coloque aqui o PIN, ex: "1234" "); Reference reference = new Reference(); reference.Uri = string.Empty; reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); reference.AddTransform(new XmlDsigC14NTransform(true)); SignedDocument.AddReference(reference); SignedDocument.ComputeSignature(); System.Xml.XmlElement xmlDigitalSignature = SignedDocument.GetXml(); xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true)); return xmlDoc; }
Abaixo coloquei o método que utilizo para escolher o certificado, caso alguém esteja procurando por isso também:
public static X509Certificate2 EscolherCertificado() { var store = new X509Store("MY", StoreLocation.CurrentUser); X509Certificate2 x509 = null; var Key = new RSACryptoServiceProvider(); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2Collection collection = store.Certificates; X509Certificate2Collection fcollection = collection.Find(X509FindType.FindBySerialNumber, "Serial do certificado aqui", false); if (fcollection.Count == 1) { return fcollection[0]; } else { //Aqui pode colocar para escolher manualmente o certificado. } }
Muito bom Renan,
Ajudou muito.
Obrigado
Tem como adicionar tambem no certificado A1, estou tendo problemas quando é ele
Desculpe, mas nunca utilizei o A1
Boa tarde, muito bom o seu artigo, ajudou bastante, obrigado pela publicação.
Boa Tarde, muito bom o artigo, me ajudou muito, porém estou com um dúvida, porque esta função de incluir o PIN no código não funciona no asp.net Core ? Ele sempre me retorna este erro: InvalidCastException: Unable to cast object of type ‘System.Security.Cryptography.RSACng’ to type ‘System.Security.Cryptography.RSACryptoServiceProvider’.
Tambem com esse problema. 🙁
Ola amigo como chamo o metodo em um button.
Funcionou lindamente!
Muito obrigado!
como que voce implementou isso no seu codigo?
consegue me ajudar?
Boa tarde!
Há como fazer para verificar a assinatura de um PDF?