6

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

对象仅包含密钥对的公共部分。还必须提供私钥。

安装程序正在运行提升,目标是 Windows Vista。

如果我使用单独的 .exe 安装完全相同的证书,使用完全相同的代码,它可以工作。那么使用 Windows Installer 安装证书有什么不同呢?

编码:

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");
  }
}
4

1 回答 1

5

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

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

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

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";
}
于 2009-09-29T13:23:07.670 回答