保护Excel工作簿中的代码?

时间:2013-05-03 16:31:28

标签: c# visual-studio excel

我想制作一个包含专有公式和其他知识产权的Excel工作簿。我很可能使用C#在Visual Studio 2010中生成此工作簿。

这些项目中的代码有多受保护? C#中的反射问题仍然适用于这些工作簿项目吗?如果是这样,是否有针对这些类型工作簿的混淆工具?

要添加这个问题 - 那么好的'ole VBA?如果我们要去VBA路线,还有办法保护那些代码吗?

3 个答案:

答案 0 :(得分:18)

正如其他答案所暗示的那样,Excel 2003(.xls)中的VBA安全性存在缺陷;密码只是一点点烦恼,往往是开发者自己。恕我直言你最好用VSTO,即使Excel 2007+(.xlsx)中的VBA安全性要好得多,更不用说几个世纪以来没有看到改进的VBA IDE(尽管不是那么真实with the right VBE add-in... )。

解决方案可能是将敏感代码写入您的VSTO项目调用的单独库中;而不是复杂的公式,你可以公开函数,它们将显示为“黑盒子”(即公式功能的抽象);没有源代码的任何人都无法使用它如何实现,并且没有dll无法计算工作簿(整个地方#NAME?)。

例如,用户会看到=some proprietary formula returning a Smurf而不是=Smurf(SomeTableColumnName, SomeRangeName, SomeRangeReference, SomeCellReference)。当然这需要性能成本,所以我只会对那些真正重要的东西保护。

我认为设法从这样一个侧面库中提取专有公式的用户应该留下它们 - 在它和Alt + F11之间,这是一个很大的步骤;专有代码与任何其他.net程序集一样“受保护”。

<强>更新

仍然没有使用任何第三方库,如果专有代码需要 Excel互操作性,可能更好的解决方案是创建功能< / em>在VBA中(即在Excel中保留 Excel interop 部分)并仅传递基本类型(VBA Integer =&gt; .net Int16; VBA {{1} } =&gt; .net Long,字符串等)到COM-visible库,甚至不需要使用Excel互操作;它将是COM互操作而不是Excel互操作,并且性能损失将显着降低,但仍然存在(它仍然是.net托管代码“与非托管COM”谈话)。

VBA代码的职责是读取和写入工作表,COM-visible库的作用是实现由VBA代码传递的值进行的计算;当然,用户可以轻松访问VBA代码(Alt + F11),但他们再次无法访问实际的计算实现。然后VBA代码可以受密码保护,没有DLL的计算结果可以是Int320,具体取决于VBA代码的实现方式。

关键是在Excel中保留特定于Excel的并让.net库在没有引用Excel互操作程序集的情况下进行拾取 - 例如,VBA函数将采用单元格引用,抓取它的值(可能验证它)并将其传递给.net程序集,该程序集将返回VBA将返回到Excel的另一种基本类型。

另一个优点是,如果您要将Excel工作簿“转换”为Web应用程序,则可以重用具有专有计算的库代码。

答案 1 :(得分:10)

供将来参考:以下是2种新的创新产品,可帮助解决您的确切问题:

1)https://HiveLink.io: - 使用HiveLink,你可以创建一个&#34;轻量级&#34;您提供给用户的电子表格版本,但它不包含任何敏感的VBA或计算公式。您从轻量级电子表格中删除了知识产权,并向您的用户发送邀请以下载此电子表格。当您的用户输入他们的输入数据时,HiveLink会将数据传送到原始电子表格以处理数据,然后自动将结果返回给用户。

这种方法的好处在于,使用.NET反射甚至汇编代码进行逆向工程是不可能的 - 因为您完全从计算机中删除了代码。这是最安全的选择,如果您的模型适合输入/输出往返设计,那就太棒了 - 如果您需要立即发生的客户端交互式代码,那就太好了。如果您确实需要快速的客户端交互式代码,通常这不太敏感,您可以使用工作簿保护,甚至使用DoneEx Excel Compiler之类的东西编译基本代码,并使用Excel Compiler和HiveLink的组合进行保护

2)http://FCell.io:这允许您直接在电子表格中构建.NET代码。它甚至在电子表格中附带了一个代码编辑器窗口,有点像用.NET代码编辑器替换现有的VBA代码编辑器。代码编辑器中的对象模型比普通代码模型稍微全面,但您也可以创建任务窗格并将它们嵌入到工作簿中进行分发,这样您的用户甚至不需要安装任何东西!我不确定您的代码嵌入到工作簿中的安全程度,但我确信,如果您的代码对您的代码非常重要,那么他们可以使用您的代码。

进一步评论Re Mat的Mug有用回复:

Re:性能成本 - 实际上,您可能会注意到通过在.NET中实现一些功能可以获得显着的性能提升,特别是如果您利用多线程,Excel根本不会使用UDF或宏执行此操作。我已经看到100倍的收益重写了我的一些客户&#39; .NET库中的代码(用于繁重的处理计算)。您可能还发现维护和改进.NET代码要比VBA容易得多。我已经将很多VBA代码和功能转换为.NET代码,并且在正确完成时从未出现明显的性能问题。

Re:用户值得通过反映.NET库获取访问权限? - 我完全不同意这一点。 非常使用反射很容易访问.NET代码,甚至可能比cracking Excel's weak passwords更容易。如果您确实需要保护敏感计算,那么最好使用类似HiveLink之类的东西来完全消除逆向工程的可能性,或使用混淆来使其变得更难/非常烦人。对于混淆,我使用CryptoObfuscator($)和Dotfuscator($$$)。我不会分享我的客户&#39;敏感模型.NET库中的VBA代码,用于excel而不需要这样。我有时也使用CryptoLicensing来控制谁可以通过为每个用户创建许可来访问他们的DLL功能。

Re:让VBA代码负责写入/读取工作表 - 我也高度反对这一点。我建议尽可能少地在VBA中保留代码并对.NET进行高级调用,将读/写写入.NET插件。在工作表中使用命名范围来标识输入/输出和数据位置,然后在.NET库中将这些命名范围定义为常量。在您的库中,您可以非常轻松地从范围读取并写入范围。这种方式更清洁,更容易维护。

在为要从VBA调用外部功能的Excel构建任何扩展库时,必须使库COM可见。有几种方法可以做到这一点:我高度建议避免使用regsvr32在Windows COM列表中注册您的库 - 不惜一切代价避免它!

注册库的最佳方法是使用ExcelDna加载它,这允许您在每次启动Excel时动态加载DLL,而无需在注册表中使用COM接口永久定义每个类(更新版本时的噩梦)。您最终创建了一个XLL文件,该文件可以将DLL打包在内部 - 您可以通过在注册表中放置一个密钥来告诉Excel每次启动时加载XLL。好处是,这并不要求您将整个COM接口存储在注册表中,因此管理新版本非常容易。

因此,您的VBA代码可能类似于:

Sub Button_Click()
    Call ThisWorkbook.EnsureLibraryInitialized
    Call ThisWorkbook.MyLibrary.ReadRangesAndWriteResults(someInputParam)
End Sub

请注意,VBA会在运行时查找此方法ReadRangesAndWriteResults。如果您在VBA中公开编译时的方法,那么您必须在注册表中注册其COM接口签名 - 值得避免不惜一切代价!

ThisWorkbook模块:

Public MyLibrary as Object

public sub Workbook_Open()
    EnsureLibraryInitialized
End Sub

public Sub EnsureLibraryInitialized()
    Dim addin As COMAddIn
    If MyLibrary is Nothing Then
        For Each addin In Application.COMAddIns
            If InStr(addin.Description, "MyLibrary.COMHelper") Then
                If addin.object Is Nothing Then
                    'complain it can't connect to library, tell user to reinstall it
                Else
                    Set MyLibrary = addin.object
                Exit For
            End If
        Next
    End if
End Sub

Re:Excel Interop和.NET库 - 好点Mat's Mug,使用普通的Microsoft.Office.Interop.Excel时,这可能是一场噩梦。因为您正在从托管.NET环境访问本机代码,所以您必须确保正确清理.NET COM包装器对象,或者即使在关闭Excel后它也会出现挂起/僵尸进程,它看起来已经消失了/关闭(查看任务管理器,他们可能仍然在那里!)

我发现处理此问题的最佳方法是使用NetOffice,它基本上是Excel互操作模型的克隆,但是为了安全地管理所有这些问题而创建。最好还要注意COM对象的安全处理,例如herehere

祝你好运!

答案 2 :(得分:7)

如果使用密码保存工作簿以作为XLSB打开(请注意,请勿保护工作簿结构等),工作簿将使用相当安全的加密进行加密(在Excel 2013中更强)。
但是用户必须提供密码才能打开它,这不适合某些用途场景。

所有其他形式的Excel保护相对较弱。

在Excel中保护代码最好使用C ++ XLL。
下一个最好的是一个VB6 DLL(但这是一个死技术,不能在64位Excel中工作)
下一个最好的是混淆.NET,但你真的需要使用那种Addin Express或XL DNA提供的.NET XLL接口,以避免.NET Interop和VSTO的性能不佳。