During a long time Manco .NET Licensing System supported 2 kinds of the protected storage: Windows Registry and Isolated Storage. No matter that it looks like enough for most .NET Framework scenarios there are environments and applications which require another approach. For example, Windows Azure Partial Trust role have not access to the Windows Registry or Isolated Storage. To make it possible to use our protection library in those scenarios we introduced ability to create custom protected storage which will better suit the needs of your application.
In this article I’ll show how custom protected storage can be implemented using very simple scenario using temporary files.
Note: Pay attentions, this is just an example which demonstrates how the custom protected storage can be implemented. The temp folder isn't a good and secure place to store licensing information.
Mostly implementation of the license protection is the same as for other licensing schemas. The difference is in the protected storage only. We suppose that you have read at least “Quick Start” section in our product documentation, so we will show the peculiarity of the custom protected storage only.
First of all you should change mode of the protected storage in the License Manager to the “Custom”:
Now you should regenerate ILicenseKeyProvider and replace it in the protected application.
As next step you should create class which will implement Manco.Licensing.IProtectedStorage interface:
[C#]
/// <summary>
[VB.NET]
The final step you have to do is informing the protection library about class which implements custom protected storage:
You can find sample solution which demonstrates creation of the custom protected storage at the http://www.mancosoftware.com/licensing/download.htm.
In this article I’ll show how custom protected storage can be implemented using very simple scenario using temporary files.
Note: Pay attentions, this is just an example which demonstrates how the custom protected storage can be implemented. The temp folder isn't a good and secure place to store licensing information.
Mostly implementation of the license protection is the same as for other licensing schemas. The difference is in the protected storage only. We suppose that you have read at least “Quick Start” section in our product documentation, so we will show the peculiarity of the custom protected storage only.
First of all you should change mode of the protected storage in the License Manager to the “Custom”:
Now you should regenerate ILicenseKeyProvider and replace it in the protected application.
As next step you should create class which will implement Manco.Licensing.IProtectedStorage interface:
[C#]
/// <summary>
/// Custom protected storage which uses temporary file.
/// Pay attentions, this is just an example which demonstrates how the
/// custom protected storage can be implemented. The temp folder isn't a
good
/// and secure place to store licensing information.
/// </summary>
public
class TempFileProtectedStorage
: IProtectedStorage
{
public
TempFileProtectedStorage()
{
}
/// Gets or sets path of the temporary file.
/// </summary>
private string FilePath
{
get;
set;
}
/// <summary>
/// Gets or sets protected assembly.
/// </summary>
private Assembly ProtectedAssembly
{
get;
set;
}
/// <summary>
/// Dispose protected storage object
/// </summary>
public void Dispose()
{
}
/// <summary>
/// Gets stream to read license document from the protected
storage
/// </summary>
/// <returns>Stream to read document from</returns>
public
System.IO.Stream GetInputStream()
{
FileStream
fileStream = File.Open(this.FilePath,
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.None);
if
(fileStream.Length > 0)
{
StreamReader
reader = new StreamReader(fileStream);
reader.ReadLine();
string
lsEncrLicense = reader.ReadLine();
reader.Close();
fileStream.Close();
byte[]
encrypted = Convert.FromBase64String(lsEncrLicense);
MemoryStream
stream = new MemoryStream(encrypted);
return
stream;
}
else
{
fileStream.Close();
return null;
}
}
/// <summary>
/// Initialize protected storage.
/// </summary>
/// <param
name="licenseKeyProvider">License
key provider.</param>
public void Initialize(ILicenseKeyProvider
licenseKeyProvider)
{
this.FilePath
= null;
// In
this example we use name of the product to create
//
temporary folder.
this.ProtectedAssembly
= licenseKeyProvider.GetType().Assembly;
AssemblyProductAttribute
attribute =
(AssemblyProductAttribute)Attribute.GetCustomAttribute(
this.ProtectedAssembly,
typeof(AssemblyProductAttribute));
if
(attribute != null && !string.IsNullOrEmpty(attribute.Product))
{
string
folderPath = Path.Combine(
Path.GetTempPath(), attribute.Product);
if
(!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
//
Use public key as index to search license file.
string
publicKey =
this.GetPublicKeyHexString(
this.ProtectedAssembly.GetName().GetPublicKey());
string[]
files = Directory.GetFiles(folderPath);
foreach
(string file in
files)
{
try
{
StreamReader loReader = new StreamReader(
File.Open(file,
FileMode.Open,
FileAccess.ReadWrite,
FileShare.None));
string textLine = loReader.ReadLine();
loReader.Close();
if (textLine == publicKey)
{
this.FilePath = file;
break;
}
}
catch
{
}
}
if
(this.FilePath == null)
{
this.FilePath = Path.Combine(
folderPath,
Path.GetRandomFileName());
}
}
else
{
throw
new ArgumentException("Product name isn't set in the protected
assembly!");
}
}
/// <summary>
/// Write byte array to the protected storage.
/// </summary>
/// <param
name="toWrite">Byte array to
write.</param>
public void WriteByteArray(byte[]
toWrite)
{
if
(!string.IsNullOrEmpty(this.FilePath))
{
FileStream
fileStream = File.Open(
this.FilePath,
FileMode.Create,
FileAccess.Write,
FileShare.None);
StreamWriter
writer = new StreamWriter(fileStream);
string
publicKey = this.GetPublicKeyHexString(
this.ProtectedAssembly.GetName().GetPublicKey());
writer.WriteLine(publicKey);
string
lsEncrLicense = Convert.ToBase64String(toWrite);
writer.WriteLine(lsEncrLicense);
writer.Close();
fileStream.Close();
}
}
private string GetPublicKeyHexString(byte[]
publicKey)
{
string
stringKey = string.Empty;
foreach
(byte b in
publicKey)
{
stringKey += b.ToString("X2");
}
return
stringKey;
}
}
[VB.NET]
'''
<summary>
'''
Custom protected storage which uses temporary file.
'''
Pay attentions, this is just an example which demonstrates how the
'''
custom protected storage can be implemented. The temp folder isn't a good
'''
and secure place to store licensing information.
'''
</summary>
Public
Class TempFileProtectedStorage
Implements
IProtectedStorage
Public Sub New()
End Sub
''' <summary>
''' Gets or
sets path of the temporary file.
''' </summary>
Private Property FilePath() As
String
Get
Return
m_FilePath
End
Get
Set(value
As String)
m_FilePath = value
End
Set
End Property
Private
m_FilePath As String
''' <summary>
''' Gets or
sets protected assembly.
''' </summary>
Private Property ProtectedAssembly() As
Assembly
Get
Return
m_ProtectedAssembly
End
Get
Set(value
As Assembly)
m_ProtectedAssembly = value
End
Set
End Property
Private
m_ProtectedAssembly As Assembly
''' <summary>
''' Dispose
protected storage object
''' </summary>
Public Sub Dispose() _
Implements IProtectedStorage.Dispose
End Sub
''' <summary>
''' Gets stream
to read license document from the protected storage
''' </summary>
''' <returns>Stream to
read document from</returns>
Public Function GetInputStream() As
System.IO.Stream _
Implements IProtectedStorage.GetInputStream
Dim
fileStream As FileStream
= File.Open( _
Me.FilePath, _
FileMode.OpenOrCreate,
_
FileAccess.ReadWrite,
_
FileShare.None)
If
fileStream.Length > 0 Then
Dim
reader As New StreamReader(fileStream)
reader.ReadLine()
Dim
lsEncrLicense As String
= reader.ReadLine()
reader.Close()
fileStream.Close()
Dim
encrypted As Byte()
= Convert.FromBase64String(lsEncrLicense)
Dim
stream As New MemoryStream(encrypted)
Return
stream
Else
fileStream.Close()
Return
Nothing
End
If
End Function
''' <summary>
''' Initialize
protected storage.
''' </summary>
''' <param name="licenseKeyProvider">License key provider.</param>
Public Sub Initialize(licenseKeyProvider As ILicenseKeyProvider)
_
Implements IProtectedStorage.Initialize
Me.FilePath
= Nothing
' In this
example we use name of the product to create
'
temporary folder.
Me.ProtectedAssembly
= licenseKeyProvider.[GetType]().Assembly
Dim
productAttribute As AssemblyProductAttribute
= _
DirectCast(Attribute.GetCustomAttribute(Me.ProtectedAssembly, _
GetType(AssemblyProductAttribute)), AssemblyProductAttribute)
If
productAttribute IsNot Nothing
_
AndAlso Not String.IsNullOrEmpty(productAttribute.Product)
Then
Dim
folderPath As String
= System.IO.Path.Combine( _
System.IO.Path.GetTempPath(),
productAttribute.Product)
If
Not Directory.Exists(folderPath)
Then
Directory.CreateDirectory(folderPath)
End If
'
Use public key as index to search license file.
Dim
publicKey As String
= Me.GetPublicKeyHexString( _
Me.ProtectedAssembly.GetName().GetPublicKey())
Dim
files As String()
= Directory.GetFiles(folderPath)
For
Each fileName As
String In files
Try
Dim loReader As New StreamReader(
_
File.Open(fileName,
_
FileMode.Open,
_
FileAccess.ReadWrite,
_
FileShare.None))
Dim textLine As String = loReader.ReadLine()
loReader.Close()
If textLine = publicKey Then
Me.FilePath = fileName
Exit Try
End If
Catch
End Try
Next
If
Me.FilePath Is Nothing Then
Me.FilePath = System.IO.Path.Combine(
_
folderPath, System.IO.Path.GetRandomFileName())
End
If
Else
Throw
New ArgumentException("Product name isn't set in the protected
assembly!")
End
If
End Sub
''' <summary>
''' Write byte
array to the protected storage.
''' </summary>
''' <param name="toWrite">Byte array to write.</param>
Public Sub WriteByteArray(toWrite As
Byte()) _
Implements IProtectedStorage.WriteByteArray
If Not String.IsNullOrEmpty(Me.FilePath) Then
Dim
fileStream As FileStream
= File.Open( _
Me.FilePath, _
FileMode.Create,
_
FileAccess.Write,
_
FileShare.None)
Dim
writer As New StreamWriter(fileStream)
Dim
publicKey As String
= Me.GetPublicKeyHexString( _
Me.ProtectedAssembly.GetName().GetPublicKey())
writer.WriteLine(publicKey)
Dim
lsEncrLicense As String
= Convert.ToBase64String(toWrite)
writer.WriteLine(lsEncrLicense)
writer.Close()
fileStream.Close()
End
If
End Sub
Private Function GetPublicKeyHexString(publicKey As Byte()) As String
Dim
stringKey As String
= String.Empty
For
Each b As Byte In publicKey
stringKey += b.ToString("X2")
Next
Return
stringKey
End Function
End
Class
The final step you have to do is informing the protection library about class which implements custom protected storage:
[C#]
//
Instantiate license object and assign assemblies for validation.
this.license
= (Manco.Licensing.License)LicenseManager.Validate(
typeof(MainWindow), this);
//
Set type which implements custom protected storage.
//
It must be done before any other operations with license object.
this.license.CustomProtectedStorageType
= typeof(TempFileProtectedStorage);
this.license.LicensedAssembly
= typeof(MainWindow).Assembly;
this.licenseProperties
= this.license.GetLicenseProperties();
this.licenseState
= this.license.GetLicenseState(true);
[VB.NET]
'
Instantiate license object and assign assemblies for validation.
Me.license
= LicenseManager.Validate(GetType(MainWindow),
Me)
' Set type which implements custom protected storage.
' It must be done before any other operations with license object.
Me.license.CustomProtectedStorageType = GetType(TempFileProtectedStorage)
Me.license.LicensedAssembly
= GetType(MainWindow).Assembly
Me.licenseProperties
= Me.license.GetLicenseProperties()
Me.licenseState
= Me.license.GetLicenseState(True)
You can find sample solution which demonstrates creation of the custom protected storage at the http://www.mancosoftware.com/licensing/download.htm.