无法获取StrongNameKeyPair的公钥

时间:2011-04-14 07:07:31

标签: .net fluent-nhibernate

我已将开发移植到另一台计算机上,如果我运行项目,我有这个例外:

  

无法获取StrongNameKeyPair的公钥。

     

HibernateException:创建代理实例失败

在原始计算机上,它可以正常工作。

我在google上发现它有一些加密的问题我应该尝试“sn -m n”,我不知道怎么做。 sn.exe在更多文件夹中,我尝试从命令行运行一些但它写道:

  

无法打开注册表项 - 无法格式化错误消息00000005

我不知道问题是因为NHibernate与否,还有更多类似的whitch对话框,它只在一种情况下抛出此异常。

有部分代码抛出异常:

public IList<DTO> GetAll(GridSortOptions sortOptions, DTOListModel<DTO> listModel)
{
    return GetAllCriteria(sortOptions, CreateCriteria(), listModel).List<DTO>();
}

解决方案中没有一个项目使用签名。 我不明白这些错误究竟意味着什么以及我应该寻找什么。

4 个答案:

答案 0 :(得分:7)

NHibernate动态创建.NET程序集(动态代理)并需要对它们进行签名。默认情况下,Windows操作系统将加密密钥存储配置为计算机级别,并将密钥存储在C:\ Documents and Settings \ All Users \ Application Data \ Microsoft \ Crypto \ RSA \ MachineKeys中。很可能您的用户可以在此文件夹中创建(例如)文本文件,但不能删除它,因为您没有完全控制权。

您的选择

  1. 通过修改可能不推荐的权限,完全控制C:\ Documents and Settings \ All Users \ Application Data \ Microsoft \ Crypto \ RSA \ MachineKeys。

  2. 通过从Windows SDK运行“sn.exe -m n”,将加密密钥存储更改为用户级别。 http://msdn.microsoft.com/en-us/library/k5b5tt23(v=VS.90).aspx这会将加密密钥存储放在您的用户本地资料下,您应该始终对其进行完全控制。

  3. 网上有几篇文章描述了类似的问题。例如,请参阅http://support.targetprocess.com/Default.aspx?g=posts&t=305

答案 1 :(得分:4)

今天有一个类似的问题,有一个不同的用例(在W2008R2盒子上运行的.NET服务),但完全相同的错误。

使用procmon我将其追溯到C:/ ProgramData / Microsoft / Crypto / RSA / MachineKeys中的密钥写入失败。

按照此处所述添加对该文件夹具有特殊权限的每个人的指导修复了问题:http://toastergremlin.com/?p=432

此外,请确保添加EVERYONE @本地计算机,而不是每个人@域!

答案 2 :(得分:1)

对于遇到这种情况的其他人,我在物理机器上遇到了同样的例外。一夜之间什么都没有改变,但这个例外在早上开始出现。

原来是磁盘空间不足问题,无法将动态代理程序集写入磁盘。只是意识到了这一点,因为当它短暂出现时我碰巧注意到了Windows的“低磁盘空间”图标。 :-P

清除一堆(大)临时文件会导致问题消失。

答案 3 :(得分:0)

我今天遇到了同样的问题,并不喜欢提供的解决方案。这些是:

  • 拥有自己的Castle.Core版本,并删除了强大的命名代码。 Reference
  • 修改文件夹的权限。参考:这个问题
  • 更改加密密钥存储。参考:这个问题

以下可能是一个肮脏的黑客,但它运作良好,我不必向IT解释为什么我希望所有最终用户计算机重新配置。

/// <summary>
/// Ensures that NHibernate creates no strong named proxy assemblies.
/// Assumes usage of Castle.DynamicProxy. Needs to be revisited
/// after update of NHibernate or Castle.Proxy!
/// </summary>
private static void EnsureNHibernateCreatesNoStrongNamedProxyAssemblies()
{
    if (!StrongNameUtil.CanStrongNameAssembly)
    {
        Logger.Debug("NHibernate is not trying to strong name assemblies." +
                     "No action needed.");
        return;
    }

    const string FieldName = "canStrongNameAssembly";
    var type = typeof(StrongNameUtil);
    var field = type.GetField(FieldName, BindingFlags.Static
                                         | BindingFlags.NonPublic);
    if (field == null)
    {
        Logger.Warn(
            "No field with the name {0} exists in the type {1}."
            + "Can't change NHibernate to use weak named proxy assemblies.", 
            FieldName, type);
        return;
    }

    field.SetValue(null, false);

    if (StrongNameUtil.CanStrongNameAssembly)
    {
        Logger.Warn(
            "Couldn't change value of field {0} on type {1}. "
            + "NHibernate will continue to use strong named proxy assemblies.", 
            FieldName, type);
    }
    else
        Logger.Debug("Successfully changed NHibernate to use "
                     + "weak named proxy assemblies.");
}

确保在生成第一个代理之前,在程序的最开始调用此方法。

我想真正的解决方案是升级到NHibernate 3.3,这已经不再存在这个问题了,但现在不是一个选择。