5

I'm new to .net and would like to know how I can prevent others from using/referencing my compiled libraries. I did some research but didn't find a clear answer. Is it authenticode or strong names or something else? and how reliable is it?

the libraries are part of a commercial desktop software

Tim
  • 109
  • 2
  • 6
  • 7
    You can't do that. All you can do is make it a bit harder. – SLaks Feb 15 '15 at 01:24
  • And if it's really hard, it probably has a cost as well. – SimpleVar Feb 15 '15 at 01:28
  • 1
    you license your software in such a way they aren't allowed. Actually stopping them physically violating that? Not many people have luck with that as you can see by the abundance of pirated software – Keith Nicholas Feb 15 '15 at 01:28
  • 1
    In general, you should know in advance that no matter what, some of the people will pirate your software, and there's nothing you can do about it, and it's okay, because the majority will be using it legally and pay. Legally forbidding and standard obfuscation is the furthest I'd go. – SimpleVar Feb 15 '15 at 01:29
  • how can i make it a little bit harder? what's the easiest way to do that? any built-in solutions? – Tim Feb 15 '15 at 01:35
  • also, am I correct to say strong names will prevent tempering? – Tim Feb 15 '15 at 01:43
  • @Tim: No; users can easily disable strong name verification. – SLaks Feb 15 '15 at 02:02
  • Don't use DLLs and mark all methods as internal? – Cole Tobin Feb 15 '15 at 02:57

3 Answers3

40

How I can prevent others from using my compiled libraries?

I would like to know how I can prevent someone from using my toothbrush. I have found a solution. I don't give them access to my toothbrush.

If you don't want people to use your software then do not give them your software.

If you want someone to be able to use the functionality of your code without knowing the implementation details then write a web service, put the software behind a web server, and people can use your software via the service you've provided. They only see the web server, not your implementation details.

Is it authenticode or strong names or something else?

No. Your scenario is that you wish to protect yourself, a software provider, from your users. That is exactly backwards. The .NET security system was designed to protect your users from bad software providers.

Both authenticode and strong names are systems whereby a user of software can obtain evidence that the software really was provided by the person they believe it to be provided by, rather than by evil hackers pretending to be you.

For example, suppose I become evil and send you a new version of System.DLL that I say is a software upgrade from Microsoft, but actually watches you type in passwords and emails them to me. I can send you a DLL called "System.DLL", but I can't send you one that has the Microsoft strong name because I can't make a Microsoft strong name. Only Microsoft can do that, because the Microsoft signing key is buried deep within Building 11 and guarded by sharks with laser beams or something. Strong names protect you from me; they don't protect Microsoft.

Similarly, strong names protect your customers from attackers pretending to be you. They don't protect you from your customers. You are not the one who is under attack; they are!

the libraries are part of a commercial desktop software

The commercial desktop software model presupposes that customers are trusted by software providers to use the software in accordance with their license. If you don't trust your customers then you need an entirely different model, like keeping the software on your web server and only allowing access via a web interface.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 8
    Are there any specifications on the lasers on the sharks? I need to know this to ensure that all software from MS conforms to ISO57348 and DOD 194834-86 standards to make sure our software is completely secure. – Zipper Feb 16 '15 at 18:29
  • 4
    @Zipper: That's proprietary, sorry. – Eric Lippert Feb 16 '15 at 22:32
1

I think I get what you're saying: you've put a lot of effort into a library that is essential to your application, and you don't want someone else to use a copy of that dll in their own application basically stealing your code, even if they can't see it. The framework is not built for this. You can hide certain code using access modifiers, but public is still public. However...

What I used to do when putting a component in a library that I know could be copied and used by someone else is to give specific classes a property that must be set to my name © and year. Without that exact text, the class won't work (or will work, but poorly). Since they can't change the code, they'll be forced to admit they stole it. You could even go as far as to put a password in there. This solution isn't perfect, of course, but it's the simplest. I don't do it any more though, because I just don't care.

EDIT: come to think of it, there are some commercial components that require a login before they can be used. Usually in the form of a username and a byte array that you buy from the author.

Patrick
  • 1,766
  • 1
  • 15
  • 27
0

Assuming no one will decompile your assembly (if this happens, it is just over anyways): The best way to protect your Secret DLL is by having your functions requiring some data to be signed.

In each of the Methods you whish to protect you could:

  1. Have them wear an extra argument called MySignedData.
  2. Insert a Function UserIsGenuine(MySignedData as String) as Boolean (sorry, VB.NET here..) just before your code.

Further considerations: The data to sign should change each time, otherwise the Evil User would just need to catch an instance of MySignedData and keep re-sending it. So you need to force the DataToSign to be different each time.

  1. The easiest would be tu use something like DataToSign = Hash(System.Time + Salt). But you are depending on the system time, which may be altered.
  2. Something more complex would be to have a DataToSign = RandomHashGeneratedBySecretDLL() located inside the Secret DLL.

Full example below.

(in VB.NET, sorry again)

Protected DLL

'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

Caller File

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
Ama
  • 1,373
  • 10
  • 24
  • This can easily be broken, why invest time into a not perfect solution? – Felix K. Feb 21 '19 at 19:57
  • So let's invest a little more to get something perfect :) How would you break it? – Ama Feb 21 '19 at 20:00
  • Just decompile it or just run a IL modifier on it. – Felix K. Feb 21 '19 at 20:41
  • Well as I said on the first line of my proposed answer: if you decompile it's game over, for any kind of soft. The OP asked "how can i make it a little bit harder?". Well that is an answer to that. What does IL stand for? Google did not pick it up. – Ama Feb 21 '19 at 20:48
  • Then you could also check against the calling assembly public key which would be easier right? – Felix K. Feb 21 '19 at 21:27
  • According to [this post](https://stackoverflow.com/questions/421137/how-can-i-prevent-unauthorized-code-from-accessing-my-assembly-in-net-2-0) and [this article](https://blogs.msdn.microsoft.com/ericlippert/2008/10/06/preventing-third-party-derivation-part-two/), I understand the public key can be freely modified by the assembly so that such check would be inneficient? – Ama Feb 21 '19 at 21:31
  • But you can hack it anyway so why not use a simple check then? IL stands for: https://en.wikipedia.org/wiki/Common_Intermediate_Language – Felix K. Feb 22 '19 at 15:18
  • I think there is a global agreement that a software on a machine can **always** be hacked; hence the rise of Web hosted Apps. However, there are different categories of cheaters, each of which will have their own ethical boundaries (actually let's be honnest here, it is usually more about guilt and the fear to be caught). To illustrate this, take a public park with `Stay off the Grass` signs: if you just put the sign, 50% of the people will not care and pretend they did not see the sign; but if you put a little shallow barrier, maybe only 10% will step. – Ama Feb 25 '19 at 20:48
  • And if you put hedges + an unlocked gate, probably 1% would go. I believe checking the public key is stepping over the shallow barrier, and I believe actively decompiling or inlining an assembly is getting into the hedged terrain. Of course that is subjective, but not senseless. – Ama Feb 25 '19 at 20:53
  • The easiest solution is to move your business code into a webservice. – Felix K. Feb 25 '19 at 21:35
  • I mainly develop VSTOs, and the new Office 365 pool of AddIns is all online. I opted for VSTO because my clients use these tools offline (on a plane, at a client meeting where the wifi never works, etc). I am also limited by data uploading speed, renting processors whilst my client have powerfull computers, and the fact that uploading sensitive data on a cloud is still not very well accepted in the industry. Microsoft want to have Office running 100% online and that will never happen, for the same reasons. – Ama Feb 25 '19 at 21:39