Why do I get an Access Denied error when creating an X509Certificate2 object?

Aaron Jensen picture Aaron Jensen · Mar 8, 2013 · Viewed 11.5k times · Source

We have some unit tests which have PFX certificates embedded in them. These certificates are read during test execution and turned into X509Certificate2 objects. Unfortunately, when run as an unprivileged user, we get Access Denied exceptions:

using (var s = EmbeddedResourceUtilities.GetEmbeddedResourceAsStream(typeThatContainsEmbeddedResource, certFileName))
{
    if (s == null)
    {

        throw new ApplicationException(String.Format("Embedded certificate {0} for type {1} not found.", certFileName, typeThatContainsEmbeddedResource.FullName));
    }

    try
    {
        var bytes = new byte[s.Length];
        s.Read(bytes, 0, (int)s.Length);
        return new X509Certificate2(bytes);
    }
    catch (Exception ex)
    {
        throw new ApplicationException(String.Format("Error loading embedded certificate {0} for type {1}.", certFileName, typeThatContainsEmbeddedResource.FullName), ex);
    }
}

Here's the exception:

System.Security.Cryptography.CryptographicException : Access denied.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData)

I've tried modifying the constructor to use an empty password and explicit keyset flags, but that doesn't fix it:

// this doesn't work, either
return new X509Certificate2(bytes, String.Empty, X509KeyStorageFlags.MachineKeySet);

I've read elsewhere that I should give my unprivileged user increased permissions on the MachineKeys directory, but I'm loathe to do that as it would allow production code to assume those permissions are available on that directory outside the test environment.

Is there any way of allowing an unprivileged user to load an X509Certificate from a file?

Answer

dajuric picture dajuric · Jul 19, 2018

Using the "X509KeyStorageFlags.UserKeySet" flag in the X509Certificate2 constructor helped me.