Repository: dnauck/Portable.Licensing
Branch: develop
Commit: 6ec8ce3b20d0
Files: 71
Total size: 182.3 KB
Directory structure:
gitextract_zc1asx_w/
├── .gitignore
├── .paket/
│ └── paket.targets
├── .travis.yml
├── Icons/
│ └── Portable.Licensing.icns
├── LICENSE.md
├── Portable.Licensing.nuspec
├── README.md
├── Samples/
│ ├── Android.Sample/
│ │ ├── Android.Sample/
│ │ │ ├── Android.Sample.csproj
│ │ │ ├── Assets/
│ │ │ │ └── AboutAssets.txt
│ │ │ ├── MainActivity.cs
│ │ │ ├── Properties/
│ │ │ │ └── AssemblyInfo.cs
│ │ │ └── Resources/
│ │ │ ├── AboutResources.txt
│ │ │ ├── Layout/
│ │ │ │ └── Main.axml
│ │ │ ├── Resource.Designer.cs
│ │ │ └── Values/
│ │ │ └── Strings.xml
│ │ ├── Android.Sample.sln
│ │ └── Android.Sample.sln.DotSettings
│ └── iOS.Sample/
│ ├── iOS.Sample/
│ │ ├── AppDelegate.cs
│ │ ├── Info.plist
│ │ ├── Main.cs
│ │ ├── MyViewController.cs
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ └── iOS.Sample.csproj
│ ├── iOS.Sample.sln
│ └── iOS.Sample.sln.DotSettings
├── Tools/
│ └── xpkg/
│ └── xpkg
├── Xamarin/
│ ├── Details.md
│ └── GettingStarted.md
├── appveyor.yml
├── build-runTests.bat
├── build.bat
├── build.fsx
├── build.sh
├── lib/
│ └── License.txt
├── paket.dependencies
└── src/
├── CommonAssemblyInfo.cs
├── Portable.Licensing/
│ ├── AssemblyBuildDateAttribute.cs
│ ├── Customer.cs
│ ├── IFluentInterface.cs
│ ├── ILicenseBuilder.cs
│ ├── License.cs
│ ├── LicenseAttributes.cs
│ ├── LicenseBuilder.cs
│ ├── LicenseType.cs
│ ├── Portable.Licensing.csproj
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── Security/
│ │ └── Cryptography/
│ │ ├── KeyFactory.cs
│ │ ├── KeyGenerator.cs
│ │ └── KeyPair.cs
│ └── Validation/
│ ├── GeneralValidationFailure.cs
│ ├── IAddAdditionalValidationChain.cs
│ ├── IAssertValidation.cs
│ ├── ICompleteValidationChain.cs
│ ├── ILicenseValidator.cs
│ ├── IStartValidationChain.cs
│ ├── IValidationChain.cs
│ ├── IValidationChainCondition.cs
│ ├── IValidationFailure.cs
│ ├── InvalidSignatureValidationFailure.cs
│ ├── LicenseExpiredValidationFailure.cs
│ ├── LicenseValidationExtensions.cs
│ ├── LicenseValidator.cs
│ └── ValidationChainBuilder.cs
├── Portable.Licensing.Tests/
│ ├── KeyGeneratorTests.cs
│ ├── LicenseSignatureTests.cs
│ ├── LicenseValidationTests.cs
│ ├── Portable.Licensing.Tests.csproj
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ └── paket.references
├── Portable.Licensing.sln
└── Portable.Licensing.sln.DotSettings
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/Build
/Publish
/Distribution
/nant-*.log*
packages/
BuildMetrics/
#ignore thumbnails created by windows
Thumbs.db
#Ignore files build by Visual Studio
*.obj
*.exe
*.pdb
*.user
*.aps
*.pch
*.vspscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.cache
*.ilk
*.log
[Bb]in
[Dd]ebug*/
*.lib
*.sbr
obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
*.userprefs
================================================
FILE: .paket/paket.targets
================================================
true
true
$(MSBuildThisFileDirectory)
$(MSBuildThisFileDirectory)..\
$(PaketToolsPath)paket.exe
$(PaketToolsPath)paket.bootstrapper.exe
"$(PaketExePath)"
mono --runtime=v4.0.30319 $(PaketExePath)
"$(PaketBootStrapperExePath)"
mono --runtime=v4.0.30319 $(PaketBootStrapperExePath)
$(MSBuildProjectDirectory)\paket.references
$(MSBuildProjectFullPath).paket.references
$(PaketCommand) restore --references-files $(PaketReferences)
$(PaketBootStrapperCommand)
RestorePackages; $(BuildDependsOn);
================================================
FILE: .travis.yml
================================================
language: objective-c
env:
matrix:
- MONO_VERSION="3.10.0"
before_install:
- wget "http://download.mono-project.com/archive/${MONO_VERSION}/macos-10-x86/MonoFramework-MDK-${MONO_VERSION}.macos10.xamarin.x86.pkg"
- sudo installer -pkg "MonoFramework-MDK-${MONO_VERSION}.macos10.xamarin.x86.pkg" -target /
- mozroots --import --sync --quiet
script:
- ./build.sh PackageNuGetDistribution
================================================
FILE: LICENSE.md
================================================
The MIT License
Copyright (c) 2012 - 2014 Nauck IT KG http://www.nauck-it.de
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: Portable.Licensing.nuspec
================================================
Portable.Licensing
$version$
Nauck IT KG
Daniel Nauck
http://opensource.org/licenses/MIT
http://dev.nauck-it.de/projects/portable-licensing
http://www.nauck-it.de/fileadmin/Portable.Licensing/Portable.Licensing.ico
false
Portable.Licensing is a cross platform software licensing framework which allows you to
implement licensing into your application or library. It provides you all tools to create
and validate licenses for your software.
Portable.Licensing is using the latest military strength, state-of-the-art cryptographic algorithm
to ensure that your software and thus your intellectual property is protected.
It is targeting the Portable Class Library and thus runs on nearly every .NET/Mono profile
including Silverlight, Windows Phone, Windows Store App, Xamarin.iOS, Xamarin.Android, Xamarin.Mac
and XBox 360. Use it for your Desktop- (WinForms, WPF, etc.), Console-, Service-,
Web- (ASP.NET, MVC, etc.), Mobile (Xamarin.iOS, Xamarin.Android) or even LightSwitch applications.
FEATURES
- runs on .NET >= 4.0.3, Silverlight 5, Windows Phone >= 8, Windows Store Apps, Mono, Xamarin.iOS, Xamarin.Android, Xamarin.Mac, XBox 360
- easy creation and validation of your licenses
- trial, standard and subscription licenses
- cryptographic signed licenses, no alteration possible
- allows you to enable/disable program modules or product features
- limit various parameters for your software, e.g. max transactions, etc.
- add additional key/value pair attributes to your licenses
- easily extend the fluent validation API with extension methods
Copyright 2012-2014 Nauck IT KG
Portable.Licensing PCL Portable Licensing License Key KeyGenerator Protection Signing Nauck
================================================
FILE: README.md
================================================
# Documentation #
----------
## About Portable.Licensing ##
Portable.Licensing is a cross platform software licensing framework which allows you to implement licensing into your application or library. It provides you all tools to create and validate licenses for your software.
Portable.Licensing is using the latest military strength, state-of-the-art cryptographic algorithm to ensure that your software and thus your intellectual property is protected.
It is targeting the *Portable Class Library* and thus runs on nearly every .NET/Mono profile including Silverlight, Windows Phone, Windows Store App, Xamarin.iOS, Xamarin.Android, Xamarin.Mac and XBox 360. Use it for your Desktop- (WinForms, WPF, etc.), Console-, Service-, Web- (ASP.NET, MVC, etc.), Mobile (Xamarin.iOS, Xamarin.Android) or even LightSwitch applications.
## Features ##
- runs on .NET >= 4.0.3, Silverlight 5, Windows Phone >= 8, Windows Store Apps, Mono, Xamarin.iOS, Xamarin.Android, Xamarin.Mac, XBox 360
- easy creation and validation of your licenses
- trial, standard and subscription licenses
- cryptographic signed licenses, no alteration possible
- allows you to enable/disable program modules or product features
- limit various parameters for your software, e.g. max transactions, etc.
- add additional key/value pair attributes to your licenses
- easily extend the fluent validation API with extension methods
## Build status
| Platform | Status of last build |
| :------ | :------: | :------: |
| **Mono** | [](https://travis-ci.org/dnauck/Portable.Licensing) |
| **Windows** | [](https://ci.appveyor.com/project/dnauck/portable-licensing) |
----------
## Getting started ##
### License.Manager light ###
A reference implementation of a management application for products, customers and licenses is available here: [https://github.com/dnauck/License.Manager-Light](https://github.com/dnauck/License.Manager-Light)
### License.Manager ###
License.Manager is a web-based management solution for Portable.Licensing developed using AngularJS and ServiceStack.
It enables you to manage customers, products and licenses and provides a
REST service backend for integration with payment providers and 3rd party tools.
License.Manager is available here: [https://github.com/dnauck/License.Manager](https://github.com/dnauck/License.Manager)
### Download ###
[Portable.Licensing](https://nuget.org/packages/Portable.Licensing) is distributed with the popular NuGet Packaging Manager. This will make it easier for developers to get the Portable.Licensing distribution into their project.
Go to the NuGet website for more details: [http://nuget.org/](http://nuget.org/)
NuGet provides several ways to get Portable.Licensing into your Project. The easiest way is to right click your project references in Visual Studio and choose the menu item "Manage NuGet Packages".
Search in the "Online" tab for "Portable.Licensing" and click "Install" on your selected packages.
It is also possible to install the Portable.Licensing packages via the "NuGet Package Manager Console".
Type the following to install the Portable.Licensing library:
PM> Install-Package Portable.Licensing
Or use the following command to get a specific version:
PM> Install-Package Portable.Licensing -Version 1.0.0
### Create a private and public key for your product ###
Portable.Licensing uses the Elliptic Curve Digital Signature Algorithmus (ECDSA) to ensure the license cannot be altered after creation.
First you need to create a new public/private key pair for your product:
var keyGenerator = Portable.Licensing.Security.Cryptography.KeyGenerator.Create();
var keyPair = keyGenerator.GenerateKeyPair();
var privateKey = keyPair.ToEncryptedPrivateKeyString(passPhrase);
var publicKey = keyPair.ToPublicKeyString();
Store the private key securely and distribute the public key with your product.
Normally you create one key pair for each product, otherwise it is possible to use a license with all products using the same key pair.
If you want your customer to buy a new license on each major release you can create a key pair for each release and product.
### Create the license generator ###
Now we need something to generate licenses. This could be easily done with the *LicenseFactory*:
var license = License.New()
.WithUniqueIdentifier(Guid.NewGuid())
.As(LicenseType.Trial)
.ExpiresAt(DateTime.Now.AddDays(30))
.WithMaximumUtilization(5)
.WithProductFeatures(new Dictionary
{
{"Sales Module", "yes"},
{"Purchase Module", "yes"},
{"Maximum Transactions", "10000"}
})
.LicensedTo("John Doe", "john.doe@yourmail.here")
.CreateAndSignWithPrivateKey(privateKey, passPhrase);
Now you can take the license and save it to a file:
File.WriteAllText("License.lic", license.ToString(), Encoding.UTF8);
or
license.Save(xmlWriter);
### Validate the license in your application ###
The easiest way to assert the license is in the entry point of your application.
First load the license from a file or resource:
var license = License.Load(...);
Then you can assert the license:
using Portable.Licensing.Validation;
var validationFailures = license.Validate()
.ExpirationDate()
.When(lic => lic.Type == LicenseType.Trial)
.And()
.Signature(publicKey)
.AssertValidLicense();
Portable.Licesing will not throw any Exception and just return an enumeration of validation failures.
Now you can iterate over possible validation failures:
foreach (var failure in validationFailures)
Console.WriteLine(failure.GetType().Name + ": " + failure.Message + " - " + failure.HowToResolve);
Or simply check if there is any failure:
if (validationFailures.Any())
// ...
Make sure to call `validationFailures.ToList()` or `validationFailures.ToArray()` before using the result multiple times.
----------
## License ##
Portable.Licensing is distributed using the MIT/X11 License.
## Further Information ##
The latest release and documentation can be found on the Portable.Licensing project website:
[http://dev.nauck-it.de/projects/portable-licensing](http://dev.nauck-it.de/projects/portable-licensing)
================================================
FILE: Samples/Android.Sample/Android.Sample/Android.Sample.csproj
================================================
Debug
AnyCPU
8.0.30703
2.0
{C1669549-42DA-49E5-B88B-A6D0AD0A545F}
{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
Library
Properties
Android.Sample
Android.Sample
512
true
Resources\Resource.Designer.cs
Off
true
full
false
bin\Debug\
DEBUG;TRACE
prompt
4
True
None
pdbonly
true
bin\Release\
TRACE
prompt
4
False
SdkOnly
..\Components\Portable.Licensing-1.0.0.0\lib\mobile\Portable.Licensing.dll
False
1.0.0.0
True
1.0.0.0
False
================================================
FILE: Samples/Android.Sample/Android.Sample/Assets/AboutAssets.txt
================================================
Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories) and given a Build Action of "AndroidAsset".
These files will be deployed with you package and will be accessible using Android's
AssetManager, like this:
public class ReadAsset : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
InputStream input = Assets.Open ("my_asset.txt");
}
}
Additionally, some Android functions will automatically load asset files:
Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
================================================
FILE: Samples/Android.Sample/Android.Sample/MainActivity.cs
================================================
using System;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Portable.Licensing;
using Portable.Licensing.Validation;
namespace Android.Sample
{
[Activity(Label = "Android.Sample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
int count = 1;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var licenseContent = @"
77d4c193-6088-4c64-9663-ed7398ae8c1a
Trial
Thu, 31 Dec 2009 23:00:00 GMT
1
John Doe
john@doe.tld
MEUCIQDdDpq/Ddt4hZJlird/BcR6FVKLdWF/DENnd6r/0LuB3gIgVm7RSQx5mcjC32JjCoHNdoL8C+etXOtWKiYGLCT4q6w=
";
var license = License.Load(licenseContent);
var validationFailures =
license.Validate()
.ExpirationDate()
.When(lic => lic.Type == LicenseType.Trial)
.And()
.Signature(Resources.GetString(Resource.String.LicensePublicKey))
.AssertValidLicense().ToList();
if (validationFailures.Any())
{
var dialogBuilder = new AlertDialog.Builder(this);
dialogBuilder.SetTitle("License validation failure!");
dialogBuilder.SetIcon(Android.Resource.Drawable.IcDialogAlert);
var messageBuilder = new StringBuilder();
foreach (var validationFailure in validationFailures)
{
messageBuilder.AppendLine("Failure:");
messageBuilder.AppendLine(validationFailure.Message);
messageBuilder.AppendLine(" ");
messageBuilder.AppendLine("Resolve issue by:");
messageBuilder.AppendLine(validationFailure.HowToResolve);
messageBuilder.AppendLine(" ");
messageBuilder.AppendLine(" ");
}
dialogBuilder.SetMessage(messageBuilder.ToString());
dialogBuilder.SetNeutralButton("Cancel", (sender, args) => { /* close app */ });
dialogBuilder.Show();
}
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById(Resource.Id.MyButton);
button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); };
}
}
}
================================================
FILE: Samples/Android.Sample/Android.Sample/Properties/AssemblyInfo.cs
================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Android.Sample")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Android.Sample")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
================================================
FILE: Samples/Android.Sample/Android.Sample/Resources/AboutResources.txt
================================================
Images, layout descriptions, binary blobs and string dictionaries can be included
in your application as resource files. Various Android APIs are designed to
operate on the resource IDs instead of dealing with images, strings or binary blobs
directly.
For example, a sample Android app that contains a user interface layout (main.xml),
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
would keep its resources in the "Resources" directory of the application:
Resources/
drawable-hdpi/
icon.png
drawable-ldpi/
icon.png
drawable-mdpi/
icon.png
layout/
main.xml
values/
strings.xml
In order to get the build system to recognize Android resources, set the build action to
"AndroidResource". The native Android APIs do not operate directly with filenames, but
instead operate on resource IDs. When you compile an Android application that uses resources,
the build system will package the resources for distribution and generate a class called
"Resource" that contains the tokens for each one of the resources included. For example,
for the above Resources layout, this is what the Resource class would expose:
public class Resource {
public class drawable {
public const int icon = 0x123;
}
public class layout {
public const int main = 0x456;
}
public class strings {
public const int first_string = 0xabc;
public const int second_string = 0xbcd;
}
}
You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main
to reference the layout/main.xml file, or Resource.strings.first_string to reference the first
string in the dictionary file values/strings.xml.
================================================
FILE: Samples/Android.Sample/Android.Sample/Resources/Layout/Main.axml
================================================
================================================
FILE: Samples/Android.Sample/Android.Sample/Resources/Resource.Designer.cs
================================================
#pragma warning disable 1591
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
// Runtime Version:4.0.30319.18033
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
[assembly: Android.Runtime.ResourceDesignerAttribute("Android.Sample.Resource", IsApplication=true)]
namespace Android.Sample
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
public partial class Resource
{
Resource()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues ();
}
public static void UpdateIdValues()
{
}
public partial class Attribute
{
private Attribute()
{
}
}
public partial class Drawable
{
// aapt resource value: 0x7f020000
public const int Icon = 2130837504;
private Drawable()
{
}
}
public partial class Id
{
// aapt resource value: 0x7f050000
public const int MyButton = 2131034112;
private Id()
{
}
}
public partial class Layout
{
// aapt resource value: 0x7f030000
public const int Main = 2130903040;
private Layout()
{
}
}
public partial class String
{
// aapt resource value: 0x7f040002
public const int ApplicationName = 2130968578;
// aapt resource value: 0x7f040001
public const int Hello = 2130968577;
// aapt resource value: 0x7f040000
public const int LicensePublicKey = 2130968576;
private String()
{
}
}
}
}
#pragma warning restore 1591
================================================
FILE: Samples/Android.Sample/Android.Sample/Resources/Values/Strings.xml
================================================
MIIBKjCB4wYHKoZIzj0CATCB1wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEIQNrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClgIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABNVLQ1xKY80BFMgGXec++Vw7n8vvNrq32PaHuBiYMm0PEj2JoB7qSSWhfgcjxNVJsxqJ6gDQVWgl0r7LH4dr0KU=
Hello World, Click Me!
Android.Sample
================================================
FILE: Samples/Android.Sample/Android.Sample.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{706292EF-A192-48CF-9DB7-9FDC32CB0F0A}"
ProjectSection(SolutionItems) = preProject
..\..\..\Portable.Licensing\paket.dependencies = ..\..\..\Portable.Licensing\paket.dependencies
..\..\..\Portable.Licensing\paket.lock = ..\..\..\Portable.Licensing\paket.lock
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Android.Sample", "Android.Sample\Android.Sample.csproj", "{C1669549-42DA-49E5-B88B-A6D0AD0A545F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C1669549-42DA-49E5-B88B-A6D0AD0A545F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1669549-42DA-49E5-B88B-A6D0AD0A545F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1669549-42DA-49E5-B88B-A6D0AD0A545F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{C1669549-42DA-49E5-B88B-A6D0AD0A545F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1669549-42DA-49E5-B88B-A6D0AD0A545F}.Release|Any CPU.Build.0 = Release|Any CPU
{C1669549-42DA-49E5-B88B-A6D0AD0A545F}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
================================================
FILE: Samples/Android.Sample/Android.Sample.sln.DotSettings
================================================
<data><IncludeFilters /><ExcludeFilters /></data>
<data />
================================================
FILE: Samples/iOS.Sample/iOS.Sample/AppDelegate.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using Portable.Licensing;
using Portable.Licensing.Validation;
namespace iOS.Sample
{
[Register("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
const string licensePublicKey = @"MIIBKjCB4wYHKoZIzj0CATCB1wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEIQNrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClgIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABNVLQ1xKY80BFMgGXec++Vw7n8vvNrq32PaHuBiYMm0PEj2JoB7qSSWhfgcjxNVJsxqJ6gDQVWgl0r7LH4dr0KU=";
UIWindow window;
MyViewController viewController;
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
var licenseContent = @"
77d4c193-6088-4c64-9663-ed7398ae8c1a
Trial
Thu, 31 Dec 2009 23:00:00 GMT
1
John Doe
john@doe.tld
MEUCIQDdDpq/Ddt4hZJlird/BcR6FVKLdWF/DENnd6r/0LuB3gIgVm7RSQx5mcjC32JjCoHNdoL8C+etXOtWKiYGLCT4q6w=
";
var license = License.Load(licenseContent);
var validationFailures =
license.Validate()
.ExpirationDate()
.When(lic => lic.Type == LicenseType.Trial)
.And()
.Signature(licensePublicKey)
.AssertValidLicense().ToList();
if (validationFailures.Any())
{
var messageBuilder = new StringBuilder();
foreach (var validationFailure in validationFailures)
{
messageBuilder.AppendLine("Failure:");
messageBuilder.AppendLine(validationFailure.Message);
messageBuilder.AppendLine(" ");
messageBuilder.AppendLine("Resolve issue by:");
messageBuilder.AppendLine(validationFailure.HowToResolve);
messageBuilder.AppendLine(" ");
messageBuilder.AppendLine(" ");
}
new UIAlertView ("License validation failure!", messageBuilder.ToString(), null, "Cancel").Show();
}
window = new UIWindow(UIScreen.MainScreen.Bounds);
viewController = new MyViewController();
window.RootViewController = viewController;
window.MakeKeyAndVisible();
return true;
}
}
}
================================================
FILE: Samples/iOS.Sample/iOS.Sample/Info.plist
================================================
UIDeviceFamily
1
2
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
MinimumOSVersion
3.2
CFBundleDisplayName
Licensing Sample
================================================
FILE: Samples/iOS.Sample/iOS.Sample/Main.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace iOS.Sample
{
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate");
}
}
}
================================================
FILE: Samples/iOS.Sample/iOS.Sample/MyViewController.cs
================================================
using System;
using MonoTouch.UIKit;
using System.Drawing;
namespace iOS.Sample
{
public class MyViewController : UIViewController
{
UIButton button;
int numClicks = 0;
float buttonWidth = 200;
float buttonHeight = 50;
public MyViewController()
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
View.Frame = UIScreen.MainScreen.Bounds;
View.BackgroundColor = UIColor.White;
View.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
button = UIButton.FromType(UIButtonType.RoundedRect);
button.Frame = new RectangleF(
View.Frame.Width / 2 - buttonWidth / 2,
View.Frame.Height / 2 - buttonHeight / 2,
buttonWidth,
buttonHeight);
button.SetTitle("Click me", UIControlState.Normal);
button.TouchUpInside += (object sender, EventArgs e) =>
{
button.SetTitle(String.Format("clicked {0} times", numClicks++), UIControlState.Normal);
};
button.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleTopMargin |
UIViewAutoresizing.FlexibleBottomMargin;
View.AddSubview(button);
}
}
}
================================================
FILE: Samples/iOS.Sample/iOS.Sample/Properties/AssemblyInfo.cs
================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("iOS.Sample")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("iOS.Sample")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("20e317da-48a5-44bf-aade-5da1046bf568")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
================================================
FILE: Samples/iOS.Sample/iOS.Sample/iOS.Sample.csproj
================================================
Debug
iPhoneSimulator
8.0.30703
2.0
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}
{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
Exe
iOS.Sample
Resources
True
full
False
bin\iPhoneSimulator\Debug
DEBUG
prompt
4
False
None
True
PortableLicensingiOSSample
none
True
bin\iPhoneSimulator\Release
prompt
4
False
None
PortableLicensingiOSSample
True
full
False
bin\iPhone\Debug
DEBUG
prompt
4
False
True
iPhone Developer
iOS.Sample
none
True
bin\iPhone\Release
prompt
4
False
iPhone Developer
iOS.Sample
none
True
bin\iPhone\Ad-Hoc
prompt
4
False
iPhone Distribution
True
iOS.Sample
none
True
bin\iPhone\AppStore
prompt
4
False
iPhone Distribution
iOS.Sample
False
1.0.0.0
..\Components\Portable.Licensing-1.0.0.0\lib\mobile\Portable.Licensing.dll
True
1.0.0.0
False
================================================
FILE: Samples/iOS.Sample/iOS.Sample.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{1E85F3C2-210B-43F2-9135-CC771B654196}"
ProjectSection(SolutionItems) = preProject
..\..\..\Portable.Licensing\paket.dependencies = ..\..\..\Portable.Licensing\paket.dependencies
..\..\..\Portable.Licensing\paket.lock = ..\..\..\Portable.Licensing\paket.lock
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Sample", "iOS.Sample\iOS.Sample.csproj", "{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|iPhone = Ad-Hoc|iPhone
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
AppStore|iPhone = AppStore|iPhone
AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
Debug|iPhone = Debug|iPhone
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.AppStore|iPhone.Build.0 = AppStore|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Debug|iPhone.ActiveCfg = Debug|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Debug|iPhone.Build.0 = Debug|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Release|iPhone.ActiveCfg = Release|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Release|iPhone.Build.0 = Release|iPhone
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{2C8B478A-A9A6-4C6B-81C5-EE2923B7ECCA}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
================================================
FILE: Samples/iOS.Sample/iOS.Sample.sln.DotSettings
================================================
<data><IncludeFilters /><ExcludeFilters /></data>
<data />
================================================
FILE: Tools/xpkg/xpkg
================================================
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
mono $DIR/xpkg.exe "$@"
================================================
FILE: Xamarin/Details.md
================================================
Portable.Licensing is a cross platform software licensing framework which allows you to implement licensing into your application or library. It provides you all tools to create and validate licenses for your software.
Portable.Licensing is using the latest military strength, state-of-the-art cryptographic algorithm to ensure that your software and thus your intellectual property is protected.
It is targeting the *Portable Class Library* and thus runs on nearly every .NET/Mono profile including Silverlight, Windows Phone, Windows Store App, Xamarin.iOS, Xamarin.Android, Xamarin.Mac and XBox 360. Use it for your Desktop- (WinForms, WPF, etc.), Console-, Service-, Web- (ASP.NET, MVC, etc.), Mobile (Xamarin.iOS, Xamarin.Android) or even LightSwitch applications.
## Features ##
- runs on .NET >= 4.0.3, Silverlight 5, Windows Phone >= 8, Windows Store Apps, Mono, Xamarin.iOS, Xamarin.Android, Xamarin.Mac, XBox 360
- easy creation and validation of your licenses
- trial, standard and subscription licenses
- cryptographic signed licenses, no alteration possible
- allows you to enable/disable program modules or product features
- limit various parameters for your software, e.g. max transactions, etc.
- add additional key/value pair attributes to your licenses
- easily extend the fluent validation API with extension methods
----------
### License.Manager light ###
A reference implementation of a management application for products, customers and licenses is available here: [https://github.com/dnauck/License.Manager-Light](https://github.com/dnauck/License.Manager-Light)
### License.Manager ###
License.Manager is a web-based management solution for Portable.Licensing developed using AngularJS and ServiceStack.
It enables you to manage customers, products and licenses and provides a
REST service backend for integration with payment providers and 3rd party tools.
License.Manager is available here: [https://github.com/dnauck/License.Manager](https://github.com/dnauck/License.Manager)
### Validate the license in your application ###
The easiest way to assert the license is in the entry point of your application.
First load the license from a file or resource:
var license = License.Load(...);
Then you can assert the license:
var validationFailures = license.Validate()
.ExpirationDate()
.When(lic => lic.Type == LicenseType.Trial)
.And()
.Signature(publicKey)
.AssertValidLicense();
----------
## License ##
Portable.Licensing is distributed using the MIT/X11 License.
## Further Information ##
The latest release and documentation can be found on the Portable.Licensing project website:
[http://dev.nauck-it.de/projects/portable-licensing](http://dev.nauck-it.de/projects/portable-licensing)
================================================
FILE: Xamarin/GettingStarted.md
================================================
## Getting started ##
### License.Manager light ###
A reference implementation of a management application for products, customers and licenses is available here: [https://github.com/dnauck/License.Manager-Light](https://github.com/dnauck/License.Manager-Light)
### Create a private and public key for your product ###
Portable.Licensing uses the Elliptic Curve Digital Signature Algorithmus (ECDSA) to ensure the license cannot be altered after creation.
First you need to create a new public/private key pair for your product:
var keyGenerator = Portable.Licensing.Security.Cryptography.KeyGenerator.Create();
var keyPair = keyGenerator.GenerateKeyPair();
var privateKey = keyPair.ToEncryptedPrivateKeyString(passPhrase);
var publicKey = keyPair.ToPublicKeyString();
Store the private key securely and distribute the public key with your product.
Normally you create one key pair for each product, otherwise it is possible to use a license with all products using the same key pair.
If you want your customer to buy a new license on each major release you can create a key pair for each release and product.
### Create the license generator ###
Now we need something to generate licenses. This could be easily done with the *LicenseFactory*:
var license = License.New()
.WithUniqueIdentifier(Guid.NewGuid())
.As(LicenseType.Trial)
.ExpiresAt(DateTime.Now.AddDays(30))
.WithMaximumUtilization(5)
.WithProductFeatures(new Dictionary
{
{"Sales Module", "yes"},
{"Purchase Module", "yes"},
{"Maximum Transactions", "10000"}
})
.LicensedTo("John Doe", "john.doe@yourmail.here")
.CreateAndSignWithPrivateKey(privateKey, passPhrase);
Now you can take the license and save it to a file:
File.WriteAllText("License.lic", license.ToString(), Encoding.UTF8);
or
license.Save(xmlWriter);
### Validate the license in your application ###
The easiest way to assert the license is in the entry point of your application.
First load the license from a file or resource:
var license = License.Load(...);
Then you can assert the license:
using Portable.Licensing.Validation;
var validationFailures = license.Validate()
.ExpirationDate()
.When(lic => lic.Type == LicenseType.Trial)
.And()
.Signature(publicKey)
.AssertValidLicense();
Portable.Licesing will not throw any Exception and just return an enumeration of validation failures.
Now you can iterate over possible validation failures:
foreach (var failure in validationFailures)
Console.WriteLine(failure.GetType().Name + ": " + failure.Message + " - " + failure.HowToResolve);
Or simply check if there is any failure:
if (validationResults.Any())
// ...
Make sure to call `validationFailures.ToList()` or `validationFailures.ToArray()` before using the result multiple times.
================================================
FILE: appveyor.yml
================================================
init:
- git config --global core.autocrlf input
build_script:
- cmd: build.bat PackageNuGetDistribution
test: off
artifacts:
- path: bin
name: bin
================================================
FILE: build-runTests.bat
================================================
@echo off
cls
.paket\paket.bootstrapper.exe prerelease
if errorlevel 1 (
exit /b %errorlevel%
)
.paket\paket.exe restore -v
if errorlevel 1 (
exit /b %errorlevel%
)
packages\FAKE\tools\FAKE.exe build.fsx target=Test %*
================================================
FILE: build.bat
================================================
@echo off
cls
.paket\paket.bootstrapper.exe prerelease
if errorlevel 1 (
exit /b %errorlevel%
)
.paket\paket.exe restore -v
if errorlevel 1 (
exit /b %errorlevel%
)
packages\FAKE\tools\FAKE.exe build.fsx %*
================================================
FILE: build.fsx
================================================
// include Fake lib
#I @"packages/FAKE/tools"
#r @"FakeLib.dll"
open Fake
open Fake.AssemblyInfoFile
open System
// build properties
let frameworkProfile = @"portable-net403+sl5+netcore45+wp8+MonoAndroid1+MonoTouch1" // profile 147
let buildTarget = getBuildParamOrDefault "buildTarget" "Build"
let buildConfiguration = getBuildParamOrDefault "buildConfiguration" "Release"
// common path properties
let sourceDir = currentDirectory @@ "src"
let buildDir = currentDirectory @@ "Build"
let buildMergedDir = buildDir @@ "merged"
let buildMetricsDir = currentDirectory @@ "BuildMetrics"
let distributionDir = currentDirectory @@ "Distribution"
let publishDir = currentDirectory @@ "Publish"
let solutionFile = sourceDir @@ "Portable.Licensing.sln"
// tools path properties
let toolsDir = currentDirectory @@ "Tools"
let nugetExecutable = "packages" @@ "NuGet.CommandLine" @@ "tools" @@ "NuGet.exe"
let mergerExecutable = toolsDir @@ "ILRepack" @@ "ILRepack.exe"
let xpkgExecutable = toolsDir @@ "xpkg" @@ "xpkg.exe"
// common assembly info properties
let assemblyVersion = getBuildParamOrDefault "assemblyVersion" "1.0.0.0"
let assemblyFileVersion = getBuildParamOrDefault "assemblyFileVersion" "1.1.0.0"
let assemblyInformationalVersion = getBuildParamOrDefault "assemblyInformationalVersion" "1.1.0"
// Targets
Target "All" DoNothing
Target "Clean" (fun _ ->
CleanDirs [
buildDir
buildMetricsDir
distributionDir
publishDir ]
)
Target "CreateAssemblyInfo" (fun _ ->
CreateCSharpAssemblyInfo (sourceDir @@ "CommonAssemblyInfo.cs")
[
Attribute.Company "Nauck IT KG"
Attribute.Product "Portable.Licensing"
Attribute.Copyright (sprintf "Copyright 2012 - %A Nauck IT KG" DateTime.Now.Year)
Attribute.Version assemblyVersion
Attribute.FileVersion assemblyFileVersion
Attribute.InformationalVersion assemblyInformationalVersion
]
)
Target "Build" (fun _ ->
build (fun msbuild ->
{msbuild with
Targets = [buildTarget]
Properties = ["Configuration", buildConfiguration]
}
) solutionFile
)
Target "Test" (fun _ ->
!! (buildDir @@ "*Tests.dll")
|> NUnit (fun p ->
{p with
//DisableShadowCopy = true;
OutputFile = buildMetricsDir @@ "nunit-result.xml" })
)
Target "MergeAssemblies" (fun _ ->
CreateDir buildMergedDir
let result =
ExecProcess (fun info ->
info.FileName <- mergerExecutable
info.WorkingDirectory <- buildDir
info.Arguments <- sprintf "-target:library -internalize -verbose -lib:%s /out:%s %s %s" buildDir (buildMergedDir @@ "Portable.Licensing.dll") "Portable.Licensing.dll" "BouncyCastle.Crypto.dll"
) (TimeSpan.FromMinutes 5.)
if result <> 0 then failwithf "Error during ILRepack execution."
let filesToDelete =
!+ (buildDir @@ "Portable.Licensing.*")
++ (buildDir @@ "BouncyCastle.Crypto.*")
-- (buildDir @@ "Portable.Licensing.XML") |> Scan
DeleteFiles filesToDelete
let filesToCopy =
!+ (buildMergedDir @@ "Portable.Licensing.*") |> Scan
Copy buildDir filesToCopy
)
Target "PreparePackaging" (fun _ ->
// create the directory structure for the deployment zip and NuGet package
// and copy in the files to deploy
let docsDir = distributionDir @@ "Documentation"
CreateDir docsDir
CopyFile docsDir "Readme.md"
CopyFile docsDir "LICENSE.md"
let libsDir = distributionDir @@ "lib" @@ frameworkProfile
CreateDir libsDir
let librariesToDeploy =
!+ (buildDir @@ "Portable.Licensing.dll")
++ (buildDir @@ "Portable.Licensing.XML")
-- (buildDir @@ "Portable.Licensing.pdb") |> Scan
Copy libsDir librariesToDeploy
)
Target "PackgaeZipDistribution" (fun _ ->
Zip distributionDir (publishDir @@ String.Format(@"Portable.Licensing-{0}.zip", assemblyInformationalVersion)) !! (distributionDir @@ "**")
)
Target "PackageNuGetDistribution" (fun _ ->
// rename Readme.md to Readme.txt in the NuGet package, so that the file
// could be shown automaticly by VS during package installation
CopyFile distributionDir "Readme.md"
Rename (distributionDir @@ "Readme.txt") (distributionDir @@ "Readme.md")
let result =
ExecProcess (fun info ->
info.FileName <- nugetExecutable
info.WorkingDirectory <- "./"
info.Arguments <- sprintf "pack Portable.Licensing.nuspec -Version %s -OutputDirectory %s" assemblyInformationalVersion publishDir
) (TimeSpan.FromMinutes 5.)
if result <> 0 then failwithf "Error during NuGet creation."
// delete the renamed file
DeleteFile (distributionDir @@ "Readme.txt")
)
Target "PackageXamarinDistribution" (fun _ ->
xpkgPack (fun p ->
{p with
ToolPath = xpkgExecutable;
Package = "Portable.Licensing";
Version = assemblyFileVersion;
OutputPath = publishDir
Project = "Portable.Licensing"
Summary = "Portable.Licensing is a cross platform software licensing framework which allows you to implement licensing into your application or library"
Publisher = "Nauck IT KG"
Website = "http://dev.nauck-it.de/projects/portable-licensing"
Details = "./Xamarin/Details.md"
License = "License.md"
GettingStarted = "./Xamarin/GettingStarted.md"
Icons = ["./Xamarin/Portable.Licensing_512x512.png"; "./Xamarin/Portable.Licensing_128x128.png"]
Libraries = ["mobile", "./Distribution/lib/" @@ frameworkProfile @@ "/Portable.Licensing.dll"]
Samples = ["Android Sample. A simple sample that validates a trial license.", "./Samples/Android.Sample/Android.Sample.sln";
"iOS Sample. A simple sample that validates a trial license.", "./Samples/iOS.Sample/iOS.Sample.sln"]
}
)
xpkgValidate (fun p ->
{p with
ToolPath = xpkgExecutable;
Package = "Portable.Licensing";
Version = assemblyFileVersion;
OutputPath = publishDir
Project = "Portable.Licensing"
}
)
)
// Dependencies
"Clean"
==> "CreateAssemblyInfo"
==> "Build"
==> "Test"
==> "MergeAssemblies"
==> "PreparePackaging"
==> "PackgaeZipDistribution"
==> "PackageNuGetDistribution"
==> "PackageXamarinDistribution"
==> "All"
// start build
Run <| getBuildParamOrDefault "target" "All"
================================================
FILE: build.sh
================================================
#!/bin/bash
if test "$OS" = "Windows_NT"
then
# use .Net
.paket/paket.bootstrapper.exe prerelease
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
.paket/paket.exe restore -v
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx
else
# use mono
mono .paket/paket.bootstrapper.exe prerelease
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
mono .paket/paket.exe restore -v
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
mono packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx
fi
================================================
FILE: lib/License.txt
================================================
Please note: our license is an adaptation of the MIT X11 License and should be read as such.
LICENSE
Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: paket.dependencies
================================================
source https://nuget.org/api/v2
nuget FAKE
nuget NUnit
nuget NUnit.Runners
nuget NuGet.CommandLine
================================================
FILE: src/CommonAssemblyInfo.cs
================================================
//
using System.Reflection;
[assembly: AssemblyCompanyAttribute("Nauck IT KG")]
[assembly: AssemblyProductAttribute("Portable.Licensing")]
[assembly: AssemblyCopyrightAttribute("Copyright � 2012 - 2014 Nauck IT KG")]
[assembly: AssemblyVersionAttribute("1.0.0.0")]
[assembly: AssemblyFileVersionAttribute("1.1.0.0")]
[assembly: AssemblyInformationalVersionAttribute("1.1.0")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "1.0.0.0";
}
}
================================================
FILE: src/Portable.Licensing/AssemblyBuildDateAttribute.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
namespace Portable.Licensing
{
///
/// Defines assembly build date information for an assembly manifest.
///
[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
public sealed class AssemblyBuildDateAttribute : Attribute
{
private readonly DateTime buildDate;
///
/// Initializes a new instance of the class
/// with the specified build date.
///
/// The build date of the assembly.
public AssemblyBuildDateAttribute(DateTime buildDate)
{
this.buildDate = buildDate;
}
///
/// Initializes a new instance of the class
/// with the specified build date string.
///
/// The build date of the assembly.
public AssemblyBuildDateAttribute(string buildDateString)
{
buildDate = DateTime.Parse(buildDateString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
///
/// Gets the assembly build date.
///
public DateTime BuildDate
{
get { return buildDate; }
}
}
}
================================================
FILE: src/Portable.Licensing/Customer.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System.Xml.Linq;
namespace Portable.Licensing
{
///
/// The customer of a .
///
public class Customer : LicenseAttributes
{
internal Customer(XElement xmlData)
: base(xmlData, "CustomerData")
{
}
///
/// Gets or sets the Name of this .
///
public string Name
{
get { return GetTag("Name"); }
set { SetTag("Name", value); }
}
///
/// Gets or sets the Company of this .
///
public string Company
{
get { return GetTag("Company"); }
set { SetTag("Company", value); }
}
///
/// Gets or sets the Email of this .
///
public string Email
{
get { return GetTag("Email"); }
set { SetTag("Email", value); }
}
}
}
================================================
FILE: src/Portable.Licensing/IFluentInterface.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel;
namespace Portable.Licensing
{
///
/// Interface that is used to build fluent interfaces and hides methods declared by from IntelliSense.
///
///
/// Code that consumes implementations of this interface should expect one of two things:
///
/// - When referencing the interface from within the same solution (project reference), you will still see the methods this interface is meant to hide.
/// - When referencing the interface through the compiled output assembly (external reference), the standard Object methods will be hidden as intended.
///
/// See http://bit.ly/ifluentinterface for more information.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IFluentInterface
{
///
/// Redeclaration that hides the method from IntelliSense.
///
[EditorBrowsable(EditorBrowsableState.Never)]
Type GetType();
///
/// Redeclaration that hides the method from IntelliSense.
///
[EditorBrowsable(EditorBrowsableState.Never)]
int GetHashCode();
///
/// Redeclaration that hides the method from IntelliSense.
///
[EditorBrowsable(EditorBrowsableState.Never)]
string ToString();
///
/// Redeclaration that hides the method from IntelliSense.
///
[EditorBrowsable(EditorBrowsableState.Never)]
bool Equals(object obj);
}
}
================================================
FILE: src/Portable.Licensing/ILicenseBuilder.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Portable.Licensing
{
///
/// Fluent api to create and sign a new .
///
public interface ILicenseBuilder : IFluentInterface
{
///
/// Sets the unique identifier of the .
///
/// The unique identifier of the .
/// The .
ILicenseBuilder WithUniqueIdentifier(Guid id);
///
/// Sets the of the .
///
/// The of the .
/// The .
ILicenseBuilder As(LicenseType type);
///
/// Sets the expiration date of the .
///
/// The expiration date of the .
/// The .
ILicenseBuilder ExpiresAt(DateTime date);
///
/// Sets the maximum utilization of the .
/// This can be the quantity of developers for a "per-developer-license".
///
/// The maximum utilization of the .
/// The .
ILicenseBuilder WithMaximumUtilization(int utilization);
///
/// Sets the license holder of the .
///
/// The name of the license holder.
/// The email of the license holder.
/// The .
ILicenseBuilder LicensedTo(string name, string email);
///
/// Sets the license holder of the .
///
/// The name of the license holder.
/// The email of the license holder.
/// A delegate to configure the license holder.
/// The .
ILicenseBuilder LicensedTo(string name, string email, Action configureCustomer);
///
/// Sets the license holder of the .
///
/// A delegate to configure the license holder.
/// The .
ILicenseBuilder LicensedTo(Action configureCustomer);
///
/// Sets the licensed product features of the .
///
/// The licensed product features of the .
/// The .
ILicenseBuilder WithProductFeatures(IDictionary productFeatures);
///
/// Sets the licensed product features of the .
///
/// A delegate to configure the product features.
/// The .
ILicenseBuilder WithProductFeatures(Action configureProductFeatures);
///
/// Sets the licensed additional attributes of the .
///
/// The additional attributes of the .
/// The .
ILicenseBuilder WithAdditionalAttributes(IDictionary additionalAttributes);
///
/// Sets the licensed additional attributes of the .
///
/// A delegate to configure the additional attributes.
/// The .
ILicenseBuilder WithAdditionalAttributes(Action configureAdditionalAttributes);
///
/// Create and sign a new with the specified
/// private encryption key.
///
/// The private encryption key for the signature.
/// The pass phrase to decrypt the private key.
/// The signed .
License CreateAndSignWithPrivateKey(string privateKey, string passPhrase);
}
}
================================================
FILE: src/Portable.Licensing/License.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Security;
using Portable.Licensing.Security.Cryptography;
namespace Portable.Licensing
{
///
/// A software license
///
public class License
{
private readonly XElement xmlData;
private readonly string signatureAlgorithm = X9ObjectIdentifiers.ECDsaWithSha512.Id;
///
/// Initializes a new instance of the class.
///
internal License()
{
xmlData = new XElement("License");
}
///
/// Initializes a new instance of the class
/// with the specified content.
///
/// This constructor is only used for loading from XML.
/// The initial content of this .
internal License(XElement xmlData)
{
this.xmlData = xmlData;
}
///
/// Gets or sets the unique identifier of this .
///
public Guid Id
{
get { return new Guid(GetTag("Id") ?? Guid.Empty.ToString()); }
set { if (!IsSigned) SetTag("Id", value.ToString()); }
}
///
/// Gets or set the or this .
///
public LicenseType Type
{
get
{
return
(LicenseType)
Enum.Parse(typeof (LicenseType), GetTag("Type") ?? LicenseType.Trial.ToString(), false);
}
set { if (!IsSigned) SetTag("Type", value.ToString()); }
}
///
/// Get or sets the quantity of this license.
/// E.g. the count of per-developer-licenses.
///
public int Quantity
{
get { return int.Parse(GetTag("Quantity") ?? "0"); }
set { if (!IsSigned) SetTag("Quantity", value.ToString()); }
}
///
/// Gets or sets the product features of this .
///
public LicenseAttributes ProductFeatures
{
get
{
var xmlElement = xmlData.Element("ProductFeatures");
if (!IsSigned && xmlElement == null)
{
xmlData.Add(new XElement("ProductFeatures"));
xmlElement = xmlData.Element("ProductFeatures");
}
else if (IsSigned && xmlElement == null)
{
return null;
}
return new LicenseAttributes(xmlElement, "Feature");
}
}
///
/// Gets or sets the of this .
///
public Customer Customer
{
get
{
var xmlElement = xmlData.Element("Customer");
if (!IsSigned && xmlElement == null)
{
xmlData.Add(new XElement("Customer"));
xmlElement = xmlData.Element("Customer");
}
else if (IsSigned && xmlElement == null)
{
return null;
}
return new Customer(xmlElement);
}
}
///
/// Gets or sets the additional attributes of this .
///
public LicenseAttributes AdditionalAttributes
{
get
{
var xmlElement = xmlData.Element("LicenseAttributes");
if (!IsSigned && xmlElement == null)
{
xmlData.Add(new XElement("LicenseAttributes"));
xmlElement = xmlData.Element("LicenseAttributes");
}
else if (IsSigned && xmlElement == null)
{
return null;
}
return new LicenseAttributes(xmlElement, "Attribute");
}
}
///
/// Gets or sets the expiration date of this .
/// Use this property to set the expiration date for a trial license
/// or the expiration of support & subscription updates for a standard license.
///
public DateTime Expiration
{
get
{
return
DateTime.ParseExact(
GetTag("Expiration") ??
DateTime.MaxValue.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture)
, "r", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
set { if (!IsSigned) SetTag("Expiration", value.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture)); }
}
///
/// Gets the digital signature of this license.
///
/// Use the method to compute a signature.
public string Signature
{
get { return GetTag("Signature"); }
}
///
/// Compute a signature and sign this with the provided key.
///
/// The private key in xml string format to compute the signature.
/// The pass phrase to decrypt the private key.
public void Sign(string privateKey, string passPhrase)
{
var signTag = xmlData.Element("Signature") ?? new XElement("Signature");
try
{
if (signTag.Parent != null)
signTag.Remove();
var privKey = KeyFactory.FromEncryptedPrivateKeyString(privateKey, passPhrase);
var documentToSign = Encoding.UTF8.GetBytes(xmlData.ToString(SaveOptions.DisableFormatting));
var signer = SignerUtilities.GetSigner(signatureAlgorithm);
signer.Init(true, privKey);
signer.BlockUpdate(documentToSign, 0, documentToSign.Length);
var signature = signer.GenerateSignature();
signTag.Value = Convert.ToBase64String(signature);
}
finally
{
xmlData.Add(signTag);
}
}
///
/// Determines whether the property verifies for the specified key.
///
/// The public key in xml string format to verify the .
/// true if the verifies; otherwise false.
public bool VerifySignature(string publicKey)
{
var signTag = xmlData.Element("Signature");
if (signTag == null)
return false;
try
{
signTag.Remove();
var pubKey = KeyFactory.FromPublicKeyString(publicKey);
var documentToSign = Encoding.UTF8.GetBytes(xmlData.ToString(SaveOptions.DisableFormatting));
var signer = SignerUtilities.GetSigner(signatureAlgorithm);
signer.Init(false, pubKey);
signer.BlockUpdate(documentToSign, 0, documentToSign.Length);
return signer.VerifySignature(Convert.FromBase64String(signTag.Value));
}
finally
{
xmlData.Add(signTag);
}
}
///
/// Create a new using the
/// fluent api.
///
/// An instance of the class.
public static ILicenseBuilder New()
{
return new LicenseBuilder();
}
///
/// Loads a from a string that contains XML.
///
/// A that contains XML.
/// A populated from the that contains XML.
public static License Load(string xmlString)
{
return new License(XElement.Parse(xmlString, LoadOptions.None));
}
///
/// Loads a by using the specified
/// that contains the XML.
///
/// A that contains the XML.
/// A populated from the that contains XML.
public static License Load(Stream stream)
{
return new License(XElement.Load(stream, LoadOptions.None));
}
///
/// Loads a by using the specified
/// that contains the XML.
///
/// A that contains the XML.
/// A populated from the that contains XML.
public static License Load(TextReader reader)
{
return new License(XElement.Load(reader, LoadOptions.None));
}
///
/// Loads a by using the specified
/// that contains the XML.
///
/// A that contains the XML.
/// A populated from the that contains XML.
public static License Load(XmlReader reader)
{
return new License(XElement.Load(reader, LoadOptions.None));
}
///
/// Serialize this to a .
///
/// A that the
/// will be written to.
public void Save(Stream stream)
{
xmlData.Save(stream);
}
///
/// Serialize this to a .
///
/// A that the
/// will be written to.
public void Save(TextWriter textWriter)
{
xmlData.Save(textWriter);
}
///
/// Serialize this to a .
///
/// A that the
/// will be written to.
public void Save(XmlWriter xmlWriter)
{
xmlData.Save(xmlWriter);
}
///
/// Returns the indented XML for this .
///
/// A string containing the indented XML.
public override string ToString()
{
return xmlData.ToString();
}
///
/// Gets a value indicating whether this is already signed.
///
private bool IsSigned
{
get { return (!string.IsNullOrEmpty(Signature)); }
}
private void SetTag(string name, string value)
{
var element = xmlData.Element(name);
if (element == null)
{
element = new XElement(name);
xmlData.Add(element);
}
if (value != null)
element.Value = value;
}
private string GetTag(string name)
{
var element = xmlData.Element(name);
return element != null ? element.Value : null;
}
}
}
================================================
FILE: src/Portable.Licensing/LicenseAttributes.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Portable.Licensing
{
///
/// Represents a dictionary of license attributes.
///
public class LicenseAttributes
{
protected readonly XElement xmlData;
protected readonly XName childName;
///
/// Initializes a new instance of the class.
///
internal LicenseAttributes(XElement xmlData, XName childName)
{
this.xmlData = xmlData ?? new XElement("null");
this.childName = childName;
}
///
/// Adds a new element with the specified key and value
/// to the collection.
///
/// The key of the element.
/// The value of the element.
public virtual void Add(string key, string value)
{
SetChildTag(key, value);
}
///
/// Adds all new element into the collection.
///
/// The dictionary of elements.
public virtual void AddAll(IDictionary features)
{
foreach (var feature in features)
Add(feature.Key, feature.Value);
}
///
/// Removes a element with the specified key
/// from the collection.
///
/// The key of the element.
public virtual void Remove(string key)
{
var element =
xmlData.Elements(childName)
.FirstOrDefault(e => e.Attribute("name") != null && e.Attribute("name").Value == key);
if (element != null)
element.Remove();
}
///
/// Removes all elements from the collection.
///
public virtual void RemoveAll()
{
xmlData.RemoveAll();
}
///
/// Gets the value of a element with the
/// specified key.
///
/// The key of the element.
/// The value of the element if available; otherwise null.
public virtual string Get(string key)
{
return GetChildTag(key);
}
///
/// Gets all elements.
///
/// A dictionary of all elements in this collection.
public virtual IDictionary GetAll()
{
return xmlData.Elements(childName).ToDictionary(e => e.Attribute("name").Value, e => e.Value);
}
///
/// Determines whether the specified element is in
/// this collection.
///
/// The key of the element.
/// true if the collection contains this element; otherwise false.
public virtual bool Contains(string key)
{
return xmlData.Elements(childName).Any(e => e.Attribute("name") != null && e.Attribute("name").Value == key);
}
///
/// Determines whether all specified elements are in
/// this collection.
///
/// The list of keys of the elements.
/// true if the collection contains all specified elements; otherwise false.
public virtual bool ContainsAll(string[] keys)
{
return xmlData.Elements(childName).All(e => e.Attribute("name") != null && keys.Contains(e.Attribute("name").Value));
}
protected virtual void SetTag(string name, string value)
{
var element = xmlData.Element(name);
if (element == null)
{
element = new XElement(name);
xmlData.Add(element);
}
if (value != null)
element.Value = value;
}
protected virtual void SetChildTag(string name, string value)
{
var element =
xmlData.Elements(childName)
.FirstOrDefault(e => e.Attribute("name") != null && e.Attribute("name").Value == name);
if (element == null)
{
element = new XElement(childName);
element.Add(new XAttribute("name", name));
xmlData.Add(element);
}
if (value != null)
element.Value = value;
}
protected virtual string GetTag(string name)
{
var element = xmlData.Element(name);
return element != null ? element.Value : null;
}
protected virtual string GetChildTag(string name)
{
var element =
xmlData.Elements(childName)
.FirstOrDefault(e => e.Attribute("name") != null && e.Attribute("name").Value == name);
return element != null ? element.Value : null;
}
}
}
================================================
FILE: src/Portable.Licensing/LicenseBuilder.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Portable.Licensing
{
///
/// Implementation of the , a fluent api
/// to create new licenses.
///
internal class LicenseBuilder : ILicenseBuilder
{
private readonly License license;
///
/// Initializes a new instance of the class.
///
public LicenseBuilder()
{
license = new License();
}
///
/// Sets the unique identifier of the .
///
/// The unique identifier of the .
/// The .
public ILicenseBuilder WithUniqueIdentifier(Guid id)
{
license.Id = id;
return this;
}
///
/// Sets the of the .
///
/// The of the .
/// The .
public ILicenseBuilder As(LicenseType type)
{
license.Type = type;
return this;
}
///
/// Sets the expiration date of the .
///
/// The expiration date of the .
/// The .
public ILicenseBuilder ExpiresAt(DateTime date)
{
license.Expiration = date.ToUniversalTime();
return this;
}
///
/// Sets the maximum utilization of the .
/// This can be the quantity of developers for a "per-developer-license".
///
/// The maximum utilization of the .
/// The .
public ILicenseBuilder WithMaximumUtilization(int utilization)
{
license.Quantity = utilization;
return this;
}
///
/// Sets the license holder of the .
///
/// The name of the license holder.
/// The email of the license holder.
/// The .
public ILicenseBuilder LicensedTo(string name, string email)
{
license.Customer.Name = name;
license.Customer.Email = email;
return this;
}
///
/// Sets the license holder of the .
///
/// The name of the license holder.
/// The email of the license holder.
/// A delegate to configure the license holder.
/// The .
public ILicenseBuilder LicensedTo(string name, string email, Action configureCustomer)
{
license.Customer.Name = name;
license.Customer.Email = email;
configureCustomer(license.Customer);
return this;
}
///
/// Sets the license holder of the .
///
/// A delegate to configure the license holder.
/// The .
public ILicenseBuilder LicensedTo(Action configureCustomer)
{
configureCustomer(license.Customer);
return this;
}
///
/// Sets the licensed product features of the .
///
/// The licensed product features of the .
/// The .
public ILicenseBuilder WithProductFeatures(IDictionary productFeatures)
{
license.ProductFeatures.AddAll(productFeatures);
return this;
}
///
/// Sets the licensed product features of the .
///
/// A delegate to configure the product features.
/// The .
public ILicenseBuilder WithProductFeatures(Action configureProductFeatures)
{
configureProductFeatures(license.ProductFeatures);
return this;
}
///
/// Sets the licensed additional attributes of the .
///
/// The additional attributes of the .
/// The .
public ILicenseBuilder WithAdditionalAttributes(IDictionary additionalAttributes)
{
license.AdditionalAttributes.AddAll(additionalAttributes);
return this;
}
///
/// Sets the licensed additional attributes of the .
///
/// A delegate to configure the additional attributes.
/// The .
public ILicenseBuilder WithAdditionalAttributes(Action configureAdditionalAttributes)
{
configureAdditionalAttributes(license.AdditionalAttributes);
return this;
}
///
/// Create and sign a new with the specified
/// private encryption key.
///
/// The private encryption key for the signature.
/// The pass phrase to decrypt the private key.
/// The signed .
public License CreateAndSignWithPrivateKey(string privateKey, string passPhrase)
{
license.Sign(privateKey, passPhrase);
return license;
}
}
}
================================================
FILE: src/Portable.Licensing/LicenseType.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing
{
///
/// Defines the type of a
///
public enum LicenseType
{
///
/// For trial or demo use
///
Trial = 1,
///
/// Standard license
///
Standard = 2
}
}
================================================
FILE: src/Portable.Licensing/Portable.Licensing.csproj
================================================
10.0
Debug
AnyCPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}
Library
Properties
Portable.Licensing
Portable.Licensing
v4.0
Profile147
512
{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
true
full
false
..\..\Build\
DEBUG;TRACE
prompt
4
..\..\Build\Portable.Licensing.XML
pdbonly
true
..\..\Build\
TRACE
prompt
4
..\..\Build\Portable.Licensing.XML
Properties\CommonAssemblyInfo.cs
..\..\lib\BouncyCastle.Crypto.dll
================================================
FILE: src/Portable.Licensing/Properties/AssemblyInfo.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Resources;
using System.Reflection;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Portable.Licensing")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: CLSCompliant(true)]
================================================
FILE: src/Portable.Licensing/Security/Cryptography/KeyFactory.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
namespace Portable.Licensing.Security.Cryptography
{
internal static class KeyFactory
{
private static readonly string keyEncryptionAlgorithm = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id;
///
/// Encrypts and encodes the private key.
///
/// The private key.
/// The pass phrase to encrypt the private key.
/// The encrypted private key.
public static string ToEncryptedPrivateKeyString(AsymmetricKeyParameter key, string passPhrase)
{
var salt = new byte[16];
var secureRandom = SecureRandom.GetInstance("SHA256PRNG");
secureRandom.SetSeed(SecureRandom.GetSeed(16)); //See Bug #135
secureRandom.NextBytes(salt);
return
Convert.ToBase64String(PrivateKeyFactory.EncryptKey(keyEncryptionAlgorithm, passPhrase.ToCharArray(),
salt, 10, key));
}
///
/// Decrypts the provided private key.
///
/// The encrypted private key.
/// The pass phrase to decrypt the private key.
/// The private key.
public static AsymmetricKeyParameter FromEncryptedPrivateKeyString(string privateKey, string passPhrase)
{
return PrivateKeyFactory.DecryptKey(passPhrase.ToCharArray(), Convert.FromBase64String(privateKey));
}
///
/// Encodes the public key into DER encoding.
///
/// The public key.
/// The encoded public key.
public static string ToPublicKeyString(AsymmetricKeyParameter key)
{
return
Convert.ToBase64String(
SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key)
.ToAsn1Object()
.GetDerEncoded());
}
///
/// Decoded the public key from DER encoding.
///
/// The encoded public key.
/// The public key.
public static AsymmetricKeyParameter FromPublicKeyString(string publicKey)
{
return PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
}
}
}
================================================
FILE: src/Portable.Licensing/Security/Cryptography/KeyGenerator.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Security;
namespace Portable.Licensing.Security.Cryptography
{
///
/// Represents a generator for signature keys of .
///
public class KeyGenerator
{
private readonly IAsymmetricCipherKeyPairGenerator keyGenerator;
///
/// Initializes a new instance of the class
/// with a key size of 256 bits.
///
public KeyGenerator()
: this(256)
{
}
///
/// Initializes a new instance of the class
/// with the specified key size.
///
/// Following key sizes are supported:
/// - 192
/// - 224
/// - 239
/// - 256 (default)
/// - 384
/// - 521
/// The key size.
public KeyGenerator(int keySize)
: this(keySize, SecureRandom.GetSeed(32))
{
}
///
/// Initializes a new instance of the class
/// with the specified key size and seed.
///
/// Following key sizes are supported:
/// - 192
/// - 224
/// - 239
/// - 256 (default)
/// - 384
/// - 521
/// The key size.
/// The seed.
public KeyGenerator(int keySize, byte[] seed)
{
var secureRandom = SecureRandom.GetInstance("SHA256PRNG");
secureRandom.SetSeed(seed);
var keyParams = new KeyGenerationParameters(secureRandom, keySize);
keyGenerator = new ECKeyPairGenerator();
keyGenerator.Init(keyParams);
}
///
/// Creates a new instance of the class.
///
public static KeyGenerator Create()
{
return new KeyGenerator();
}
///
/// Generates a private/public key pair for license signing.
///
/// An containing the keys.
public KeyPair GenerateKeyPair()
{
return new KeyPair(keyGenerator.GenerateKeyPair());
}
}
}
================================================
FILE: src/Portable.Licensing/Security/Cryptography/KeyPair.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using Org.BouncyCastle.Crypto;
namespace Portable.Licensing.Security.Cryptography
{
///
/// Represents a private/public encryption key pair.
///
public class KeyPair
{
private readonly AsymmetricCipherKeyPair keyPair;
///
/// Initializes a new instance of the class
/// with the provided asymmetric key pair.
///
///
internal KeyPair(AsymmetricCipherKeyPair keyPair)
{
this.keyPair = keyPair;
}
///
/// Gets the encrypted and DER encoded private key.
///
/// The pass phrase to encrypt the private key.
/// The encrypted private key.
public string ToEncryptedPrivateKeyString(string passPhrase)
{
return KeyFactory.ToEncryptedPrivateKeyString(keyPair.Private, passPhrase);
}
///
/// Gets the DER encoded public key.
///
/// The public key.
public string ToPublicKeyString()
{
return KeyFactory.ToPublicKeyString(keyPair.Public);
}
}
}
================================================
FILE: src/Portable.Licensing/Validation/GeneralValidationFailure.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Represents a general validation failure.
///
public class GeneralValidationFailure : IValidationFailure
{
///
/// Gets or sets a message that describes the validation failure.
///
public string Message { get; set; }
///
/// Gets or sets a message that describes how to recover from the validation failure.
///
public string HowToResolve { get; set; }
}
}
================================================
FILE: src/Portable.Licensing/Validation/IAddAdditionalValidationChain.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Interface for the fluent validation syntax.
///
public interface IAddAdditionalValidationChain : IFluentInterface
{
///
/// Adds an additional validation chain.
///
/// An instance of .
IStartValidationChain And();
}
}
================================================
FILE: src/Portable.Licensing/Validation/IAssertValidation.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
namespace Portable.Licensing.Validation
{
///
/// Interface for the fluent validation syntax.
///
public interface IAssertValidation : IFluentInterface
{
///
/// Invokes the license assertion.
///
/// An array is when the validation fails.
IEnumerable AssertValidLicense();
}
}
================================================
FILE: src/Portable.Licensing/Validation/ICompleteValidationChain.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Interface for the fluent validation syntax.
/// This interface is used to complete a validation chain.
///
public interface ICompleteValidationChain : IAddAdditionalValidationChain, IAssertValidation
{
}
}
================================================
FILE: src/Portable.Licensing/Validation/ILicenseValidator.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
namespace Portable.Licensing.Validation
{
///
/// Represents a validator.
///
public interface ILicenseValidator
{
///
/// Gets or sets the predicate to determine if the
/// is valid.
///
Predicate Validate { get; set; }
///
/// Gets or sets the predicate to determine if the
/// should be executed.
///
Predicate ValidateWhen { get; set; }
///
/// Gets or sets the result. The
/// will be returned to the application when the fails.
///
IValidationFailure FailureResult { get; set; }
}
}
================================================
FILE: src/Portable.Licensing/Validation/IStartValidationChain.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Interface for the fluent validation syntax.
/// Validators should use this interface to start a new validation chain.
///
public interface IStartValidationChain : IFluentInterface
{
}
}
================================================
FILE: src/Portable.Licensing/Validation/IValidationChain.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Interface for the fluent validation syntax.
/// This interface is used to add a condition or to complete a validation chain.
///
public interface IValidationChain : IValidationChainCondition, ICompleteValidationChain
{
}
}
================================================
FILE: src/Portable.Licensing/Validation/IValidationChainCondition.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
namespace Portable.Licensing.Validation
{
///
/// Interface for the fluent validation syntax.
///
public interface IValidationChainCondition : IFluentInterface
{
///
/// Adds a when predicate to the current validator.
///
/// The predicate that defines the conditions.
/// An instance of .
ICompleteValidationChain When(Predicate predicate);
}
}
================================================
FILE: src/Portable.Licensing/Validation/IValidationFailure.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Represents a failure of a .
///
public interface IValidationFailure
{
///
/// Gets or sets a message that describes the validation failure.
///
string Message { get; set; }
///
/// Gets or sets a message that describes how to recover from the validation failure.
///
string HowToResolve { get; set; }
}
}
================================================
FILE: src/Portable.Licensing/Validation/InvalidSignatureValidationFailure.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Represents a failure when the is invalid.
///
public class InvalidSignatureValidationFailure : IValidationFailure
{
///
/// Gets or sets a message that describes the validation failure.
///
public string Message { get; set; }
///
/// Gets or sets a message that describes how to recover from the validation failure.
///
public string HowToResolve { get; set; }
}
}
================================================
FILE: src/Portable.Licensing/Validation/LicenseExpiredValidationFailure.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace Portable.Licensing.Validation
{
///
/// Represents a expired failure of a .
///
public class LicenseExpiredValidationFailure : IValidationFailure
{
///
/// Gets or sets a message that describes the validation failure.
///
public string Message { get; set; }
///
/// Gets or sets a message that describes how to recover from the validation failure.
///
public string HowToResolve { get; set; }
}
}
================================================
FILE: src/Portable.Licensing/Validation/LicenseValidationExtensions.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Reflection;
namespace Portable.Licensing.Validation
{
///
/// Extension methods for validation.
///
public static class LicenseValidationExtensions
{
///
/// Starts the validation chain of the .
///
/// The to validate.
/// An instance of .
public static IStartValidationChain Validate(this License license)
{
return new ValidationChainBuilder(license);
}
///
/// Validates if the license has been expired.
///
/// The current .
/// An instance of .
public static IValidationChain ExpirationDate(this IStartValidationChain validationChain)
{
var validationChainBuilder = (validationChain as ValidationChainBuilder);
var validator = validationChainBuilder.StartValidatorChain();
validator.Validate = license => license.Expiration > DateTime.Now;
validator.FailureResult = new LicenseExpiredValidationFailure()
{
Message = "Licensing for this product has expired!",
HowToResolve = @"Your license is expired. Please contact your distributor/vendor to renew the license."
};
return validationChainBuilder;
}
///
/// Check whether the product build date of the provided assemblies
/// exceeded the date.
///
/// The current .
/// The list of assemblies to check.
/// An instance of .
public static IValidationChain ProductBuildDate(this IStartValidationChain validationChain, Assembly[] assemblies)
{
var validationChainBuilder = (validationChain as ValidationChainBuilder);
var validator = validationChainBuilder.StartValidatorChain();
validator.Validate = license => assemblies.All(
asm =>
asm.GetCustomAttributes(typeof (AssemblyBuildDateAttribute), false)
.Cast()
.All(a => a.BuildDate < license.Expiration));
validator.FailureResult = new LicenseExpiredValidationFailure()
{
Message = "Licensing for this product has expired!",
HowToResolve = @"Your license is expired. Please contact your distributor/vendor to renew the license."
};
return validationChainBuilder;
}
///
/// Allows you to specify a custom assertion that validates the .
///
/// The current .
/// The predicate to determine of the is valid.
/// The will be returned to the application when the fails.
/// An instance of .
public static IValidationChain AssertThat(this IStartValidationChain validationChain, Predicate predicate, IValidationFailure failure)
{
var validationChainBuilder = (validationChain as ValidationChainBuilder);
var validator = validationChainBuilder.StartValidatorChain();
validator.Validate = predicate;
validator.FailureResult = failure;
return validationChainBuilder;
}
///
/// Validates the .
///
/// The current .
/// The public product key to validate the signature..
/// An instance of .
public static IValidationChain Signature(this IStartValidationChain validationChain, string publicKey)
{
var validationChainBuilder = (validationChain as ValidationChainBuilder);
var validator = validationChainBuilder.StartValidatorChain();
validator.Validate = license => license.VerifySignature(publicKey);
validator.FailureResult = new InvalidSignatureValidationFailure()
{
Message = "License signature validation error!",
HowToResolve = @"The license signature and data does not match. This usually happens when a license file is corrupted or has been altered."
};
return validationChainBuilder;
}
}
}
================================================
FILE: src/Portable.Licensing/Validation/LicenseValidator.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
namespace Portable.Licensing.Validation
{
///
/// Represents a validator.
///
internal class LicenseValidator : ILicenseValidator
{
///
/// Gets or sets the predicate to determine if the
/// is valid.
///
public Predicate Validate { get; set; }
///
/// Gets or sets the predicate to determine if the
/// should be executed.
///
public Predicate ValidateWhen { get; set; }
///
/// Gets or sets the result. The
/// will be returned to the application when the fails.
///
public IValidationFailure FailureResult { get; set; }
}
}
================================================
FILE: src/Portable.Licensing/Validation/ValidationChainBuilder.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace Portable.Licensing.Validation
{
internal class ValidationChainBuilder : IStartValidationChain, IValidationChain
{
private readonly Queue validators;
private ILicenseValidator currentValidatorChain;
private readonly License license;
public ValidationChainBuilder(License license)
{
this.license = license;
validators = new Queue();
}
public ILicenseValidator StartValidatorChain()
{
return currentValidatorChain = new LicenseValidator();
}
public void CompleteValidatorChain()
{
if (currentValidatorChain == null)
return;
validators.Enqueue(currentValidatorChain);
currentValidatorChain = null;
}
public ICompleteValidationChain When(Predicate predicate)
{
currentValidatorChain.ValidateWhen = predicate;
return this;
}
public IStartValidationChain And()
{
CompleteValidatorChain();
return this;
}
public IEnumerable AssertValidLicense()
{
CompleteValidatorChain();
while (validators.Count > 0)
{
var validator = validators.Dequeue();
if (validator.ValidateWhen != null && !validator.ValidateWhen(license))
continue;
if (!validator.Validate(license))
yield return validator.FailureResult
?? new GeneralValidationFailure
{
Message = "License validation failed!"
};
}
}
}
}
================================================
FILE: src/Portable.Licensing.Tests/KeyGeneratorTests.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using NUnit.Framework;
using Portable.Licensing.Security.Cryptography;
namespace Portable.Licensing.Tests
{
[TestFixture]
public class KeyGeneratorTests
{
[Test] // See Bug #135
public void Ensure_To_Not_Generate_Identical_Keys()
{
var passPhrase = "test";
var privKeySet = new HashSet();
var pubKeySet = new HashSet();
// add well known key
privKeySet.Add(
"MIICITAjBgoqhkiG9w0BDAEDMBUEEF5Fx1gxrWd+0G10a7+UbxQCAQoEggH4SUUim2C3kcHApCKVgIeXpKlZQHcaRgfWt0rVEWr8zRnzO9xT5itU2Sw7j0N3oh6cPer/QGNCmAgnRyiDatruJznDPOmMzK5Yskj6mlCaY6JEjcol+E4SBZJDgvIejy8HVCy+DOIR42JXs9oxgeq8eqB+0RZwvDMBG2hrUjnZ4/hPKRPJY134cqTH68jLv6SXglIPcrL9OxOwdzJBaq0ngSBfqhBWbLRIy/Th2btl9Q/0b+sZxG6r2b80wOxIewlr6EUqXtMaA8Bo5dgVZt1itWYafIAbLWzjZavwdO+EkUMCjZhsfvbXSCmcLRmitdJ6beG7jg7R6m6Q92DpU3qZhEio9akX3MQmOTO63Er4T2t6HHYnTzPaZPjdn8D+8lcTUntp/0vD8SvC3+Cb7tZOHSVGMUDdj7WIW+Bl/5bhdmnChE83HSxR4OsBjLATuZOpYtOefWbXyT8qsUn1IouaCjH+BYejBIPrmFVVl0WZADtbyE0LAOyHCD2quAjCpIwXXONG/gXm+XVGst5clbcuxaG4TxKWA8ifIXaio3aJgLfI+D0Izt2GscKRg6oGTlbC3YFIJg+PAH3A4qufoRSPmtREz0oR1X1ZsS6m/IKezf8vl3S+fSpmR/mUuc6uBx9qI9yJIEW/In90r5vO9fKGusEElP6svlub");
pubKeySet.Add(
"MIIBKjCB4wYHKoZIzj0CATCB1wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEIQNrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClgIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABNVLQ1xKY80BFMgGXec++Vw7n8vvNrq32PaHuBiYMm0PEj2JoB7qSSWhfgcjxNVJsxqJ6gDQVWgl0r7LH4dr0KU=");
for (int i = 0; i < 100; i++)
{
var keyGenerator = new KeyGenerator(256); //default key size
var pair = keyGenerator.GenerateKeyPair();
var privateKey = pair.ToEncryptedPrivateKeyString(passPhrase);
var publicKey = pair.ToPublicKeyString();
Assert.That(privKeySet.Add(privateKey), Is.True);
Assert.That(pubKeySet.Add(publicKey), Is.True);
}
privKeySet.Clear();
pubKeySet.Clear();
}
}
}
================================================
FILE: src/Portable.Licensing.Tests/LicenseSignatureTests.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml.Linq;
using NUnit.Framework;
namespace Portable.Licensing.Tests
{
[TestFixture]
public class LicenseSignatureTests
{
private string passPhrase;
private string privateKey;
private string publicKey;
[SetUp]
public void Init()
{
passPhrase = Guid.NewGuid().ToString();
var keyGenerator = Security.Cryptography.KeyGenerator.Create();
var keyPair = keyGenerator.GenerateKeyPair();
privateKey = keyPair.ToEncryptedPrivateKeyString(passPhrase);
publicKey = keyPair.ToPublicKeyString();
}
private static DateTime ConvertToRfc1123(DateTime dateTime)
{
return DateTime.ParseExact(
dateTime.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture)
, "r", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
[Test]
public void Can_Generate_And_Validate_Signature_With_Empty_License()
{
var license = License.New()
.CreateAndSignWithPrivateKey(privateKey, passPhrase);
Assert.That(license, Is.Not.Null);
Assert.That(license.Signature, Is.Not.Null);
// validate xml
var xmlElement = XElement.Parse(license.ToString(), LoadOptions.None);
Assert.That(xmlElement.HasElements, Is.True);
// validate default values when not set
Assert.That(license.Id, Is.EqualTo(Guid.Empty));
Assert.That(license.Type, Is.EqualTo(LicenseType.Trial));
Assert.That(license.Quantity, Is.EqualTo(0));
Assert.That(license.ProductFeatures, Is.Null);
Assert.That(license.Customer, Is.Null);
Assert.That(license.Expiration, Is.EqualTo(ConvertToRfc1123(DateTime.MaxValue)));
// verify signature
Assert.That(license.VerifySignature(publicKey), Is.True);
}
[Test]
public void Can_Generate_And_Validate_Signature_With_Standard_License()
{
var licenseId = Guid.NewGuid();
var customerName = "Max Mustermann";
var customerEmail = "max@mustermann.tld";
var expirationDate = DateTime.Now.AddYears(1);
var productFeatures = new Dictionary
{
{"Sales Module", "yes"},
{"Purchase Module", "yes"},
{"Maximum Transactions", "10000"}
};
var license = License.New()
.WithUniqueIdentifier(licenseId)
.As(LicenseType.Standard)
.WithMaximumUtilization(10)
.WithProductFeatures(productFeatures)
.LicensedTo(customerName, customerEmail)
.ExpiresAt(expirationDate)
.CreateAndSignWithPrivateKey(privateKey, passPhrase);
Assert.That(license, Is.Not.Null);
Assert.That(license.Signature, Is.Not.Null);
// validate xml
var xmlElement = XElement.Parse(license.ToString(), LoadOptions.None);
Assert.That(xmlElement.HasElements, Is.True);
// validate default values when not set
Assert.That(license.Id, Is.EqualTo(licenseId));
Assert.That(license.Type, Is.EqualTo(LicenseType.Standard));
Assert.That(license.Quantity, Is.EqualTo(10));
Assert.That(license.ProductFeatures, Is.Not.Null);
Assert.That(license.ProductFeatures.GetAll(), Is.EquivalentTo(productFeatures));
Assert.That(license.Customer, Is.Not.Null);
Assert.That(license.Customer.Name, Is.EqualTo(customerName));
Assert.That(license.Customer.Email, Is.EqualTo(customerEmail));
Assert.That(license.Expiration, Is.EqualTo(ConvertToRfc1123(expirationDate)));
// verify signature
Assert.That(license.VerifySignature(publicKey), Is.True);
}
[Test]
public void Can_Detect_Hacked_License()
{
var licenseId = Guid.NewGuid();
var customerName = "Max Mustermann";
var customerEmail = "max@mustermann.tld";
var expirationDate = DateTime.Now.AddYears(1);
var productFeatures = new Dictionary
{
{"Sales Module", "yes"},
{"Purchase Module", "yes"},
{"Maximum Transactions", "10000"}
};
var license = License.New()
.WithUniqueIdentifier(licenseId)
.As(LicenseType.Standard)
.WithMaximumUtilization(10)
.WithProductFeatures(productFeatures)
.LicensedTo(customerName, customerEmail)
.ExpiresAt(expirationDate)
.CreateAndSignWithPrivateKey(privateKey, passPhrase);
Assert.That(license, Is.Not.Null);
Assert.That(license.Signature, Is.Not.Null);
// verify signature
Assert.That(license.VerifySignature(publicKey), Is.True);
// validate xml
var xmlElement = XElement.Parse(license.ToString(), LoadOptions.None);
Assert.That(xmlElement.HasElements, Is.True);
// manipulate xml
Assert.That(xmlElement.Element("Quantity"), Is.Not.Null);
xmlElement.Element("Quantity").Value = "11"; // now we want to have 11 licenses
// load license from manipulated xml
var hackedLicense = License.Load(xmlElement.ToString());
// validate default values when not set
Assert.That(hackedLicense.Id, Is.EqualTo(licenseId));
Assert.That(hackedLicense.Type, Is.EqualTo(LicenseType.Standard));
Assert.That(hackedLicense.Quantity, Is.EqualTo(11)); // now with 10+1 licenses
Assert.That(hackedLicense.ProductFeatures, Is.Not.Null);
Assert.That(hackedLicense.ProductFeatures.GetAll(), Is.EquivalentTo(productFeatures));
Assert.That(hackedLicense.Customer, Is.Not.Null);
Assert.That(hackedLicense.Customer.Name, Is.EqualTo(customerName));
Assert.That(hackedLicense.Customer.Email, Is.EqualTo(customerEmail));
Assert.That(hackedLicense.Expiration, Is.EqualTo(ConvertToRfc1123(expirationDate)));
// verify signature
Assert.That(hackedLicense.VerifySignature(publicKey), Is.False);
}
}
}
================================================
FILE: src/Portable.Licensing.Tests/LicenseValidationTests.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Portable.Licensing.Validation;
namespace Portable.Licensing.Tests
{
[TestFixture]
public class LicenseValidationTests
{
[Test]
public void Can_Validate_Valid_Signature()
{
var publicKey =
@"MIIBKjCB4wYHKoZIzj0CATCB1wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEIQNrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClgIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABNVLQ1xKY80BFMgGXec++Vw7n8vvNrq32PaHuBiYMm0PEj2JoB7qSSWhfgcjxNVJsxqJ6gDQVWgl0r7LH4dr0KU=";
var licenseData = @"
77d4c193-6088-4c64-9663-ed7398ae8c1a
Trial
Sun, 31 Dec 1899 23:00:00 GMT
1
John Doe
john@doe.tld
MEUCIQCCEDAldOZHHIKvYZRDdzUP4V51y23d6deeK5jIFy27GQIgDz2CndjBh4Vb8tiC3FGQ6fn3GKt8d/P5+luJH0cWv+I=
";
var license = License.Load(licenseData);
var validationResults = license
.Validate()
.Signature(publicKey)
.AssertValidLicense();
Assert.That(validationResults, Is.Not.Null);
Assert.That(validationResults.Count(), Is.EqualTo(0));
}
[Test]
public void Can_Validate_Invalid_Signature()
{
var publicKey =
@"MIIBKjCB4wYHKoZIzj0CATCB1wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEIQNrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClgIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABNVLQ1xKY80BFMgGXec++Vw7n8vvNrq32PaHuBiYMm0PEj2JoB7qSSWhfgcjxNVJsxqJ6gDQVWgl0r7LH4dr0KU=";
var licenseData = @"
77d4c193-6088-4c64-9663-ed7398ae8c1a
Trial
Sun, 31 Dec 1899 23:00:00 GMT
999
John Doe
john@doe.tld
MEUCIQCCEDAldOZHHIKvYZRDdzUP4V51y23d6deeK5jIFy27GQIgDz2CndjBh4Vb8tiC3FGQ6fn3GKt8d/P5+luJH0cWv+I=
";
var license = License.Load(licenseData);
var validationResults = license
.Validate()
.Signature(publicKey)
.AssertValidLicense().ToList();
Assert.That(validationResults, Is.Not.Null);
Assert.That(validationResults.Count(), Is.EqualTo(1));
Assert.That(validationResults.FirstOrDefault(), Is.TypeOf());
}
[Test]
public void Can_Validate_Expired_ExpirationDate()
{
var publicKey = "";
var licenseData = @"
77d4c193-6088-4c64-9663-ed7398ae8c1a
Trial
Sun, 31 Dec 1899 23:00:00 GMT
1
John Doe
john@doe.tld
MEUCIQCCEDAldOZHHIKvYZRDdzUP4V51y23d6deeK5jIFy27GQIgDz2CndjBh4Vb8tiC3FGQ6fn3GKt8d/P5+luJH0cWv+I=
";
var license = License.Load(licenseData);
var validationResults = license
.Validate()
.ExpirationDate()
.AssertValidLicense().ToList();
Assert.That(validationResults, Is.Not.Null);
Assert.That(validationResults.Count(), Is.EqualTo(1));
Assert.That(validationResults.FirstOrDefault(), Is.TypeOf());
}
[Test]
public void Can_Validate_CustomAssertion()
{
var publicKey = @"MIIBKjCB4wYHKoZIzj0CATCB1wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEIQNrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClgIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABNVLQ1xKY80BFMgGXec++Vw7n8vvNrq32PaHuBiYMm0PEj2JoB7qSSWhfgcjxNVJsxqJ6gDQVWgl0r7LH4dr0KU=";
var licenseData = @"
77d4c193-6088-4c64-9663-ed7398ae8c1a
Trial
Thu, 31 Dec 2009 23:00:00 GMT
1
John Doe
john@doe.tld
123456789
yes
yes
10000
MEUCIQCa6A7Cts5ex4rGHAPxiXpy+2ocZzTDSP7SsddopKUx5QIgHnqv0DjoOpc+K9wALqajxxvmLCRJAywCX5vDAjmWqr8=
";
var license = License.Load(licenseData);
var validationResults = license
.Validate()
.AssertThat(lic => lic.ProductFeatures.Contains("Sales Module"),
new GeneralValidationFailure {Message = "Sales Module not licensed!"})
.And()
.AssertThat(lic => lic.AdditionalAttributes.Get("Assembly Signature") == "123456789",
new GeneralValidationFailure {Message = "Assembly Signature does not match!"})
.And()
.Signature(publicKey)
.AssertValidLicense().ToList();
Assert.That(validationResults, Is.Not.Null);
Assert.That(validationResults.Count(), Is.EqualTo(0));
}
[Test]
public void Do_Not_Crash_On_Invalid_Data()
{
var publicKey = "1234";
var licenseData =
@"John Doe ";
var license = License.Load(licenseData);
var validationResults = license
.Validate()
.ExpirationDate()
.And()
.Signature(publicKey)
.AssertValidLicense().ToList();
Assert.That(validationResults, Is.Not.Null);
Assert.That(validationResults.Count(), Is.EqualTo(1));
Assert.That(validationResults.FirstOrDefault(), Is.TypeOf());
}
}
}
================================================
FILE: src/Portable.Licensing.Tests/Portable.Licensing.Tests.csproj
================================================
Debug
AnyCPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}
Library
Properties
Portable.Licensing.Tests
Portable.Licensing.Tests
v4.5
512
..\
true
full
false
..\..\Build\
DEBUG;TRACE
prompt
4
pdbonly
true
..\..\Build\
TRACE
prompt
4
Properties\CommonAssemblyInfo.cs
{6d2b800c-c252-4a33-ba05-904ae5b79417}
Portable.Licensing
..\..\packages\NUnit\lib\nunit.framework.dll
True
True
================================================
FILE: src/Portable.Licensing.Tests/Properties/AssemblyInfo.cs
================================================
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Portable.Licensing.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ecb19417-e47a-43ec-b573-063931631cd3")]
================================================
FILE: src/Portable.Licensing.Tests/paket.references
================================================
NUnit
================================================
FILE: src/Portable.Licensing.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{476022A4-7C0A-4FC7-830E-ED32D3F82B13}"
ProjectSection(SolutionItems) = preProject
..\paket.dependencies = ..\paket.dependencies
..\paket.lock = ..\paket.lock
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{449E5271-6EE5-49BA-AB0E-370978ACD89C}"
ProjectSection(SolutionItems) = preProject
..\build.fsx = ..\build.fsx
..\LICENSE.md = ..\LICENSE.md
..\Portable.Licensing.nuspec = ..\Portable.Licensing.nuspec
..\README.md = ..\README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xamarin", "Xamarin", "{BB17039C-1F40-476D-8F75-DA11576E4168}"
ProjectSection(SolutionItems) = preProject
..\Xamarin\Details.md = ..\Xamarin\Details.md
..\Xamarin\GettingStarted.md = ..\Xamarin\GettingStarted.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Portable.Licensing", "Portable.Licensing\Portable.Licensing.csproj", "{6D2B800C-C252-4A33-BA05-904AE5B79417}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Portable.Licensing.Tests", "Portable.Licensing.Tests\Portable.Licensing.Tests.csproj", "{16CEEFD4-62BF-4539-9A08-0D05EC695572}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Ad-Hoc|iPhone = Ad-Hoc|iPhone
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
Ad-Hoc|Mixed Platforms = Ad-Hoc|Mixed Platforms
AppStore|Any CPU = AppStore|Any CPU
AppStore|iPhone = AppStore|iPhone
AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
AppStore|Mixed Platforms = AppStore|Mixed Platforms
Debug|Any CPU = Debug|Any CPU
Debug|iPhone = Debug|iPhone
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Debug|Mixed Platforms = Debug|Mixed Platforms
Release|Any CPU = Release|Any CPU
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
Release|Mixed Platforms = Release|Mixed Platforms
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Ad-Hoc|Mixed Platforms.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Ad-Hoc|Mixed Platforms.Build.0 = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.AppStore|Mixed Platforms.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.AppStore|Mixed Platforms.Build.0 = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Debug|Any CPU.Build.0 = Release|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Release|Any CPU.Build.0 = Release|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Release|iPhone.ActiveCfg = Release|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{6D2B800C-C252-4A33-BA05-904AE5B79417}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Ad-Hoc|Mixed Platforms.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Ad-Hoc|Mixed Platforms.Build.0 = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.AppStore|Mixed Platforms.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.AppStore|Mixed Platforms.Build.0 = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Debug|Any CPU.Build.0 = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Release|Any CPU.Build.0 = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Release|iPhone.ActiveCfg = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{16CEEFD4-62BF-4539-9A08-0D05EC695572}.Release|Mixed Platforms.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BB17039C-1F40-476D-8F75-DA11576E4168} = {449E5271-6EE5-49BA-AB0E-370978ACD89C}
EndGlobalSection
EndGlobal
================================================
FILE: src/Portable.Licensing.sln.DotSettings
================================================
<data><IncludeFilters /><ExcludeFilters /></data>
<data />