当您使用基于您创建的私钥的强名称签署程序集时,这具有以下好处:
- 强名称通过向程序集添加公钥令牌和数字签名来保证程序集身份的唯一性。
- 强名称可以与公钥匹配,以证明程序集来自具有该公钥的发布者,并且仅来自该发布者。
- 强名称提供强完整性检查。通过 .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 或更高版本(具有强名称绕过功能)的应用程序。可以通过将设置添加到其配置文件来为您的应用程序禁用此功能。但是当然,任何对该配置文件具有读/写访问权限的攻击者都可以推翻您的决定。