Search code examples
c#xml.net-4.0x509certificate2

"Key not valid for use in specified state" while trying to Sign a Xml


My History:

I need to sign all my Xml's before uploading to the government agency. To sign, I'm using client certificates loaded from the X509Store:

var repo = new X509Store("My", StoreLocation.CurrentUser);

repo.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

foreach (X509Certificate2 certCurrent in repo.Certificates)
{
    if (!certCurrent.Subject.Equals(subject)) continue;

    if (certCurrent.NotAfter > DateTime.Now)
    {
        repo.Close();
        return certCurrent;
    }
}

repo.Close();
return null;

And SignedXml (XmlDocument xmlDoc, string id, X509Certificate2 certificate):

var refer = new Reference();
refer.Uri = "#" + id;
refer.AddTransform(new XmlDsigEnvelopedSignatureTransform());
refer.AddTransform(new XmlDsigC14NTransform());

var signedXml = new SignedXml(xmlDoc);
signedXml.SigningKey = certificate.PrivateKey;
signedXml.AddReference(refer);

signedXml.ComputeSignature();

var key = new KeyInfo();
key.AddClause(new KeyInfoX509Data(certificate));
signedXml.KeyInfo = key;

//Final signature xml block.
XmlElement signedBlock = signedXml.GetXml();

Problem:

One of my clients changed his PC password and out of nothing the second block of code throws this error:

Message - 
    Key not valid for use in specified state.
Type - 
    CryptographicException
Source - 
    mscorlib
TargetSite - 
    System.Security.Cryptography.SafeProvHandle CreateProvHandle(System.Security.Cryptography.CspParameters, Boolean)
StackTrace - 
    at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
    at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
    at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
    at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
    at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
    at Util.SignXml.Sign(XmlDocument xmlDoc, String id, X509Certificate2 certificate, String& error)

It says that the getter of the PrivateKey is throwing that exception. Later, I'll try to install that certificate again, with the Exportable checked.

PS: Windows Server 2003


Solution

  • Since my client changed his password, the certificate needed to be installed again.

    That's it.