防止他人使用我的DLL文件

5

我是 .net 的新手,想知道如何防止他人使用/引用我的编译库。我做了一些研究,但没有找到明确的答案。是 Authenticode 还是强名称,还是其他什么?它们的可靠性如何?

这些库是商业桌面软件的一部分。


7
你不能这样做。你只能让它变得更难一点。 - SLaks
如果它真的很难,那么它可能也有一个代价。 - SimpleVar
1
你以这样的方式许可你的软件,使得他们不被允许使用。实际上,阻止他们物理上违反这一点?很少有人能够做到,正如你可以看到盗版软件的丰富一样。 - Keith Nicholas
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - SimpleVar
不要使用DLL,并将所有方法标记为internal? - Cole Tobin
显示剩余3条评论
3个回答

40

如何防止他人使用我的编译库?

我想知道如何防止别人使用我的牙刷。我找到了一个解决方案。我不让他们接触我的牙刷。

如果你不想让别人使用你的软件,那么不要给他们你的软件。

如果你希望有人能够使用你代码的功能而不知道实现细节,那么可以编写一个Web服务,将软件放在Web服务器后面,人们可以通过你提供的服务使用你的软件。他们只会看到Web服务器,而看不见你的实现细节。

是Authenticode还是strong names或其他东西?

不是。你的场景是你希望保护自己这个软件提供者,免受用户的侵害。这完全是相反的。 .NET安全系统的设计目的是保护用户免受不良软件提供者的伤害。

Authenticode和strong names都是一种系统,使软件的用户可以获得证据,证明该软件确实是由他们认为的提供者所提供,而不是由假冒你身份的恶意黑客提供的。

例如,假设我变成了一个邪恶的人,向你发送一个名为“System.DLL”的软件升级版,声称来自微软,但实际上会监视你输入的密码并将其发送给我。我可以发送一个名为“System.DLL”的DLL文件,但我不能发送一个带有Microsoft strong name的DLL文件,因为我不能制造Microsoft strong name。只有Microsoft才能这样做,因为Microsoft的签名密钥嵌入在11号楼的深处,并由激光鲨鱼之类的东西守卫着。Strong names保护你免受我伤害;它们不保护Microsoft。

同样,强名称可以保护您的客户不受冒充您身份的攻击者的侵害。它们并不能保护您免受客户的攻击,因为他们才是受到攻击的人!

这些库是商业桌面软件的一部分

商业桌面软件模型假定客户信任软件提供商按照其许可证使用该软件。如果您不相信您的客户,那么您需要一个完全不同的模型,例如将软件保存在您的Web服务器上,并仅通过Web接口允许访问。

8
鲨鱼身上的激光有规格要求吗?我需要了解这些以确保我们的所有微软软件符合ISO57348和DOD194834-86标准,以确保我们的软件完全安全。 - Zipper
4
@Zipper:对不起,那是专有信息。 - Eric Lippert

1
我认为我明白你的意思:你已经花了很多精力创建一个对你的应用程序至关重要的库,而且你不希望其他人在他们自己的应用程序中使用该dll的副本,即使他们看不到它。框架并不是为此而建立的。您可以使用访问修饰符隐藏某些代码,但public仍然是public。然而...
当我将组件放入库中时,我知道它可能会被复制并被其他人使用,我会给特定类一个属性,必须设置为我的名字©和年份。如果没有这个确切的文本,该类将无法工作(或者工作得很差)。由于他们无法更改代码,他们将被迫承认他们窃取了它。你甚至可以进一步加入密码。当然,这种解决方案并不完美,但它是最简单的。虽然我不再这样做了,因为我根本不在乎。
编辑:想起来了,有些商业组件在使用前需要登录。通常以作者提供的用户名和字节数组的形式出售。

0
假设没有人会反编译您的程序集(如果发生这种情况,那就完了):保护秘密DLL的最佳方法是要求函数需要一些数据签名。
在您希望保护的每个方法中,您可以:
1. 添加一个额外参数,称为 `MySignedData`。 2. 在您的代码之前插入一个 `Function UserIsGenuine(MySignedData as String) as Boolean`(抱歉,这里是VB.NET)。
进一步考虑:签名的数据应该每次更改,否则恶意用户只需捕获 `MySignedData` 的实例并不断重新发送它。因此,您需要强制使 `DataToSign` 每次都不同。
最简单的方法是使用类似于 `DataToSign = Hash(System.Time + Salt)` 这样的东西。但是,您依赖于系统时间,而系统时间可能会被更改。
更复杂的方法是在秘密DLL内部放置一个 `DataToSign = RandomHashGeneratedBySecretDLL()`。
完整的示例如下。
'Note this class in C# will (and MUST) be Sealed, which is the equivalent in VB of NotInheritable with Shared Members
Public NotInheritable Class ProtectMyDLL 

    Private Shared ReadOnly MyPublicKey As String = "<RSAKeyValue><Modulus>SomeLongBase64StringHere</Modulus><Exponent>SomeShortBase64StringHere</Exponent></RSAKeyValue>"
    Private Shared _DataToSign(32) As Byte 'Recommended size in Bytes, for SHA256 hash signature (256 bits = 32 bytes)
    Public Shared Property SignedData As Byte() 'The caller will be asked to put the signed version of DataToSign here

    Public Shared ReadOnly Property DataToSign As Byte()
        Get
            If _DataToSign Is Nothing Then 'If empty then generate a new random string (string size is determined by the size of the Byte() array: 32)
                Using MyRndGen = System.Security.Cryptography.RandomNumberGenerator.Create
                    MyRndGen.GetBytes(_DataToSign)
                End Using
            End If
            Return _DataToSign
        End Get
    End Property


    Public Shared Function UserIsGenuine() As Boolean
        Using MyRSA As New System.Security.Cryptography.RSACryptoServiceProvider
            MyRSA.FromXmlString(MyPublicKey)
            UserIsGenuine = MyRSA.VerifyData(DataToSign,
                                             System.Security.Cryptography.CryptoConfig.MapNameToOID("SHA256"),
                                             SignedData)
            _DataToSign = Nothing 'This forces the data to be signed to change each time an access to the DLL is granted; otherwise the data to be signed will change only each time the Application is started. Argueably necessary, argueably consumming unnecessary resources..
        End Using

    End Function

End Class

Public Class MySecretClass

    Public Shared Sub IntelectualPropertyMethod()

        If Not ProtectMyDLL.UserIsGenuine() Then
            Throw New System.AccessViolationException("Caller signature could not be verified.")
            Exit Sub
        End If

        '... This code is protected

    End Sub

End Class

调用者文件

Public Class CallerFromOutsideTheProtectedDLL

    Public Sub Main()
        ProtectMyDLL.SignedData = SignData(ProtectMyDLL.DataToSign) 'Must do this before every calls of a protected method, unless the _DataToSign = Nothing line is removed, in which case you onlyned to add this line once (see Secret DLL file).
        Call MySecretClass.IntelectualPropertyMethod()
    End Sub

    Private Function SignData(MyData As Byte()) As Byte()
        Return MyCrypto.SignWithMyPrivateKey(MyData) 'If you want to avoid having to provide a Private Key in an assembly, you can pass MyData through a WebAPI where the Private Key would be 100% securely kept secret. But then your App needs an access to the web, at least from times to times.
    End Function

End Class

这个很容易被破解,为什么要投资时间在一个不完美的解决方案上呢? - Felix K.
那么,让我们再多投入一点,以获得完美的东西 :) 你会如何打破它? - Ama
只需反编译它或在上运行 IL 修改程序。 - Felix K.
正如我在我的答案的第一行所说的那样:如果你反编译了它,任何软件都将无法幸免。OP问道:“我该如何让它变得更难?”好吧,这就是一个回答。IL代表什么?谷歌没有查到。 - Ama
根据这篇帖子这篇文章,我理解公钥可以被程序集自由修改,以至于这种检查将变得无效? - Ama
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接