如何忽略单元测试中的装配参考不匹配?

时间:2015-08-09 01:16:33

标签: c# .net-assembly code-signing

我正在尝试篡改程序集,以便能够模拟无法轻易模拟的代码such as SharePoint assemblies

作为一个原型,我有一个解决方案,通过ILRepack和Mono.Cecil的自定义构建操作来修改测试代码,以便实际代码不是最初编写的代码。

当包含测试代码的程序集未签名时,一切正常。当程序集签名时,我看到了预期的错误:

  

找到的程序集的清单定义与程序集引用不匹配。

由于组件被篡改,显然,密钥要么不相同(如果在篡改后签名),要么不存在。

我认为通过AppDomain.CurrentDomain.AssemblyResolve事件可以允许强制接受篡改的程序集,但事实并非如此。

如何让.NET Framework在完全信任的单元测试中忽略程序集匹配检查,并在希望签名时接受未签名的程序集?

据我了解,问题不在于强名称验证。不仅错误会有所不同,而且running the corresponding sn –Vr也没有效果:错误仍然存​​在。

实际问题似乎是在装配绑定级别。这也是为什么我很惊讶地看到AppDomain.CurrentDomain.AssemblyResolve事件被提出,但其结果仍被忽略;可能,它并没有像我一直认为的那样做。

1 个答案:

答案 0 :(得分:0)

我认为解决方案要容易得多。因为,正如我猜测的那样,问题不是强名称验证,而是依赖于公钥令牌的程序集绑定,可以在篡改程序集时替换令牌。

第一步是在篡改之前获取原始公钥和公钥令牌。它们都在AssemblyName内。

var originalAssemblyBytes = File.ReadAllBytes(originalFilePath);
var originalAssemblyName = Assembly.Load(originalAssemblyBytes).GetName();

下一步是篡改本身:首先使用ILRepack合并两个程序集,然后使用Mono.Cecil进行更细粒度的更改。在第二步中,Mono.Cecil用于替换公钥和公钥令牌:

var assemblyName = mergedModule.Assembly.Name;
assemblyName.HasPublicKey = true;
assemblyName.PublicKey = originalAssemblyName.GetPublicKey();
assemblyName.PublicKeyToken = originalAssemblyName.GetPublicKeyToken();

必须更改两者:如果只更改了令牌,则在使用程序集时会立即抛出错误“无效的程序集公钥”。

这适用于使用.snk和.pfx签名的程序集:由于测试以完全信任的方式运行,因此验证未完成,这意味着公钥与私钥不对应的事实是不相关的。