トライアルシリアルライセンス
この記事では、トライアルシリアルライセンスの考え方を取り上げ、サンプルのコンソールアプリケーションを使ってその実装を示します。提供するコードは、一定の日数が経過すると期限が切れ、実行回数も制限するトライアルライセンスの作成方法を示します。さらに、ライセンスが有効な場合にのみ実行される機密性の高いコードを、暗号化の手法で保護する方法も示します。トライアルシリアルライセンスのモデルを理解し、付属のコードを確認することで、開発者は、Babel Licensing を活用してソフトウェア製品のトライアル版を実装する方法を把握できます。
コード例
TrialLicense プロジェクトのコードを入手して詳しく調べるには、次のコマンドで GitHub からリポジトリをクローンします。
git clone https://github.com/babelfornet/trial-license-string-console-example.gitTrialLicense プロジェクトは、コンソールアプリケーションで Babel Licensing を使ってトライアルライセンスの仕組みを実装する方法を示します。このサンプルプロジェクトは、Windows、Linux、macOS に対応しています。リポジトリをクローンすると完全なソースコードを入手でき、実装の詳細、各コンポーネント、トライアルライセンスの仕組みの機能を確認できます。
このプロジェクトは、Babel Obfuscator の NuGet パッケージを利用して、ビルド時にコードを難読化および暗号化します。
Babel Obfuscator をアクティベートするには、環境変数 BABEL_LICENSE に、ライセンスファイルのパス、またはフローティングライセンスキーを設定します。
暗号化されたコードは、復号用のパスワードを含む有効なシリアル番号がある場合にのみ実行できます。

トライアルライセンスのサンプル
アプリケーションを起動するには、シェルのウィンドウを開き、プロジェクトの Debug フォルダーに移動して、TrialLicense コマンドを入力し、ENTER を押します。これでアプリケーションが実行されます。
トライアルライセンスの生成
次のコードは、トライアルライセンスのシリアル番号を生成します。
string hardwareKey = HardwareId.Create().ToMachineKey();
var sign = (RSASignature)Pem.ReadSignature("Keys.pem");
var lic = new StringLicense() // Create a new string license
.ForAssembly(Assembly.GetExecutingAssembly()) // The license is for this assembly
.WithUniqueId() // Unique ID for the license
.WithHardwareKey(hardwareKey) // Lock to the current machine
.WithTrialDays(2) // Give 2 days trial
.WithMaximumRunCount(3) // Allow 3 runs
.WithField("source1", "p@ssw0rd1".Encrypt("!sEcr3tp@sswOrD!")) // Set the encrypted code password
.SignWith(sign); // Sign the license with the private key
// Convert the license object to an ASCII string
string serial = lic.ToReadableString("ASCII");このコードの動作を順に説明します。
HardwareId.Create().ToMachineKey()は、現在のコンピューターを一意に識別する、ハードウェア固有のキーを生成します。このキーは、トライアルライセンスを現在のコンピューターに紐付けるために使用されます。(RSASignature)Pem.ReadSignature("Keys.pem")は、「Keys.pem」ファイルから RSA 秘密キーを読み取ります。このキーは、ライセンスに署名し、その真正性を検証するために使用されます。new StringLicense()は、トライアルライセンスを表すStringLicenseクラスの新しいインスタンスを作成します。.ForAssembly(Assembly.GetExecutingAssembly())は、ライセンスが現在のアセンブリに関連付けられることを指定します。.WithUniqueId()は、ライセンスの一意の識別子を生成します。.WithHardwareKey(hardwareKey)は、手順 1 で生成したハードウェアキーに関連付けることで、ライセンスを現在のコンピューターに紐付けます。.WithTrialDays(2)は、トライアル期間を 2 日に設定します。この期間が過ぎると、ライセンスの期限が切れます。.WithMaximumRunCount(3)は、トライアル版で許可される最大実行回数を設定します。.WithField("source1", "p@ssw0rd1".Encrypt("!sEcr3tp@sswOrD!"))は、「source1」という名前のフィールドをライセンスに追加し、その値に暗号化されたパスワードを設定します。このパスワードは、ライセンスが有効な場合に、特定のコードを復号して実行するために使用されます。.SignWith(sign)は、手順 2 で取得した RSA 秘密キーでライセンスに署名し、その整合性と真正性を保証します。lic.ToReadableString("ASCII")は、ライセンスオブジェクトを ASCII 文字列の表現に変換します。- 生成されたライセンスのシリアル番号は、検証に使用する公開キーとともにレジストリに保存されます。
このコードは、暗号化による保護とレジストリへの保存を含め、トライアルライセンスのシリアル番号を生成する手順を示しています。トライアルライセンスは、対応する公開キーを使って検証でき、これによって真正性を確認し、トライアル期間や実行回数の上限などのトライアル制限を適用できます。
トライアルライセンスの検証
次のコードスニペットは、この手順の実際の実装を示しています。Babel Licensing を利用して、トライアルのシリアル番号を検証します。
var store = new LicenseStore();
store.Load();
if (store.Serial == null)
{
Console.WriteLine("No serial found");
return;
}
// Get the public key from the key to validate the license signature
string publicKey = Convert.ToString(store.Key).Decrypt("pk_p@sswOrd");
var manager = new StringLicenseManager();
// The public key is used to validate the license signature
manager.SignatureProvider = RSASignature.FromKeys(publicKey);
// Validate the serial
// A license object is returned if the serial is valid and all license restrictions are met
Babel.Licensing.ILicense license = manager.Validate(store.Serial);
Console.WriteLine("Serial {0} is valid", license.Id);
var trial = license.Restrictions.OfType<TrialRestriction>().FirstOrDefault();
if (trial != null)
{
Console.WriteLine("Trial time left: {0}", trial.TimeLeft);
Console.WriteLine("Runs left: {0}", trial.RunCountLeft);
}ここでは、ライセンスの署名の検証に使用する公開キーを、ライセンスファイルの情報から取得します。「Key」キーに関連付けられた値を取得し、復号用のパスワード「pk_p@sswOrd」を使って、保存されている値を復号します。
ライセンスの検証を管理するために、StringLicenseManager クラスのインスタンスを作成します。このマネージャーの SignatureProvider プロパティには、取得した公開キーから作成した RSASignature オブジェクトを設定します。これにより、マネージャーはライセンスの署名の検証に公開キーを使用するようになります。
Babel.Licensing.ILicense license = manager.Validate(serial);ライセンスを検証するために、manager.Validate(serial) メソッドを呼び出します。引数には、serial 変数に格納されているライセンスのシリアル番号を渡します。シリアル番号が有効で、ライセンスの制限をすべて満たしている場合、Babel.Licensing.ILicense インターフェイスを実装するライセンスオブジェクトが返されます。これは、検証済みのライセンスを表します。
最後に、トライアルの残り時間と残りの実行回数をコンソールに出力します。
まとめると、このコードは、レジストリからシリアル番号と公開キーを取得し、公開キーでライセンスマネージャーを設定して、検証メソッドを呼び出すことで、ライセンスのシリアル番号を検証します。その後、検証結果と、該当する場合はトライアルの残り時間や実行回数などのライセンス情報を表示します。
暗号化されたコードの実行
次のコードは、暗号化されたコードの実行と、Babel Obfuscator を使ってそのコードを取得する方法を示しています。このコードの動作を見ていきます。
まず、2 つのメソッドが関係しています。
[Obfuscation(Feature = "msil encryption get password", Exclude = false)]
internal static string GetEncryptedCodePassword(string source)
{
return EncryptedGetEncryptedCodePassword(source);
}
[Obfuscation(Feature = "msil encryption", Exclude = false)]
private static string EncryptedGetEncryptedCodePassword(string source)
{
var store = new LicenseStore();
store.Load();
if (store.Serial == null)
{
throw new Exception("No serial found");
}
// Get the public key from the key to validate the license signature
string publicKey = Convert.ToString(store.Key).Decrypt("pk_p@sswOrd");
var manager = new StringLicenseManager();
// The public key is used to validate the license signature
manager.SignatureProvider = RSASignature.FromKeys(publicKey);
// Validate the serial
// A license object is returned if the serial is valid and all license restrictions are met
Babel.Licensing.ILicense license = manager.Validate(store.Serial);
// Reuse the same secret used to decrypt the code password
return license.Fields.First(item => item.Name == source).Value.Decrypt("!sEcr3tp@sswOrD!");
}GetEncryptedCodePassword メソッドは、暗号化されたコードのパスワードを取得するためのエントリポイントです。このメソッドは、ソースの値をパラメーターとして渡して、EncryptedGetEncryptedCodePassword メソッドを呼び出します。このメソッドの目的は、指定されたソースに関連付けられた、暗号化されたコードのパスワードをライセンスから取り出すことです。パスワードで保護されたコードの詳細については、Babel Obfuscator のコード暗号化を参照してください。
EncryptedGetEncryptedCodePassword の内部では、次の処理が行われます。
- ライセンスファイルから、ライセンスのシリアル番号と対応する公開キーを取得します。
- パスワード「pk_p@sswOrd」を使って公開キーを復号します。
- 復号した公開キーでライセンスを検証するために、
StringLicenseManagerのインスタンスを作成します。 - マネージャーの
Validateメソッドにシリアル番号を渡して、ライセンスを検証します。 - シリアル番号が有効で、ライセンスの制限をすべて満たしている場合、ライセンスオブジェクトが返されます。
- 指定されたソースに関連付けられた、暗号化されたコードのパスワードを、ライセンスのフィールドから取得します。
- 最後に、シークレット「!sEcr3tp@sswOrD!」を使って暗号化されたパスワードを復号し、返します。
さらに、Babel Obfuscator を使ってコードを難読化および暗号化します。使用する難読化機能は次のとおりです。
ExecuteEncryptedCodeメソッドの場合:
[Obfuscation(Feature = "msil encryption:source=source1;password=p@ssw0rd1;internal=true", Exclude = false)]
private void ExecuteEncryptedCode()
{
Console.WriteLine("Encrypted code running");
}msil encryption 機能が、指定したソース(「source1」)、暗号化パスワード(「p@ssw0rd1」)、および true に設定した internal で適用されます。この難読化により、このメソッド内のコードが暗号化され、保護されます。
これらの要素を組み合わせることで、Babel Obfuscator を使って、暗号化されたコードのパスワードをライセンスから取得できます。検証済みのパスワードによって、ExecuteEncryptedCode メソッド内の暗号化されたコードを復号して実行できるようになり、機密性の高いコード部分に対して、安全で制御された実行環境が提供されます。