X509Certificate2 - the system cannot find the path specified

13,637

Solution 1

If you are running in IIS, you need to set "Load User Profile" to True in the application pool's advanced settings to be able to load a cert by filename & password.

Solution 2

So, I just had the exact same problem. I tried to solve it for almost 4 hours.

Problem was in passed path to key. Because I used the code from Google sample console application, where the path was just "key.p12" and the key was in the same directory as the exe file.

And when I wanted to create MVC application, I did not realize, that root of virtual server path can not be called just like "key.p12".

SOLUTION

Double check the path to the key. If it is MVC application (or another ASP web), then add the key file to the root and in code call the key by using Server.MapPath("key.p12").

Share:
13,637
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I wish to get the data of Google analytics via service account. When I launch first time the application, everything works correctly and I have access to the data. But When I launch second time the application I have the following error which appears: " the system cannot find the path specified ". Have you an idea? I thought it can be a lock.

    This is my source code:

       public static String GetAccessToken(string clientIdEMail, string keyFilePath, String scope)
        {
            // certificate
            var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
    
            // header
            var header = new { typ = "JWT", alg = "RS256" };
    
            // claimset
            var times = GetExpiryAndIssueDate();
            var claimset = new
            {
                iss = clientIdEMail,
                scope = scope,
                aud = "https://accounts.google.com/o/oauth2/token",
                iat = times[0],
                exp = times[1],
            };
    
            JavaScriptSerializer ser = new JavaScriptSerializer();
    
            // encoded header
            var headerSerialized = ser.Serialize(header);
            var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);
            var headerEncoded = Convert.ToBase64String(headerBytes);
    
            // encoded claimset
            var claimsetSerialized = ser.Serialize(claimset);
            var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);
            var claimsetEncoded = Convert.ToBase64String(claimsetBytes);
    
            // input
            var input = headerEncoded + "." + claimsetEncoded;
            var inputBytes = Encoding.UTF8.GetBytes(input);
    
            // signiture
            var rsa = certificate.PrivateKey as RSACryptoServiceProvider;
            var cspParam = new CspParameters
            {
                KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
                KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
                Flags = CspProviderFlags.UseMachineKeyStore
            };
            var aescsp = new RSACryptoServiceProvider(1024,cspParam) { PersistKeyInCsp = false };
            var signatureBytes = aescsp.SignData(inputBytes, "SHA256");
            var signatureEncoded = Convert.ToBase64String(signatureBytes);
    
            // jwt
            var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded;
    
            var client = new WebClient();
            client.Encoding = Encoding.UTF8;
            var uri = "https://accounts.google.com/o/oauth2/token";
            var content = new NameValueCollection();
    
            content["assertion"] = jwt;
            content["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer";
    
            string response = Encoding.UTF8.GetString(client.UploadValues(uri, "POST", content));
    
            JsonGoogleResponse result = (ser.Deserialize<JsonGoogleResponse>(response));
    
    
    
            return result.access_token;
        }
    

    And this is the stack:

      à   System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
      à System.Security.Cryptography.SafeProvHandle._FreeCSP(IntPtr pProvCtx)
      à System.Security.Cryptography.SafeProvHandle.ReleaseHandle()
      à System.Runtime.InteropServices.SafeHandle.InternalFinalize()
      à System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
      à System.Runtime.InteropServices.SafeHandle.Finalize()