代码之家  ›  专栏  ›  技术社区  ›  Magnus Johansson

在.MSI自定义操作中安装证书无法正常工作

  •  6
  • Magnus Johansson  · 技术社区  · 17 年前

    我正在尝试以自定义操作在本地计算机存储中安装证书。 证书已安装,但当我使用它查询AWS时,会出现以下错误:

    一对钥匙。还必须提供私钥 提供。

    ,目标是Windows Vista。

    如果我使用一个单独的.exe来安装完全相同的证书,使用完全相同的代码,它就可以工作。

    守则:

    private void InstallCertificate(string certificatePath, string certificatePassword)
    {
      if (IsAdmin())
      {
        try
        {
          X509Certificate2 cert = new X509Certificate2(certificatePath, certificatePassword,
            X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
    
          X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
          store.Open(OpenFlags.ReadWrite);
          store.Add(cert);
          store.Close();
        }
        catch (Exception ex)
        {
          throw new DataException("Certificate appeared to load successfully but also seems to be null.", ex);
        }
      }
      else
      {
        throw new Exception("Not enough priviliges to install certificate");
      }
    }
    
    1 回复  |  直到 17 年前
        1
  •  5
  •   Magnus Johansson    15 年前

    好吧,至少这个问题为我赢得了一枚滚草徽章。。。

    原来是对已安装密钥文件的权限。我必须授予所有用户读取权限。

    下面是我用来授予所有(本地)用户读取权限的代码:

    private static void AddAccessToCertificate(X509Certificate2 cert)
    {
      RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
      if (rsa == null) return;
    
      string keyfilepath = FindKeyLocation(rsa.CspKeyContainerInfo.UniqueKeyContainerName);
    
      FileInfo file = new FileInfo(System.IO.Path.Combine(keyfilepath, rsa.CspKeyContainerInfo.UniqueKeyContainerName));
    
      FileSecurity fs = file.GetAccessControl();
    
      SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
      fs.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.Read, AccessControlType.Allow));
      file.SetAccessControl(fs);
    }
    
    private static string FindKeyLocation(string keyFileName)
    {
      string pathCommAppData = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Microsoft\Crypto\RSA\MachineKeys");
      string[] textArray = Directory.GetFiles(pathCommAppData, keyFileName);
      if (textArray.Length > 0) return pathCommAppData;
    
      string pathAppData = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Microsoft\Crypto\RSA\");
      textArray = Directory.GetDirectories(pathAppData);
      if (textArray.Length > 0)
      {
        foreach (string str in textArray)
        {
          textArray = Directory.GetFiles(str, keyFileName);
          if (textArray.Length != 0) return str;
        }
      }
      return "Private key exists but is not accessible";
    }