チュートリアル:オンライン登録でプラグインをアンロックする
認証されるまでアクセスをロックすることで、アプリやプラグインのセキュリティを向上させます。オンラインキー登録を通じてプラグインをアンロックするメカニズムをユーザーに提供する方法を学びます。
レベル: 上級
プラットフォーム: Windows, macOS, Linux
クラス: OnlineUnlockStatus, OnlineUnlockForm, KeyGeneration, RSAKey, TracktionMarketplaceStatus
このチュートリアルは、RSA暗号、証明書、ネットワークプロトコル、PHPの構文に関する初歩的な知識を前提としています。
はじめに
このチュートリアルのデモプロジェクトをこちらからダウンロードしてください:PIP | ZIP。プロジェクトを解凍し、最初のヘッダファイルをProjucerで開いてください。
この手順についてサポートが必要な場合は、チュートリアル:Projucer Part 1: Projucerを始めようを参照してください。
デモプロジェクト
デモプロジェクトは、2つのボタンを持つ非常にシンプルなUIを表示します。そのうちの1つは、登録を通じてもう1つへのアクセスをアンロックするために使用されます。「Unlock」ボタンが押されると、ユーザーが資格情報を入力するための登録フォームが開きます。現時点では、バックエンドサーバーの実装を開始するまで、登録プロセスは失敗します。

このチュートリアルの終わりに実装と認証が成功すると、以下のようなアプリのアンロック状態が表示されるはずです。

導入
プラグインメーカーとして、プラグインがハッカーにクラックされたり、同意なしに無料で配布されたりすることは時としてフラストレーションを感じることがあります。そのような脅威に対してアプリケーションを完全に防御することは難しい場合がありますが、ハッカーにとってこのプロセスをより面倒にする手段はあります。場合によっては、ユーザーが製品を購入する前に試用できる試用期間を提供したり、無料ティアユーザーに対して特定の機能を制限したりすることもあります。
メーカーによって、プラグインのセキュリティを向上させるために異なる方法が使用されます:一部はライセンスを持ち運ぶための物理的なUSBスティックを必要とするPACEのiLokなどのサードパーティのライセンスソリューションを使用したり、リモートWebサーバー上のデータベースに対して資格情報をチェックしてユーザーを認証する独自のシステムを使用したりします。
このチュートリアルでは、Webサーバー認証を介してプラグインを登録する2番目の方法を見ていきます。この方法の利点は、オンラインでもオフラインでも機能し、登録に物理的なデバイスを必要としないことです。ただし、プラグインは一定期間マシンに登録されるため、この技術はプラグインが起動するたびに認証を必要とするPACEのソリューションに比べてハッキングに対してより脆弱です。
では、サーバー認証はどのように機能するのでしょうか?マシンがインターネットに接続されている場合、オンライン認証と呼ばれるものを実行でき、プラグインは安全な接続を通じてユーザーの資格情報を送信し、サーバーにライセンスキーをプローブします。ユーザーが製品を購入したことが確認された場合、サーバーはマシンにキーファイルを送り返し、プラグインをアンロックできます。一方、マシンがオフラインの場合、ユーザーはインターネットに接続された別のコンピュータを介してWebサーバーからキーファイルをダウンロードでき、そのキーファイルをオフラインマシンにコピーしてプラグインにロードすることで適用できます。
RSA暗号化
では、暗号について少し話しましょう。2つの当事者間の送信中に情報が改ざんされないことをどのように保証するのでしょうか?これを保証するためにRSAと呼ばれる広く使用されている安全な暗号化アルゴリズムを使用します。RSAは、素数を使用してペアのキーが作成され、そのうちの1つが公開で、もう1つが非公開であることに基づいて機能します。公開キーは公開で共有でき、メッセージを暗号化するために使用されます。秘密キーは受信者によって非公開に保持され、メッセージを復号化するために使用されます。
RSAの設計方法により、一致するペアの対応する公開キーで暗号化されたメッセージを復号化できるのは秘密キーの所有者だけです。このシナリオは、Bobが公開キーを知っており、Aliceが秘密キーを所有し、Eveがメッセージを傍受しようとする第三者である以下の図で説明できます:
上記の場合、Eveはメッセージを復号化する秘密キーを持っていないため、Bobからのメッセージを読むことができません。彼女は公開キーを使用してAliceに暗号化されたメッセージを送信できますが、これはBobのメッセージを傍受したいEveには役に立ちません。これは通常、ある当事者が秘密のメッセージを送信したいRSAの最も一般的なユースケースですが、これはプラグイン登録プロセスでRSAが使用される方法ではありません。
プラグイン認証に使用されるRSAの代替シナリオがあり、秘密キーがメッセージを暗号化するために使用され、公開キーがそれを復号化するために使用されます。これは、Bobがプラグインがインストールされているマシン、Aliceが登録用の認証Webサーバー、Eveがプラグインにハッキングしようとする第三者である以下の図で説明できます:
この場合、公開キーを持つ誰でも(BobとEveを含む)、Aliceの秘密キーで暗号化されたメッセージを復号化できます。ただし、Eveが一致するペアの対応する秘密キーなしでBobに暗号化されたメッセージを送信しようとした場合、Bobは公開キーで復号化することでメッセージの真正性を確認できます。その後、データにゴミが含まれるため、結果が確かに有効であることを確認でき、したがってEveはAliceになりすますことができません。
同様に、サーバーが資格情報がデータベースに対して正しい場合にのみ応答を送信することを条件として、サーバーから送信されたメッセージが有効かどうかを確認するだけでプラグイン認証を実行できます。幸いなことに、この暗号化と復号化の手順はすべて、KeyGenerationやRSAKeyなどのクラスによってJUCEライブラリで処理されます。
RSA暗号化がどのように機能するかを理解したので、デモプロジェクトに登録メカニズムを実装し始めましょう。
マーケットプレイスステータスの実装
マシン上のアプリケーションを使用するクライアントとアプリケーションを認証する登録サーバー間の通信を容易にするために、JUCEライブラリはOnlineUnlockStatusクラスと呼ばれるインターフェースとして機能する基本クラスを提供します。このクラスは、アプリケーションがインストールされている現在のマシンの登録ステータスを管理するための基盤を提供します。
ストア固有のマーケットプレイスを実装するための最初のステップは、OnlineUnlockStatusクラスから継承することであり、このサブクラスを実装する方法の例はTracktionMarketplaceStatusクラスで説明されています。この実装はTracktionマーケットプレイス用に特別に設計されているため、独自の独立したサブクラスを作成する必要がありますが、サーバーからの応答を処理するコードは同一のままにできるため借用します。
まず、OnlineUnlockStatusクラスから派生するTutorialMarketplaceStatusクラスの実装を見てみましょう。readReplyFromWebserver()とuserCancelled()関数は、簡単のためにTracktionMarketplaceStatus実装からコピーされていることに注意してください。
基本クラスからの残りの仮想関数を埋めて、独自のマーケットプレイス実装を完成させる必要があります。
getProductID()関数にアプリケーションの製品IDを挿入し、このIDが後でサーバー上の製品IDと一致することを確認してください:
juce::String getProductID() override
{
return "TestApp";
}
次のdoesProductIDMatch()関数は、サーバーから送信されたIDが前のステップで挿入された製品IDと一致するかどうかを確認する必要があります:
bool doesProductIDMatch (const juce::String& returnedIDFromServer) override
{
return getProductID() == returnedIDFromServer;
}
次に、getWebsiteName()関数にウェブサイトの名前を挿入します。この情報は、サーバーに連絡するときにユーザーにドメイン名を表示するためにのみ使用されます。
juce::String getWebsiteName() override
{
return "juce.com";
}
次の関数は重要です。これはアプリの認証を試みるときに連絡されるアドレスであり、マーケットプレイスサーバーを指す必要があります。このチュートリアルの目的のために、テストサーバーはマシン上でローカルに実行されるため、「localhost」または「127.0.0.1」IPアドレスを指します。サーバーは簡単のためにPHP言語を使用するため、ポイントするページはPHP拡張子で終わります。
juce::URL getServerAuthenticationURL() override
{
return juce::URL ("https://localhost:8443/auth.php");
}
認証プロセスは安全な接続でのみ機能するため、サーバーとの通信に使用されるプロトコルはHTTPSである必要があることに注意してください。8443ポートはこの選択を反映し、デフォルトのSSLポートを示します。
登録プロセスが開始されると、クライアントアプリはユーザーが提供した資格情報で認証を要求し、サーバーは暗号化されたメッセージで応答します。アプリをアンロックするためのキーファイルを含むこのメッセージは、サーバー側でメッセージを暗号化するために使用された秘密RSAキーに対応する公開RSAキーを使用してのみ復号化できます。
getPublicKey()関数はこの公開キーを返す必要があり、このチュートリアルのキー生成ステップで後で入力されます。以下のように関数を準備し、フィールドは今のところ空白のままにしておきます:
juce::RSAKey getPublicKey() override
{
return juce::RSAKey ("INSERT_PUBLIC_KEY_HERE");
}
TutorialMarketplaceStatusクラスは、マーケットプレイスサーバーと通信してキーを取得するために必要なすべての情報を持っています。
登録フォームの提供
ユーザーがアプリやプラグインで入力するための登録フォームを表示するにはいくつかの方法があります。インターフェースの上に通常のComponentをオーバーレイするか、メインウィンドウの上にDialogWindowをポップアップさせることができます。後者のオプションは、プラグインを開発する際には非常に推奨されません。これにより、プラグインを検証する際の単純なスキャンルーチンがフリーズする可能性があり、登録ウィンドウがまだアクティブな状態でDAWがプラグインをシャットダウンした場合にも問題を引き起こす可能性があります。
したがって、このセクションでは、アプリとプラグインの両方との互換性を確保するために前者のオプションを選択します。登録ユーザーインターフェースの実装プロセスを簡素化するために、JUCEライブラリはOnlineUnlockFormクラスを提供しており、メールとパスワード用の2つのフィールドを表示し、OnlineUnlockStatusクラスと組み合わせて登録のためのシームレスな実装を提供します。
TutorialUnlockFormという名前のクラスを作成し、OnlineUnlockFormから以下のように派生します:
class TutorialUnlockForm : public juce::OnlineUnlockForm
{
public:
TutorialUnlockForm (TutorialMarketplaceStatus& status)
: OnlineUnlockForm (status, "Please provide your email and password.")
{
}
ここでは、前のセクションで実装したTutorialMarketplaceStatusクラスへの参照も渡し、クラスコンストラクタでユーザーに指示するための説明メッセージを提供します。
MainContentComponentで、それぞれTutorialMarketplaceStatusとTutorialUnlockFormオブジェクトのインスタンス、およびアプリケーションがアンロックされたかどうかを保存するブール値の3つのプライベートメンバー変数を宣言します。
TutorialMarketplaceStatus marketplaceStatus;
TutorialUnlockForm unlockForm;
bool isUnlocked = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};
TutorialMarketplaceStatusオブジェクトを渡してTutorialUnlockFormを初期化するようにコンストラクタを変更し、ここに示すようにフォームを子Componentとして追加します:
class MainContentComponent : public juce::Component,
private juce::Timer
{
public:
//==============================================================================
MainContentComponent()
: unlockForm (marketplaceStatus)
{
addChildComponent (unlockForm);
setSize (400, 250);
startTimer (100);
}
ここでは、Timerクラスからも継承し、後でアプリがアンロックされたかどうかを確認するために使用されるstartTimer()関数を呼び出していることに注意してください。
resized()メソッドで、centreWithSize()関数を呼び出すことでインターフェースのほとんどをカバーするようにフォームのサイズを設定します:
void resized() override
{
unlockForm.centreWithSize (300, 200);
showForm()ヘルパー関数は、ユーザーが「Unlock」ボタンを押したときに呼び出されます。ComponentはaddAndMakeVisible()ではなくaddChildComponent()関数で単純に追加されたため、フォームはデフォルトで非表示になっているため、ここではsetVisible()を呼び出してフォームを表示するだけです:
void showForm()
{
unlockForm.setVisible (true);
}
登録プロセスがキャンセルまたは成功した場合、フォームを閉じる必要があり、OnlineUnlockFormクラスは自動的にdismiss()コールバックを呼び出してこれを行います。TutorialUnlockForm宣言で、setVisible()を呼び出してComponentを非表示にするだけでこの関数をオーバーライドします:
void dismiss() override
{
setVisible (false);
}
};
MainContentComponentのコンストラクタで前に見たように、タイマーが起動されて、timerCallback()関数でアプリケーションが正常にアンロックされたかどうかを定期的に確認します:
void timerCallback() override
{
if (!isUnlocked && marketplaceStatus.isUnlocked())
{
isUnlocked = true;
unlockApp();
}
}
ここでは、isUnlockedローカル変数でアプリがまだロックされているかどうかを確認し、そうであれば、isUnlocked()関数を介してOnlineUnlockStatusインスタンスにアプリがまだロックされているかどうかを尋ねます。アプリが認証された場合、その後の反復を防ぐためにローカル変数を切り替え、次のunlockApp()ヘルパー関数を呼び出します:
void unlockApp()
{
secretButton.setEnabled (true);
unlockButton.setEnabled (false);
unlockLabel.setText ("Status: Unlocked", juce::dontSendNotification);
unlockLabel.setColour (juce::Label::textColourId, juce::Colours::green);
}
この関数は単に秘密機能にアクセスするボタンを有効にし、アプリをアンロックするボタンを無効にして、新しい認証ステータスを表示します。
最後に、checkFeature()関数はユーザーが秘密機能ボタンをクリックしたときに呼び出され、アンロックされたアプリケーションの動作をシミュレートします:
void checkFeature()
{
if (marketplaceStatus.isUnlocked())
DBG ("App unlocked!");
else
DBG ("Beware of hackers!");
}
この関数は重要です。アプリケーションに別のセキュリティ層を提供するためです。ここで、関数がOnlineUnlockStatusインスタンスでアプリがまだアンロックされているかどうかを再度確認していることに注意してください。この背後にある理由は、ハッカーがアプリをアンロックするためにこの関数をクラックする必要があるだけでなく、アプリの制限された機能を完全に侵害するためにアプリケーションコード内のこの関数のすべてのインスタンスを置き換える必要があるためです。
したがって、より堅牢なセキュリティメカニズムを提供するために、コード内のできるだけ多くの場所でアプリケーションの認証ステータスを確認することをお勧めします。
これでアプリケーションを実行すると登録フォームを表示できます。

ただし、任意のメールとパスワードの組み合わせでアプリを登録しようとすると、以下のエラーメッセージが表示されます:

これは、認証サーバーへの接続ができないためであり、セットアップはこのチュートリアルの次のセクションで説明されています。
このコードの変更版のソースコードは、デモプロジェクトのOnlineUnlockStatusTutorial_02.hファイルにあります。
バックエンドサーバーのセットアップ
このセクションでは、PHPを使用したmacOSとWindowsでのローカルテストサーバーのセットアップ手順を説明しますが、Java、Ruby、Pythonなど、任意のタイプのバックエンドサーバーを自由に使用してください...
OnlineUnlockStatusクラスはXML形式でサーバーからの応答を処理するため、PHPを使用してXML応答を提供する必要があります。アプリケーションは、チュートリアルの最初のセクションで「https://localhost:8443/auth.php」として定義された`TutorialMarketplaceStatus`実装の`getServerAuthenticationURL()`関数で提供された[URL](https://docs.juce.com/master/classURL.html "Represents a URL and has a bunch of useful functions to manipulate it.")に資格情報を送信します。
したがって、デモプロジェクトのResourcesフォルダに付属のauth.phpファイルを見て、PHPで応答がどのように作成されたかを調べましょう:
<?php
function sendResponse() // [1]
{
$response = '<?xml version="1.0" encoding="utf-8"?>'; // [2]
if ($_POST['email'] === 'test@example.com' and $_POST['pw'] === 'test') // [3] {
$response .=
'<MESSAGE message="Thanks for registering our product!"><KEY>INSERT_KEY_HERE</KEY></MESSAGE>';
} else {
$response .=
'<ERROR error="Sorry, we were not able to authorise your request. Please provide a valid email address and password."></e>';
}
return $response;
}
header('Content-type: text/xml; charset=utf-8'); // [4]
echo sendResponse();
?>
- [1]:まず、後でXMLコンテンツを表示するために呼び出される
sendResponse()という関数を定義します。 - [2]:次に、メタデータヘッダーをローカルPHP変数に割り当ててXMLドキュメントを準備します。
- [3]:次に、POST経由で受信したテストメールとパスワード文字列と比較して、資格情報がテストユーザーに対応するかどうかを確認します。資格情報が一致する場合、次のセクションで挿入する暗号化されたキーファイルとともに成功メッセージを追加します。そうでなければ、認証が失敗した理由を説明するエラーメッセージを追加します。
- [4]:最後に、コンテンツがXML形式であることを示すように応答ヘッダーを設定し、
echo関数で応答を送信します。
この時点で、サーバーをローカルで実行してアプリから認証サーバーに連絡しようとすると、接続がプライベートまたは安全ではないというセキュリティ警告を受け取ります。OnlineUnlockStatusインスタンスが資格情報を安全に送信するには、HTTPSプロトコルを介してSSLを使用して安全な接続を作成する必要があります。
これをテスト目的でローカルで行うには、自己署名証明書を作成し、トンネリングを使用してHTTPSを介して基礎となる安全でないHTTPプロトコルにアクセスできます。
バックエンドサーバーをテストするには、OpenSSL、PHP、および「stunnel」がコンピュータにインストールされていることを確認してください。OpenSSLは自己署名証明書を生成するために必要であり、PHPはマシン上でローカルに実行できる組み込みWebサーバーを提供し、「stunnel」は安全な接続をトンネルすることができます。
プロジェクトのResourcesフォルダに移動し、ターミナルから以下のコマンドを実行して自己署名証明書を作成します:
// RSAキーと証明書のペアを作成します。
// macOS
openssl req -new -newkey rsa:4096 -x509 -nodes -sha256 -days 365 -keyout stunnel.key -out stunnel.cert
// Windows
C:\\path-to-openssl\\openssl req -new -newkey rsa:4096 -x509 -nodes -sha256 -days 365 -keyout stunnel.key -out stunnel.cert
証明書の情報を提供するよう求められたら、共通名またはCNエントリを除くすべてのフィールドをスキップし、「localhost」と入力します。
ドメイン名のスペルミスがないことを確認してください。これにより、サーバーへの接続時に問題が発生する可能性があります。
これにより、SHA-256ハッシュアルゴリズムと1年の有効期限を使用したRSA 4096ビットキーと証明書のペアを形成する2つのファイルが作成されます。X.509標準は、関心のある自己署名ポリシーを示します。簡単にするために、生成されたキーと証明書ファイルを次のように1つのPEMファイルに結合します:
// キーと証明書をPEMファイルに結合します。
// macOS
cat stunnel.key stunnel.cert > stunnel.pem
// Windows
type stunnel.key stunnel.cert > stunnel.pem
macOSでは、FinderでPEMファイルをダブルクリックして、証明書をキーチェーンに追加します。これにより、Applications/Utilitiesフォルダにあるキーチェーンアクセスアプリケーションが開きます。リスト内の新しく追加された証明書をダブルクリックして詳細ビューを開き、信頼ビューを展開します。以下に示すように、Macの現在のユーザーアカウントで証明書を信頼するために「常に信頼」オプションを選択します:

Windowsでは、実行プロンプトで「MMC」と入力してMicrosoft管理コンソールを開き、**ファイル > スナップインの追加...**に移動して「証明書」を選択します。追加をクリックして現在のユーザーの証明書を追加し、OKをクリックして終了します。

次に、左パネルの対応するフォルダに移動し、メニュー項目からアクション > すべてのタスク > インポート...を選択して、自己署名証明書を信頼されたルート証明機関 > 証明書にインポートします。証明書を見つけるステップに案内され、その時点でMMCが受け入れる形式である.cert拡張子のファイルを選択する必要があります。

実際のアプリケーションでは自己署名証明書やトンネリングを使用しないでください。これはCA署名証明書ほど安全とは見なされません。この方法はデモンストレーション目的でのみ使用されます。
次に、デモプロジェクトのResourcesフォルダに付属のstunnel.confファイルを開いてトンネリングプロトコルを設定しましょう:
[https]
accept = 8443
connect = 8080
cert = stunnel.pem
TIMEOUTclose = 0
ここでは、接続する送受信ポートと、リンクを保護するために前のステップで作成した証明書ファイルを定義します。アプリケーションはポート8443に接続しようとし、トンネリングはPHPサーバーが実行されているポート8080にリンクします。
最後に、Resourcesディレクトリに移動し、ターミナルから以下のコマンドを実行してサーバーを起動できます:
// 組み込みPHP Webサーバーを起動し、安全な接続をトンネルします。
// macOS
php -S localhost:8080 & stunnel stunnel.conf
// Windows
C:\\path-to-php\\php -S 127.0.0.1:8080 & C:\\path-to-stunnel\\stunnel stunnel.conf
これにより、ローカルサーバーがポート8080で起動し、アプリケーションが安全にアクセスできるように接続がポート8443にトンネルされます。お気に入りのブラウザで認証URL「https://localhost:8443/auth.php」を開いて、サーバーが実行されていることを確認してください。`auth.php`ファイルで宣言されたエラーメッセージがXML応答の形式で表示されるはずです。
すべてが正しく機能する場合は、アプリケーションを起動し、任意のメールとパスワードの組み合わせを送信して認証を試みます。受信するエラーメッセージは前回の試みとは異なり、以下のようにブラウザに表示されたメッセージと一致するはずです:

これは、アプリケーションがサーバーに正常に連絡し、応答を処理したことを意味しますが、アプリケーションをアンロックするために正しいキーファイルを生成して送信する必要があります。
キーボードの「Ctrl+C」を押すか、以下のコマンドを実行してサーバーとトンネリングを停止します:
// 実行中のPHPサーバープロセスとHTTPSからHTTPへのトンネリングを停止します。
// macOS
killall php & killall stunnel
// Windows
taskkill /f /im php.exe & taskkill /f /im stunnel.exe
セキュリティキーの生成
最後のステップとしてセキュリティキーの生成を見てみましょう。
プロジェクトのResourcesフォルダに、このアプリケーションの認証に使用するRSAキーペアを生成するKeyGeneratorというヘルパーコンソールアプリケーションがあります。これらはプロジェクトの存続期間中同じままでいられるため、アプリやプラグインごとに1回だけキーを生成する必要があります(秘密キーが何らかの形で侵害された場合を除き、その場合は新しいペアを作成する必要があります)。
KeyGeneratorアプリのmain()関数を見ると、256ビットのキーサイズでRSAKeyクラスのcreateKeyPair()関数を呼び出し、結果を画面に出力しているだけであることがわかります:
juce::RSAKey publicKey;
juce::RSAKey privateKey;
juce::RSAKey::createKeyPair (publicKey, privateKey, 256);
std::cout << "Public Key: " << publicKey.toString() << std::endl
<< "Private Key: " << privateKey.toString() << std::endl
<< std::endl;
KeyGeneratorアプリをビルドし、以下のコマンドを実行してキーを取得します:
// プログラムを実行してキーをコピーします。
// macOS
./KeyGenerator
// Windows
KeyGenerator.exe
前のステップから公開キーをコピーして、TutorialMarketplaceStatusクラスのgetPublicKey()関数に貼り付けます:
return juce::RSAKey ("INSERT_PUBLIC_KEY_HERE");
これにより、メッセージが本物であり、一致する秘密キーを使用して暗号化された場合、アプリケーションはサーバーからのメッセージを復号化できます。
サーバーがアプリから要求されたときに本物のキーファイルを生成するには、メッセージを暗号化するために前のステップで生成された秘密キーを所有している必要があります。実際の本番シナリオでは、キー生成ステップはサーバー上でプログラム的に行う必要がありますが、このチュートリアルの目的のために、このステップを手動で実行し、キーファイルをPHPスクリプトにコピーして貼り付けます。
Resourcesフォルダに再度移動して、Unlockerという別のヘルパーコンソールアプリケーションを見つけます。これは、KeyGenerationクラスのgenerateKeyFile()関数を呼び出すことで、アプリをアンロックするために必要なキーファイルを作成します:
// args[0]: app-name
// args[1]: user-email
// args[2]: username
// args[3]: machine-numbers
// args[4]: private-key
std::cout << juce::KeyGeneration::generateKeyFile (args[0], args[1], args[2], args[3], juce::RSAKey (args[4])) << std::endl;
この関数は、アプリ名、ユーザーのメールとユーザー名、使用が許可されたマシンID、およびメッセージを暗号化するRSA秘密キーを引数として取ります。デモプロジェクトを実行して登録を試みると、デバッガログを確認することで対応するマシンIDを見つけることができます。
Unlockerアプリをビルドし、以下のコマンドを実行して暗号化されたキーファイルを取得します:
// プログラムを実行してキーをコピーします。
// macOS
./Unlocker TestApp test@example.com testuser INSERT_MACHINE_ID_HERE INSERT_PRIVATE_KEY_HERE
// Windows
Unlocker.exe TestApp test@example.com testuser INSERT_MACHINE_ID_HERE INSERT_PRIVATE_KEY_HERE
前のステップから「#」文字で始まるキーファイルをコピーして、PHPスクリプトのsendResponse()関数に「#」文字を含めて貼り付けます:
$response .= '<MESSAGE message="Thanks for registering our product!"><KEY>INSERT_KEY_HERE</KEY></MESSAGE>';
サーバーを起動し、PHPスクリプトで定義された適切なメールとパスワードの組み合わせを送信して認証を試みるためにアプリケーションを実行します:

すべてがうまくいけば、以下の成功メッセージが表示され、登録フォームが閉じた後にアプリケーションがアンロックされるはずです:

まとめ
このチュートリアルでは、オンライン登録を通じてプラグインをアンロックする方法を学びました。特に、以下のことを行いました:
- RSAによる暗号化の原理を理解しました。
- フォームを通じてユーザーがアプリをアンロックするためのUIを提供しました。
- アプリのアンロックメカニズムのためのセキュリティキーを生成しました。
- バックエンドとして機能するシンプルな安全なローカルサーバーを構築しました。
- 登録ステータスに応じてアプリケーションの機能をアンロックしました。