Error signing xml passing PIN automatically

Asked

Viewed 160 times

4

I have this code that selects the certificate according to the serial passed:

public static X509Certificate2Collection SelecionarCertificado(string serial)
{
   X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
   var Key = new RSACryptoServiceProvider();
   store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
   X509Certificate2Collection collection = store.Certificates;
   X509Certificate2Collection fcollection = collection.Find(X509FindType.FindBySerialNumber, serial, true);

  return fcollection;
}

And this part here in the signature, to automatically pass the password:

SignedXml signedXml = new SignedXml(doc);

KeyInfo keyInfo = new KeyInfo();
//signedXml.SigningKey = x509Cert.PrivateKey;
keyInfo.AddClause(new KeyInfoX509Data(x509Cert));
RSACryptoServiceProvider Key = new RSACryptoServiceProvider();
Key = (System.Security.Cryptography.RSACryptoServiceProvider)x509Cert.PrivateKey;
signedXml.SigningKey = Key;
signedXml.KeyInfo = keyInfo;
signedXml.SigningKey = Certificados.LerDispositivo(Key, PIN);
signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;
reference.DigestMethod = SignedXml.XmlDsigSHA1Url;

But what happens, when I have two certificates on my machine, it returns invalid password. I changed the passwords to be equal, but in this case it does not return invalid PIN error, but it signs with the wrong certificate, which returns another error. It’s as if the consultation I make is worth nothing.

This is the function LerDispositivo()

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;
}

I’ve tried it line by line, changed a few things, and it still happens. If you only have one certificate connected, it works perfectly, everything indicates that it takes the first certificate in alphabetical order, because when I’m signing the other does not return the problem.

EDIT

Analyzing the code, I came to the conclusion that the two connected certificates have the same name/ProviderName:

csp.ProviderName = key.CspKeyContainerInfo.ProviderName;
csp.ProviderType = key.CspKeyContainerInfo.ProviderType;

That’s why he’s confusing, there’s some way to differentiate, so he knows the right certificate ?

  • Mariana, have you tried to move to the function LerDispositivo the object representing the type certificate X509Certificate2, as I suggested in that answer https://answall.com/a/347796/86952, instead of passing an object of the type https://answall.com RSACryptoServiceProvider (that’s how you’re doing)?

  • @Pedrogaspar I had to do it again this way, because I had numerous problems, and this happens. I don’t know if it caches, how it works, what really happens, because when I enter the function LerDispositivo() i can’t see which certificate is selected on time. But when it selects the certificate, the x509Cert comes with the correct certificate, so I do not understand why it selects the other. If it is something that remains to pass, something like.

  • @Pedrogaspar I edited the question, explaining what I suspect it is.

  • How you take the certificate from the collection returned by the function SelecionarCertificado? You have already made sure that the certificate returned by this function is the correct certificate?

  • @Pedrogaspar yes, he gets the correct certificate there, the problem is here key.CspKeyContainerInfo.ProviderName because both certificates have equal names, so he always takes the first one. With the help of this link https://www.oipapio.com/question-1951681 I was able to solve.

1 answer

2


In function LerDispositivo() change the line:

csp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseDefaultKeyContainer;

for:

csp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseExistingKey;

See what the Enum documentation says CspProviderFlags (used on the property CspParameters.Flags):

UseDefaultKeyContainer => Use key information from the default key container.
UseExistingKey => Use key information from the Current key.

It is also worth remembering that the serial number of the certificate is not totally unique, maybe it is better to use the thumbprint to uniquely identify each certificate, using the option X509FindType.FindByThumbprint instead of the option X509FindType.FindBySerialNumber:

What is the Difference between serial number and thumbprint? - Information Security Stack Exchange

Although I don’t think this affects your current context, since the two certificates apparently come from the same supplier.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.