外部暗号化ファイルとしての機能
プレミアム機能を、アプリケーションの外部に置いた暗号化コードとして配布します。この機能のロックは、それを付与するライセンスを顧客が持っている場合にのみ解除されます。
Babel Obfuscator は、暗号化したメソッド本体をアセンブリに埋め込む代わりに、.eil 拡張子を持つ別のバイナリファイルに切り出すことができます(外部コードファイルを参照)。このファイルは単独で配布できます。たとえば、顧客がアップグレードした時点で、ライセンスと一緒に提供できます。このサンプルは、この 2 つを組み合わせたものです。プレミアムコードは外部の .eil ファイルであり、実行するには、そのファイルと、機能を付与する有効な Babel ライセンスの両方が必要です。
コード例
git clone https://github.com/babelfornet/external-encrypted-code-console-example.gitReportTool は、無料の Standard レポートと Premium 分析を備えたコンソールアプリケーションです。Premium のコードは premium.eil に暗号化され、LicenseGenerator は Standard または Premium のライセンスを発行します。
外部暗号化
プレミアムメソッドは source を設定しますが、internal は設定しません。そのため、Babel は暗号化した本体を外部の premium.eil ファイルに書き出します。
[Obfuscation(Feature = "msil encryption:source=premium;password=Pr3m!um-R3port-K3y", Exclude = false)]
public static string Analyze(int[] data)
{
double mean = data.Average();
double variance = data.Select(x => (x - mean) * (x - mean)).Sum() / data.Length;
return $"Premium analysis: mean={mean:0.00}, variance={variance:0.00}, stddev={Math.Sqrt(variance):0.00}";
}Babel は、premium.eil を中間アセンブリと同じ場所に出力します。短い MSBuild ターゲットがこのファイルを出力フォルダーにコピーするので、アプリケーションと一緒に配布することも、意図的に配布しないこともできます。
<Target Name="CopyBabelExternalFiles" AfterTargets="Build">
<ItemGroup>
<BabelEilFiles Include="$(IntermediateOutputPath)*.eil" />
</ItemGroup>
<Copy SourceFiles="@(BabelEilFiles)" DestinationFolder="$(OutDir)"
SkipUnchangedFiles="false" Condition="'@(BabelEilFiles)' != ''" />
</Target>ライセンスで制御する 2 つのフック
外部コードの場合、BVM は 2 つのフックを呼び出します。1 つは暗号化されたストリームを取得するためのもので、もう 1 つはパスワードを取得するためのものです。このサンプルでは、両方のフックが有効なライセンスを条件としているため、ファイルだけでも、ライセンスだけでも不十分です。
// Returns the .eil stream only when a valid license grants the feature.
[Obfuscation(Feature = "msil encryption get stream")]
internal static Stream? GetSourceStream(string source)
{
if (!HasFeature(source))
return null; // Not licensed for this feature.
var path = Path.Combine(FeaturesDirectory, source + ".eil");
return File.Exists(path) ? File.OpenRead(path) : null; // Feature file not delivered.
}
// Returns the password carried by the license.
[Obfuscation(Feature = "msil encryption get password")]
internal static string GetSourcePassword(string source)
{
var license = Validate();
var field = license.Fields.FirstOrDefault(f => f.Name == source)
?? throw new InvalidOperationException($"License does not grant source '{source}'.");
return field.Value.Decrypt(Secrets.FieldSecret);
}HasFeature は、検証済みのライセンスに機能名のフィールドが含まれている場合にのみ true を返します。このフィールドは、ジェネレーターが Premium ライセンスに追加します。
if (premium)
{
string encrypted = Secrets.PremiumPassword.Encrypt(Secrets.FieldSecret);
builder = builder.WithField(Secrets.PremiumSource, encrypted);
}実行
# Build in Release — Babel encrypts Premium.Analyze into premium.eil.
dotnet build src/ReportTool/ReportTool.csproj -c Release
# Mint a Premium license (add --standard for a Standard one).
dotnet run --project src/LicenseGenerator
# Deliver BOTH the license and the external code, then run.
cp ReportTool.lic src/ReportTool/bin/Release/net8.0/
dotnet src/ReportTool/bin/Release/net8.0/ReportTool.dll4 つの組み合わせを見ると、2 つの要素による制御がわかります。
| ライセンス | premium.eil の配布 | 結果 |
|---|---|---|
| Standard | なし | Premium はブロックされる |
| Premium | なし | Premium はブロックされる(機能が配布されていない) |
| Standard | あり | Premium はブロックされる(ライセンスがない) |
| Premium | あり | Premium 分析が実行される |
いずれかの要素が欠けている場合、BVM は no code source premium stream を報告し、Standard レポートは単独で引き続き動作します。
保護されたコードを別のファイルとして提供する方法は、機能ベースのライセンスやアドオンのライセンスによく合います。基本のアプリケーションは 1 回のダウンロードで提供し、有料の機能はそれぞれ、そのロックを解除するライセンスと一緒に配布する小さな .eil ファイルになります。ベンダーは、機能を付与するライセンスを更新しないだけで、その機能を失効させられます。
サンプルの keys.pem とパスワードは、デモ専用です。本番環境では、ライセンスはベンダーまたは Babel Licensing Service が発行し、RSA 秘密キーはオフラインで保管します。