可以使用强命名装配体来验证装配体作者吗?

我一直在阅读MSDN,Strong-Named Assemblies和一个相关的堆栈溢出问题的相应文章,检查程序集中的强名称。

  • 为了避免篡改,可以在多大程度上验证强名称的程序集?
  • 是否可以使用强命名来验证程序集作者?
  • 第一个问题出现在阅读CSharp411的文章.NET Assembly FAQ - Part 3 - 强名和签名之后,其中提到了这一点,以及使用强名称的其他问题:

    无法停止完全替换,强名称无法防止黑客删除强名称签名,恶意修改您的程序集,用自己的密钥重新签名,然后将自己的程序集与您的名字相混淆。”

    第二个问题试图找出强命名和其他签名方案(如Authenticode)之间的区别。 早期提到的同一个MSDN文章指出:

    “然而,请注意,强名称本身并不意味着像例如数字签名和支持证书所提供的信任水平。”

    我是否试图使用强名称比创建它更多? 创建强名称是为了避免名称冲突或新的“GAC DLL地狱”?


    当您根据您创建的私钥为具有强名称的程序集签名时,这具有以下优点:

  • 通过在程序集中添加公钥标记​​和数字签名,强名称保证了程序集标识的唯一性。
  • 一个强大的名字可以与一个公钥相匹配,以证明这个程序集来自发布者使用该公钥,并且只有该公布者。
  • 强名称提供了强大的完整性检查。 通过.NET Framework安全检查可确保程序集的内容自上次构建以来未发生更改。
  • 是否可以使用强命名来验证程序集作者?

    是的,如上所述,强命名可以验证程序集的最新作者。 但它不验证原作者。 如果攻击者替换你的程序集的强名,那么所有可以验证的是你不是程序集的最新作者。 如果他删除了强名,则根本不能进行作者验证。

    为了避免篡改,可以在多大程度上验证强名称的程序集?

    以下C#代码验证攻击者是否在应用强名称时未篡改写入您的程序集的公钥标记。 它不会避免篡改,但它可以检测到某些类型的篡改。 下面的方法接受一个包含公钥标记的字节数组,并将其与程序集的实际标记进行比较。 请注意,为了使此技术有效,您选择的混淆器应该对包含公钥标记的字符串进行加密,并且只在使用时对其进行即时解密。 同时请注意,您需要拥有FullTrust权限才能使用此代码,因为它在底层使用了反射。

    // Check that public key token matches what's expected.
    private static bool IsPublicTokenOkay_Check(byte [] tokenExpected)
    {
        // Retrieve token from current assembly
        byte [] tokenCurrent = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken();
    
        // Check that lengths match
        if (tokenExpected.Length == tokenCurrent.Length)
        {
            // Check that token contents match
            for (int i = 0; i < tokenCurrent.Length; i++)
                if (tokenExpected[i] != tokenCurrent[i]) 
                    return false;
        }
        else
        {
            return false;
        }
        return true;
    }
    

    只要您在.NET 3.5 SP1之前的.NET Framework版本下运行,您还可以强制验证强名称签名,以防强者名称被攻击者删除,或强名称检查在注册表中。 以下代码演示了调用另一个称为NativeMethods的类的静态方法。 这是验证执行的地方。

    // Check that this assembly has a strong name.
    private bool IsStrongNameValid_Check()
    {
        byte wasVerified = Convert.ToByte(false); 
         byte forceVerification = Convert.ToByte(true);
        string assemblyName = AppDomain.CurrentDomain.BaseDirectory + 
                              AppDomain.CurrentDomain.FriendlyName; 
        return NativeMethods.CheckSignature(assemblyName, 
                                            forceVerification, 
                                            ref wasVerified);
    }
    

    实际签名验证使用P / Invoke完成,如下所示。 StrongNameSignatureVerificationEx API的使用非常复杂 - 为了一个体面的解释,请参阅此博客条目。

    // P/Invoke to check various security settings
    // Using byte for arguments rather than bool, 
    // because bool won't work on 64-bit Windows!
    [DllImport("mscoree.dll", CharSet=CharSet.Unicode)]
    private static extern bool StrongNameSignatureVerificationEx(string wszFilePath, 
                                                                 byte fForceVerification, 
                                                                 ref byte pfWasVerified);
    
    // Private constructor because this type has no non-static members
    private NativeMethods()
    {
    }
    
    public static bool CheckSignature(string assemblyName, 
                                      byte forceVerification, 
                                      ref byte wasVerified)
    {
        return StrongNameSignatureVerificationEx(assemblyName, 
                                                 forceVerification, 
                                                 ref wasVerified );
    }
    

    请注意,对于使用.NET 3.5 SP1或更高版本(具有强名称绕过功能)的应用程序,默认情况下这不起作用。 通过向其配置文件添加设置,可以为您的应用程序禁用此功能。 但是,当然任何具有对该配置文件的读/写访问权的攻击者都可以改变你的决定。


    Authenticode依靠第三方证书颁发机构进行证书验证。 强命名就像一个自签名证书一样工作,可以这样对待。 它确实使用标准数字签名,但问题在于验证程序集作者的公钥是否确实有效。 如果您通过来自作者的可信渠道单独获取它,并且您信任该频道,那么是的,您可以像验证自我签名一样验证它。

    只要您确定作者的强名私钥是安全的,并且您知道作者的公钥,那么您可以确保它没有被篡改(以确保数字签名的电子邮件不被篡改)。 顺便说一句,不要误解我的意思:引用是完全正确的,攻击者可以轻易地辞去程序集或删除现有的签名。 但是,生成的程序集将具有**不同的*数字签名,可以根据原始签名进行检查(如果您拥有原始公钥)。

    在这种情况下,它与自签名证书相似。 如果你能以某种方式确定作者的公钥,你可以验证权限。 但是,与依赖证书颁发机构的Authenticode不同,没有简单的,系统定义的分发公钥的方式。


    我认为强名称对于版本控制很有用,可用于帮助设置“代码访问安全性编辑 ”的信任级别:但不能使用它们来验证程序集是由受信任的或特定作者创作的。 请参阅@RoadWarrior和@ RoadWarrior对此问题的回答。

    强大的命名你的组件并不能防止篡改。
    编辑:查看@RoadWarrior和@divo的评论。 如果您的应用程序正在从程序集的作者检查原始私钥并强制进行名称验证,那么我的声明是不正确的。 但是,如果攻击者可以访问应用程序中的所有程序集,并且/或者您正在使用CLR免费提供的开箱即用名称验证,那么我支持我所说的。

    这可以被一个坚定的攻击者破坏。

    我前一段时间阅读了一个关于强名和安全性的讨论,这让我相信,对于我们生产的组件而言,authenticode为我们的客户提供了一个更好的保证,即该组装来自可信来源。

    链接地址: http://www.djcxy.com/p/57485.html

    上一篇: Can strong naming an assembly be used to verify the assembly author?

    下一篇: reflection is possible on obfuscation