Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在单元测试中忽略程序集引用不匹配?_C#_.net Assembly_Code Signing - Fatal编程技术网

C# 如何在单元测试中忽略程序集引用不匹配?

C# 如何在单元测试中忽略程序集引用不匹配?,c#,.net-assembly,code-signing,C#,.net Assembly,Code Signing,我正在尝试篡改程序集,以便能够模拟无法轻松模拟的代码 作为一个原型,我有一个解决方案,通过ILRepack和Mono.Cecil的自定义构建操作篡改测试代码,因此实际代码不是最初编写的代码 当包含测试代码的程序集没有签名时,一切正常。当对程序集进行签名时,我看到了预期的错误: 定位的程序集清单定义与程序集引用不匹配 由于程序集被篡改,显然,密钥不是相同的(如果在篡改后签名),就是不存在 我认为通过AppDomain.CurrentDomain.AssemblyResolve事件可以强制接受被篡改

我正在尝试篡改程序集,以便能够模拟无法轻松模拟的代码

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

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

定位的程序集清单定义与程序集引用不匹配

由于程序集被篡改,显然,密钥不是相同的(如果在篡改后签名),就是不存在

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

如何要求.NET Framework在完全信任运行的单元测试期间忽略对程序集匹配的检查,并在希望对未签名的程序集进行签名时接受这些程序集


据我所知,问题不在于强名称验证。不仅错误会有所不同,而且没有影响:错误仍然存在


实际问题似乎在程序集绑定级别。这也是为什么我惊讶地看到,
AppDomain.CurrentDomain.AssemblyResolve
事件被引发,但其结果仍然被忽略;很可能,它并不像我一直认为的那样。解决方案比我想象的要简单得多。正如我所猜测的,问题不是强名称验证,而是依赖公钥令牌的程序集绑定,因此可以在篡改程序集的同时替换令牌

第一步是,在篡改之前,获取原始公钥和公钥令牌。它们都在
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签名的程序集都有效:因为测试是在完全信任的情况下运行的,所以验证没有完成,这意味着公钥与私钥不对应这一事实无关紧要。

解决方案比我想象的要简单得多。正如我所猜测的,问题不是强名称验证,而是依赖公钥令牌的程序集绑定,因此可以在篡改程序集的同时替换令牌

第一步是,在篡改之前,获取原始公钥和公钥令牌。它们都在
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签名的程序集都有效:因为测试是在完全信任的情况下运行的,所以验证没有完成,这意味着公钥与私钥不对应这一事实是不相关的。

我不确定自己是否理解正确,但听起来好像你在试图破解你编写的安全代码。i、 e.如果你能通过单元测试来智胜你的代码,这难道不意味着黑客可以用同样的方法在生产中击败你的防御吗?@PaulSasik:没错。在生产中,黑客确实可以使用相同的技术,但它适用于完全信任运行的代码。除此之外,我希望单元测试的特定上下文也能有所帮助:例如,在进行代码覆盖或分析时不使用相同的机制吗?似乎提到了一些关于能够使用
sn-T
的内容,其中
fullname
Assembly=MyAssembly.dll,公钥令牌=
。也许你可以在修改程序集后设置它?我不确定我是否理解正确,但听起来你好像在试图破坏你编写的安全代码。i、 e.如果你能通过单元测试来智胜你的代码,这难道不意味着黑客可以用同样的方法在生产中击败你的防御吗?@PaulSasik:没错。在生产中,黑客确实可以使用相同的技术,但它适用于完全信任运行的代码。除此之外,我希望单元测试的特定上下文也能有所帮助:例如,在进行代码覆盖或分析时不使用相同的机制吗?似乎提到了一些关于能够使用
sn-T
的内容,其中
fullname
Assembly=MyAssembly.dll,公钥令牌=
。也许你可以在修改组件后设置它?