⬆️ ⬇️

Easy way to add license file support to your .Net application

Some time ago, a friend asked me to automate part of the routine work of his business. At that moment I was anticipating the onset of the coming reduction, and I agreed with pleasure.

The development took three full cycles and now the fourth and final cycle of work on the program is coming to an end and I had an idea to move my product further to the masses. It’s been said, work has begun on drawing up contracts, redesigning, otbutforsingu and other other craps, and an interesting question arose - how to protect the program from non-licensed use and not allow it to be copied?



Poryskav on the Internet, more precisely on the portal CodeProject , found several implementations using license files.

In theory, the problem is solved simply:

  1. Create an xml file with the content we need
  2. Sign the file with the SignedXml class
  3. In the application we check the signature. If the check is successful - we look at the contents of the file, if not - we immediately drop out with an error


In practice, the SignedXml object requires an instance of AssimetricAlgorithm encryption. In the examples found, asymmetric encryption was used with any certificate installed on the computer and then decrypted by the exported public key. Taking into account the fact that after some time I am going to reinstall the system, it was necessary to be bothered about exporting the certificate, and it’s not an option that it can then get back up, and a very long implementation code.

I thought, because there may be a way easier. And found.

All the work of the Subscriber is to add to the xml some line that should be checked. So why not write there my string formed by a certain algorithm. My method uses a symmetric encryption method, so to speak.

I needed to check whether the license had reached its expiration date, how many updates were possible and who actually owns this license.

I created two classes: one to create a license file, the other to check it.

The method is very simple. We take the input parameters to create a license, write everything in xml. Then we concatenate these same parameters, add a certain constant to them, we get a hash, which will be our signature and append it to the end of xml in the appropriate section.



class LicenseGenerator

{

public void Generate( string Path, String Name, DateTime StartDate, DateTime UpdateTo)

{



XmlDocument doc = new XmlDocument ();

doc.LoadXml( @"<license>

<Name></Name>

<Date></Date>

<UpdateTo></UpdateTo>

<Signature></Signature>

</license>"
);

doc.ChildNodes[0].SelectSingleNode( @"/license/Name" , null ).InnerText = Name;

doc.ChildNodes[0].SelectSingleNode( @"/license/Date" , null ).InnerText = StartDate.ToShortDateString();

doc.ChildNodes[0].SelectSingleNode( @"/license/UpdateTo" , null ).InnerText = UpdateTo.ToShortDateString();



MD5 md5 = new MD5CryptoServiceProvider();

byte [] data = System.Text. Encoding .UTF8.GetBytes(Name + StartDate.ToShortDateString() + UpdateTo.ToShortDateString() + "SomePasswordKey" );

byte [] hash = md5.ComputeHash(data);

doc.ChildNodes[0].SelectSingleNode( @"/license/Signature" , null ).InnerText = Convert .ToBase64String(hash);

doc.Save(System.IO.Path.Combine(Path, "license.xml" ));

}

}




* This source code was highlighted with Source Code Highlighter .




At the output we get something like this license.xml

< license >

< Name > </ Name >

< Date > 15.06.2009 </ Date >

< UpdateTo > 15.12.2009 </ UpdateTo >

< Signature > w673nrcuvxjnn7R4heEnvw== </ Signature >

</ license >




* This source code was highlighted with Source Code Highlighter .


')

Next, in the protected application, we need to pass a check, this is done by calling the Verify method every time the application is started:

public class LicenseVerify

{

public LicenseVerify() { }

public string Name { get ; private set ; }

public DateTime StartDate { get ; private set ;}

public DateTime UpdateTo { get ; private set ;}



public void Verify()

{

string File = "license.xml" ;

if (!System.IO. File .Exists( File ))

{

throw new ApplicationException ( " ! License.xml.\n ." );

}



XmlDocument doc = new XmlDocument ();

doc.Load( File );

string sig1;

string Signature;

try

{

string Name = doc.ChildNodes[0].SelectSingleNode( @"/license/Name" , null ).InnerText;

string StartDate = doc.ChildNodes[0].SelectSingleNode( @"/license/Date" , null ).InnerText;

string UpdateTo = doc.ChildNodes[0].SelectSingleNode( @"/license/UpdateTo" , null ).InnerText;

Signature = doc.ChildNodes[0].SelectSingleNode( @"/license/Signature" , null ).InnerText;

MD5 md5 = new MD5CryptoServiceProvider();

byte [] data = System.Text. Encoding .UTF8.GetBytes(Name + StartDate + UpdateTo + "SomePasswordKey" );

byte [] hash = md5.ComputeHash(data);

sig1 = Convert .ToBase64String(hash);

this .Name = Name;

this .StartDate = Convert .ToDateTime(StartDate);

this .UpdateTo = Convert .ToDateTime(UpdateTo);

}

catch (Exception)

{



throw new ApplicationException( " !\n !\n ." );

}



if (sig1 != Signature)

{

throw new ApplicationException( " !\n !\n ." );



}

if ( DateTime .Now < this .StartDate)

{

throw new ApplicationException( string .Format( " !\n ! {0}\n ." ,StartDate.ToShortDateString()));



}



if (App.Created > this .UpdateTo)

{

throw new ApplicationException( string .Format( " !\n .\n {0}\n ." , UpdateTo.ToShortDateString()));



}

}

}




* This source code was highlighted with Source Code Highlighter .




The negative may be that having solved SomePasswordKey, having received a disassembly code, an attacker can create his license file.

The positive point is the simplicity of implementation, when cryptographic protection does not come in the first place.



ToDo List:

Source: https://habr.com/ru/post/62315/



All Articles