OZeroSDK Manual - Unity Native C++ Security Setup Guide
OZero Security
ドキュメント

はじめに

このガイドでは、OZero Security のインストールから最初のセキュリティ機能適用までを段階的に案内します。セキュリティの専門知識がなくても、約3分で基本設定を完了できます。

約3分 · Unity 2020.3 LTS+ · iOS 12.0+ / Android API 21+

概要

OZero Security は、一般的なハッキングツールがアクセスしにくい Native C++ レイヤーでセキュリティロジックを実行し、Unity ゲームを保護します。Unity エディター内のダッシュボードでモジュールを有効化するだけで、コアな保護機能が動作します。シーンの設定や追加のコード作成は必要ありません。

基本提供される保護機能:
  • ビルド整合性検査(アプリ改ざん検知)
  • スピードハックおよびタイムハック検知
  • メモリインジェクション監視
  • 暗号化されたインゲーム変数型(Secure Types)
  • 暗号化されたセーブファイルと PlayerPrefs
コード接続が不要な自動ブートストラップおよび Config 暗号化
  • 有効化された検出器は SDK 開始時に自動的に準備されます。シーンに別のオブジェクトを配置したり、繰り返し初期化コードを記述したりする必要はありません。
  • セキュリティ設定はビルド処理中に保護され、一般プレイヤーの配布物に平文の設定が露出することはありません。
  • Native C++ ランタイムガードが、管理された Unity コードの外側で追加の検証レイヤーを提供します。
  • 検知結果はコールバック、ログ、Pro テレメトリで確認できるため、テストや運用中に原因を追跡しやすくなります。

1 パッケージのインポート

Unity エディターを開き、OZero Security パッケージをインポートします。Unity Package Manager を使用するか、.unitypackage ファイルをダブルクリックしてインポートできます。

Import Unity Package ダイアログが表示されたら、すべての項目がチェックされた状態で Import をクリックしてください。必要なスクリプト、ネイティブプラグイン、エディターツールが自動的に追加されます。

Import Unity Package dialog with all OZeroSDK files selected
インポートの前に Unity のプレイモードを終了し、可能であればエディターを一度再起動してから進めてください。実行中のプレイヤーが OZero DLL をロードした状態では、Windows が DLL ファイルをロックし、インポートや上書きが失敗する可能性があります。インポート後、Unity がスクリプトを再コンパイルするため、右下の進行状況バーが消えるまで待ってから次のステップに進んでください。

2 ダッシュボードを開く

インポートが完了したら、Unity のメニューバーから Config Dashboard を開きます:

OZeroSDK -> Security -> Config Dashboard
OZero Security Config Dashboard opened in the Unity Editor

Config Dashboard が開くと、この画面でプリセット、セキュリティモジュール、ライセンス、ビルド整合性設定を一度に管理できます。Project ウィンドウでファイルを直接探して修正する必要はありません。

Unity エディターメニューの説明

OZeroSDK > Security メニューには、SDK の設定と診断コマンドがまとまっています。セキュリティプリセットは上部メニューではなく Config & Dashboard から適用する設計です。保存前に変更後の設定を確認できます。

メニュー 役割 使用タイミング
OZeroSDK > Security > Config & Dashboardメインの OZeroSecurityConfig アセットを開く、または作成します。プリセット適用、モジュール有効化、対応ポリシー設定、ビルド整合性設定の確認を最初にここで行います。
OZeroSDK > Security > License > SettingsOZeroLicenseConfig を開く、または作成します。Standard、Plus、Pro のライセンス設定、サーバーエンドポイント、テレメトリオプションを入力するときに使用します。
OZeroSDK > Security > Tools > Check Setupプロジェクトとリリース設定でよく発生する問題をエディター上で診断します。パッケージのインポート直後、リリースビルド前、またはモジュールが期待どおり動作しない場合に実行します。
OZeroSDK > Security > Tools > Check Integrity ManifestOZero 整合性マニフェストを開き、デコードされた内容を確認します。ビルド整合性のトラブルシュートやサポート調査でマニフェスト内容を確認するときに使用します。
OZeroSDK > Security > Tools > Bake Security Config Blob保護されたセキュリティ設定 blob を StreamingAssets に再生成します。高度なデバッグまたは CI ワークフローで使用します。通常のプレイヤービルドでは自動的に bake されます。
OZeroSDK > Security > Tools > Bake Assembly Hash直近のビルド出力に対して oz_ahash.bin を再生成します。フルビルドパイプラインを再実行せず、コードだけを再ビルドした場合にのみ使用します。
OZeroSDK > Security > Tools > Keystore SHA ExtractorAndroid keystore から SHA-1 と SHA-256 fingerprint を抽出します。Build Integrity の Android 署名 fingerprint を入力するときに使用します。
OZeroSDK > Security > Tools > Add Debug SHA Key to ConfigAndroid debug keystore を探し、その SHA-256 fingerprint を config に追加します。ローカル Android デバッグビルドでのみ使用します。リリースビルドではリリース署名キーの fingerprint を使用してください。
OZeroSDK > Security > Tools > Steam Anti-Piracy > Scan Steam RedistributablePC ビルドまたはプラグインフォルダー内の Steam redistributable ファイルと既知の emulator artifact をスキャンします。Steam リリースのパッケージング前、または疑わしい Steam ファイルが含まれていないか確認するときに使用します。
OZeroSDK > Security > Tools > Check Time.timeScale UsageOZero の時間保護と競合する可能性がある直接的な Time.timeScale 書き換えコードをスキャンします。リリース前、または Speed & Time Hack モジュールがプロジェクト側の time-scale ポリシー問題を報告した場合に実行します。

3 モジュールの有効化

ダッシュボード内でセキュリティモジュールの一覧とトグルスイッチを確認できます。使用するモジュールを有効化してください。以下は推奨される開始設定です。

OZero Security Config Dashboard in the Unity Editor

セキュリティのプリセットを選択する

まずプリセットを選択した後、プロジェクトに合わせて個別のモジュールだけ調整してください。一般的なライブゲームは Standard から始めることをお勧めします。保護のレベル、パフォーマンス、誤検知の可能性のバランスが最も良いです。

プリセット 推奨される使用先 適用されるポリシーの要約
Low プロトタイプ、開発ビルド、初期の QA 軽い核心の検査だけ維持します。テストの環境が早すぎる段階でブロックされないよう、プラットフォームネイティブ検査と強制終了のポリシーを緩和します。
Standard ほとんどのリリースゲームに推奨されるデフォルト値 核心保護のセット、開始の際の検証、ランタイムの再検証、エミュレーターの検査、推奨される IL2CPP ファイルのカバレッジをオンにします。互換性と保護のレベルのバランスを合わせた構成です。
Strict リスクの高いライブサービス、PvP、対戦型のビルド 最も広いカバレッジを適用し、より多くの失敗を致命的な違反として処理します。プラットフォーム、署名、ストア配布フローを十分にテストした後に適用してください。
モジュール 機能説明 推奨有無
Build Integrity Validator アプリバイナリの改ざんの有無を検知 推奨
Speed Hack Detector 時間操作チート検知 推奨
Injection Detector メモリフッキングツールの監視 推奨
Install Source Validator 不正な APK のブロック(Android 専用) 選択

ダッシュボードで使用するモジュールをオンにし、OZeroSecurityConfig アセットを保存するだけです。プレイヤーが起動すると、SDK が有効化されたモジュールを自動的に準備します。

シーンに別のオブジェクトを配置する必要はありません。必要なモジュールをオンにして設定を保存すると、次回の実行から該当モジュールが自動的に初期化されます。

ライセンスモデル — Standard / Plus / Pro

OZero Security は Standard、Plus、Pro の3つのティアーで提供されます。Standard はサーバーの連携なしでローカルの保護機能を使用します。Plus はプロジェクト別の Native Variant パッケージとマニフェスト / Bundle ID バインディングを追加します。Pro は Plus の構成を含み、テレメトリー、署名されたサーバー時間、リモートポリシー、サーバー検証、デバイスの限度などの運用機能を提供します。

下のマトリクスは、開発者の観点から SDK がランタイムにティアー別に実際どのように動作するかをまとめたものです。全体の機能の比較はホームページの ライセンスモード比較表 で確認してください。
項目 Standard Plus Pro
ライセンスキー — (なし) OZ-PLS-XXXX ×6 OZ-PRO-XXXX ×6
ブート時のネットワーク 必要なし — オフライン実行可能 ランタイムのサーバー不要 — ポータルで Variant のダウンロードのみ進行 デバイスあたり POST /v1/activate 1回の後キャッシュ
10個の保護モジュール 10個の保護モジュール全体を活性化 10個の全体 (ローカル保護モジュールは Standard と同一) 10個の全体 (Standard と同一)
ネイティブ Variant 共用のネイティブモジュール アプリ別の Variant + マニフェストバインディング 含む
クラウドのテレメトリー 送信しない オフ (サーバーレス) オン — 脅威イベントを /v1/telemetry に送信
署名された時間 (時計の操作防止) オフ — WebTime は HTTPS HEAD のみ使用 オフ — Standard と同一 オン — 署名された /v1/time 応答を使用
デバイスあたりの限度 無制限 (キーなし、強制なし) プロジェクト帰属ライセンス、ランタイムのデバイスの限度なし デフォルト 5台 / 調整可能
ソースコードのアクセス 管理型の C# のみ 管理型の C# のみ 管理型の C# のみ
今日 Standard でリリースした後、後で Plus または Pro にアップグレードしてもゲームプレイのコードはそのまま維持できます。Plus は Variant マニフェストとネイティブパッケージを追加し、Pro はここに OZeroLicenseConfig ベースのサーバー機能を加えます。

Plus / Pro ライセンスキーの登録

Standard ティアーは別途の設定が必要ありません。Plus または Pro は ScriptableObject エセットを1つ追加し、購入後に受け取ったキーを貼り付けます。Plus キーはプロジェクト別の Variant 検証とポータルのダウンロードに使用され、Pro キーはランタイムサーバーの活性化にも使用されます。

1. 設定エセットの生成

Config Dashboard (メニュー: OZeroSDK → Security → Config Dashboard) を開き、License & Server セクションで Create OZeroLicenseConfig ボタンをクリックします。エセットが自動的に正しい Resources/ フォルダに生成されるため手動で移動する必要はありません。

または Project 窓で Assets → Create → OZero → License Config で手動生成も可能です。ただし、エセットが Resources/ フォルダの直下にあり、名前が正確に OZeroLicenseConfig(大文字と小文字を区別)であることを直接確認する必要があります。

2. Inspector フィールドを埋める

フィールド 必須の可否 説明
tier すべてのティアー ドロップダウンで StandardPlusPro のいずれかを選択します。Standard は基本のネイティブモジュールを使用します。Plus はプロジェクトに接続された Variant manifest が必要です。Pro は Plus 機能にサーバーの運用機能を加えます。
licenseKey Plus / Pro 電子メールで受け取ったキーです。Plus キーは OZ-PLS-...、Pro キーは OZ-PRO-... 形式を使用します。キーを空にしておくと、Plus または Pro を選択してもサーバー機能を使用せず Standard と同じ方式で実行されます。
appIdentifier 自動送信 SDK は活性化の際に Unity の Application.identifierappIdentifier として送信します。サーバーはこの値をライセンスに登録されたバンドル / パッケージ id と比較するため、Player Settings の Identifier が発行されたキーと一致する必要があります。
serverBaseUrl Plus / Pro デフォルト https://api.ozero.security — OZero サポートチームが別途のエンポイントを案内した場合を除いてそのまま置いておきます。リリースビルドでは必ず HTTPS である必要があり、trailing slash は自動的に除去されます。
serverPublicKeyHex Plus / Pro OZero ライセンスサーバー応答の署名を確認する公開キーです。購入の電子メールに含まれる64桁の hex 値をそのまま貼り付けます。リリースビルドではこの値を空にしないことをお勧めします。
tokenTtlSeconds 選択 オフラインの状態でキャッシュされた活性化の結果を信頼する時間(秒)。デフォルト 604800 (7日)。満了の後にも SDK は継続して動作しますが、次の成功の活性化までサーバー専用の機能(テレメトリー / signed time)が消えます。
offlineProPolicyMode Plus / Pro デバイスがオフラインの時、署名された Pro ポータルのブロックのポリシーをどう適用するか決めます。推奨される値は ApplyCachedBlockPolicies です。RequireFreshPolicy はポリシーが古ければ拒否すべきオンライン専用ゲームにのみ使用してください。IgnoreCachedBlockPolicies は特殊なテストの状況のためのオプションであり、ライブビルドにはお勧めしません。
activationTimeoutSeconds 選択 /v1/activate 応答を待つ最大時間(秒)です。この時間を超過すれば SDK は保存された活性化の情報を使用するか Standard 方式で引き続き実行します。デフォルト値は 6.0秒です。
enableLog 選択 true であれば、ライセンスキャッシュの使用、活性化の成功、タイムアウト、署名の不一致のような流れを OZeroSecLog として記録します。リリースのビルドでログを減らしたい場合はオフにします。

3. ビルド & 検証

コードの変更は必要ありません。アプリが開始されると SDK が OZeroLicenseConfig エセットを自動的に読み取ります。最初の実行の後 Player ログから [OZeroLicense] activated; tier=pro caps=5 と同じ列を確認してください。Pro として設定したのに Standard モードで実行されるというログが見える場合は、エセットが Resources/ フォルダーの下にあり、名前が正確に OZeroLicenseConfig か確認してください。

ライセンスキーは秘密ではありません — 流出されてもサーバーが強制するデバイスあたりの限度を誰かが使い果たすのが全てです。そのため、エセットはビルドと共に同封され (意図的に) 暗号化されません。キーはパスワードではなく製品コードのように扱ってください。

サーバーの活性化のフロー

活性化はアプリ開始の際にバックグラウンドで進行されます。サーバーの応答が遅れたり一時的に失敗してもシーンのロードを止めず、保存された活性化の情報があればその値を使用します。

ブートシーケンス

  1. SDK はアプリの開始の際、ライセンスランタイムを自動初期化します。
  2. Standard と Plus はランタイムサーバー呼び出しなしに引き続き進行されます。
  3. Pro はバックグラウンドで軽い活性化のリクエストを送ります。
  4. 活性化に成功すればテレメトリー、signed time、attestation のような Pro サーバー機能が使用可能になります。
  5. 活性化の失敗、満了、タイムアウトが発生してもプレイヤーにエラーを表示せず Standard モードで継続して実行されます。

ネットワークに流れるデータ

活性化のリクエストは小さな JSON POST です。必須フィールドは licenseKeydeviceIdsdkVersionplatform です。appIdentifiercompanyNameproductNamewebglOrigin は Unity で空でない値を提供するときにのみ追加されます。デバイスの識別子のソースは OZeroLicenseRuntime.DeviceIdProvider としてオーバーライドできます。

POST https://api.ozero.security/v1/activate
Content-Type: application/json

{
  "licenseKey":    "OZ-PRO-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX",
  "deviceId":      "<DeviceIdProvider result; default SystemInfo.deviceUniqueIdentifier>",
  "sdkVersion":    "<OZeroSdkVersion.ManagedVersion>",
  "platform":      "<android | ios | windows | macos | linux | webgl | ...>",
  "appIdentifier": "<Application.identifier>",
  "companyName":   "<Application.companyName>",
  "productName":   "<Application.productName>",
  "webglOrigin":   "<WebGL origin only>"
}

サーバーは署名されたトークン、決定されたティアー、使用可能な機能のリスト、満了時刻を JSON として返します。SDK は設定された公開キーで応答の署名を確認した後のみ Pro 機能を活性化します。

サーバーの機能を使用できない場合

サーバーの点検、ネットワークのタイムアウト、ライセンス満了/停止/廃棄、Bundle ID 不一致はすぐにハッキングとして判断しません。この場合、Pro 専用の機能のみ非活性化し、基本の保護機能は継続して実行します。反対にビルド不一致、ブロックされたビルド、インジェクション、デバッガーのように改ざんが明確な状況は設定された対応のポリシーに従います。

ライブの活性化が実際に成功したか確認したい場合 (キャッシュのみを信頼せず)、独自のブートストラップで await OZeroLicenseRuntime.Initialize(); を呼び出し、OZeroLicenseRuntime.Entitlement?.cachedAtMillis を探してみてください。最近数秒以内の値であればサーバーがちょうど応答したことで、もっと古い値であればキャッシュベースで動作中です。

オフラインの動作

OZero はネットワーク状態と無関係にプレイヤーが常にゲームを実行できるように設計されました。正確な動作はティアーによって異なります:

Standard — 常にオフライン

Standard はサーバーの活性化やテレメトリーの転送なしでローカルの保護機能のみ実行します。ネットワークがなくてもゲームはそのまま開始され、Pro 専用の機能のみ使用されません。

Pro — TTL 内のオフライン可能

指定デバイスで /v1/activate が初めて成功した後、Pro 活性化の情報は PlayerPrefs に保存されます(デバイスのバインディングキーで暗号化 — 下記のキャッシュセキュリティを参照)。以後の実行ではネットワーク呼び出しが始まる 前に 保存された活性化の情報を読むため、プレイヤーがオフラインであっても SDK はどんなティアーでどんな Pro 機能が使用可能かわかります。

保存された Pro 活性化の情報は活性化の時点に記録された cachedAtMillis から tokenTtlSeconds の間信頼されます。デフォルト 7日(604800)です。その間ずっとオフラインの状態で時間が過ぎれば保存された情報は廃棄され、次のオンライン活性化が成功するまで SDK は Standard レベルで動作します。ディテクターは引き続き動作し、テレメトリーの送信と signed-time 検証のみオフになります。

Pro — 署名されたオフラインのブロックのポリシー

サーバーの障害の際に基本の保護で継続して実行されることと、ポータルで明示的にブロックしたビルドを許可することは異なります。Pro 活性化が成功すればサーバーは現在のブロックのポリシーを署名された形で提供し、SDK はこれを別途に保存します。

推奨される値である ApplyCachedBlockPolicies モードでは、署名されたポリシーが有効な間にプレイヤーが機内モードで実行しても、ブロックされた manifest hash、SDK のバージョン、アプリのバージョンが Build Integrity で継続して拒否されます。ポリシーは署名トークンの TTL に従うため、ポータルでブロックのルールを変えた後は1度のオンラインの活性化が必要です。

まだ Pro 活性化を一度も受け取ったことのない最初の実行のデバイスは、完全オフラインの状態でポータルのブロックのルールを知ることができません。売上/経済の流れが重要なライブゲームは、核心のプレイまたは財貨の処理の区間でサーバーサイドセッション/OZA 検証を最終の関門として維持してください。
状態 ディテクター テレメトリー Signed Time
オンライン、ちょうど活性化 10個の全て On On On
オフライン、キャッシュ < TTL 10個の全て On キュー (次のオンラインの際転送) WebTime HTTPS HEAD 使用
オフライン、キャッシュ > TTL 10個の全て On Off (降等) Off (降等)
キャッシュなし (最初の実行 + オフライン) 10個の全て On 最初のオンライン実行まで Off 最初のオンライン実行まで Off
オフラインで発生したテレメトリーイベントはディスクにバッファリングされません — warn レベルのログ1行と一緒に廃棄されます。意図された動作です: バッファリングされたキュー自体が変調の表面になります。次のオンライン状態の正常な検知は正常に送信されます。

トラブルシューティング

すべてのライセンスイベントは、基本的に Unity の Debug.Log にルーティングされる OZeroSecLog を通じて記録されます (OZeroSecurityConfig で設定可能)。Player ログを [OZeroLicense] プレフィックスでフィルタリングして起動時点の決定を確認し、[OZeroTelemetry] でレポーターを確認してください。一般的な症状と解決策:

症状 (ログライン) 予想される原因 確認する事項
[OZeroLicense] Standard / serverless mode. エセットの欠落または tier=Standard または空のキー OZeroLicenseConfig.assetResources/ フォルダの直下にあり、名前が正確に OZeroLicenseConfig であり、tier=Pro であり、空いていない licenseKey を持っているか確認してください。
/v1/activate failed: 401: invalid_key キーの入力ミスまたは間違ったティアーのプレフィックス 元の購入電子メールからキーを再度貼り付けてください。形式は大文字と小文字を区別し、ダッシュが含まれる必要があり、プレフィックスは OZ-PRO- である必要があります。
/v1/activate failed: 403: bundle_mismatch appIdentifier の不一致 サーバー側のライセンスの記録はキーを特定のバンドル / パッケージ id にバインドします。Player Settings の Application.identifier がライセンスに登録された id と一致するか確認してください。
activation token signature verification failed 間違った serverPublicKeyHex または MITM エセットの hex 文字列を購入電子メールの標準公開キーと比較してください — 64個の hex 文字が1文字も欠かさずに一致する必要があります。正確であるのに引き続き失敗する場合は、企業のプロキシ/MITM アプライアンスを疑い、直接モバイルデータ接続を試してください。
/v1/activate timed out ネットワークの遅延 / ファイアウォール SDK は自動的に保存された活性化の情報を使用します。最初の実行であるか、保存された情報がない時にのみ問題になります。デバイスが https://api.ozero.security/health に到達できるか確認してください。遅延がひどい地域で運用する場合は activationTimeoutSeconds を増やしてください。
cached activation past TTL; clearing. プレイヤーがオフライン > TTL 正常です。ディテクターは引き続き動作します; 次のオンライン実行までテレメトリー / signed-time は消えます。ユーザーが7日以上オフラインでプレイする場合が多い場合は tokenTtlSeconds を増やしてください。
cache hit; tier=pro on a different machine than expected デバイスの指紋の変更 SystemInfo.deviceUniqueIdentifier が変更されると(一部の Android ROM / OS 初期化)、保存された活性化の情報を読めなくなり、SDK が再び活性化を試みます。ユーザーの操作は必要ありません。次のオンライン実行の際に復旧します。
リリースビルドでは enableLog を消しておくことをお勧めします。開発ログにはティアー、機能の状態、検知のフローの一部が残る可能性があり、QA には有用ですが、一般ユーザーの配布には必要ありません。

プロジェクト設定

個別のセキュリティモジュールを調整する前に、ネイティブプラグインとストアのビルド、プラットフォームの検証に影響を与える Unity Player Settings を先に確認してください。

最小のビルドターゲット

プラットフォーム 最小のターゲット 説明
iOS 12.0+ iOS ビルドでは Project Settings > Player > iOS > Target minimum iOS Version12.0 以上に設定してください。OZero はこの PlayerSettings 値を強制的に上書きしないため、アプリのサポート方針に合わせて維持すればよいです。
Android API 21+ Android ビルドは Project Settings > Player > Android > Minimum API LevelAndroid 5.0 Lollipop (API level 21) 以上に設定してください。ストアのリリースビルドは IL2CPP と ARM64 の使用を推奨します。

リリースビルドの IL2CPP と Managed Stripping

Android、iOS、standalone のリリースビルドでは、Unity が対応している場合 IL2CPP を優先してください。IL2CPP はリバースエンジニアリングを不可能にするものではありませんが、平文の managed metadata 露出を減らし、OZero の native 整合性チェックにより強いリリース基準を与えます。

Project Settings > Player > Other Settings > Scripting BackendIL2CPP に設定してください。リリースビルドの Managed Stripping Level はまず Low または Medium にし、対象デバイスでクリーンなスモークテストを実行します。reflection、serialization、Addressables、サードパーティ SDK の流れを確認する前に、より厳しい stripping level へ上げないでください。

Windows Standalone ビルドを実行する PC には Microsoft Visual C++ Redistributable 2015-2022 (x64) がインストールされている必要があります。このランタイムがないと、Windows が OZero のネイティブプラグインを読み込めず、アプリが起動直後に終了する可能性があります。Steam、ランチャー、独自のインストールファイルで配布する場合は、VC++ Redistributable を必須の構成要素として一緒にインストールするように構成してください。

Android ProGuard / R8 の設定

OZero Security は別途の Java SDK パッケージを要求しません。ただし、Android リリースビルドで Minify、ProGuard、R8 を有効にした場合は、Unity Java ブリッジとプロジェクトで使用するカスタム Android ブリッジクラスを保持する必要があります。そうすることで、パッケージ情報、インストール元、APK 署名証明書チェック、ブートアセットロードに必要な JNI 呼び出しが難読化以降も安定して動作します。

Unity で Project Settings > Player > Android > Publishing Settings を開きます。Minify Release をオンにした場合は、Custom ProGuard File も有効にした後、以下のルールを proguard-user.txt に追加してください。Minify を使用しない場合、別途の ProGuard 設定は必要ありません。
# OZero Security - Unity Android ProGuard/R8 keep rules
-keep class com.unity3d.player.UnityPlayer { *; }
-keep class com.unity3d.player.UnityPlayerActivity { *; }
-keep class com.unity3d.player.UnityPlayerGameActivity { *; }
-keep class com.unity3d.player.UnityPlayerForActivityOrService { *; }
-keepattributes *Annotation*,InnerClasses,EnclosingMethod,Signature

# If your game adds custom Java/Kotlin bridge classes that OZero or your code
# calls through AndroidJavaClass / AndroidJavaObject, keep those classes too.
# Replace the package below with your own bridge package.
# -keep class com.yourcompany.yourgame.bridge.** { *; }

5 OZeroSecurityConfig の設定

OZeroSecurityConfig ScriptableObject アセットはパッケージのインポート時に含まれます。Project ウィンドウで選択し、すべてのセキュリティモジュールの設定を確認および調整してください。ランタイムでは OZeroSecurityConfig.Instance としてアクセスします。

OZeroSecurityConfig Inspector panel in the Unity Editor

Common Setting

すべてのモジュールにグローバルに適用される最上位フィールドです。

フィールド Type デフォルト 説明
developerSecret string 暗号化キーの導出に使用される固有のパスフレーズです。ゲームに固有の値を設定し、秘密に保ってください。リリース後に変更すると、既存のセーブデータが読み取れなくなります。
enableLog bool false Enable Debug Logs をオンにすると、SDK 初期化、設定の読み込み、ライセンス/テレメトリの流れ、検知イベントなどの内部状態が Unity Console と Player ログに出力されます。開発/QA 段階で原因を特定するのに役立ちますが、検知フローやモジュールの状態が露出する可能性があるため、本番ビルドではオフにすることを推奨します。
enableFailureDiagnostics bool false Enable Failure Diagnostics をオンにすると、セキュリティ違反が発生した際にローカル診断ファイルを Application.persistentDataPath に保存します。ファイルにはモジュール名、ハッシュ、デバイスの状態、インストールパッケージ名、ランタイム設定の一部が含まれる可能性があるため、QA やカスタマーサポートセッションでのみオンにすることを推奨します。

プラットフォームごとの既定の保存場所:
  • Windows: %USERPROFILE%\AppData\LocalLow\CompanyName\ProductName
  • macOS: ~/Library/Application Support/CompanyName/ProductName
  • Linux: ~/.config/unity3d/CompanyName/ProductName
  • Android: /storage/emulated/0/Android/data/package.name/files
  • iOS: アプリサンドボックスの Documents フォルダ
  • WebGL: ブラウザの IndexedDB に基づく /idbfs ストレージ
重要: 最初のリリース前に必ず固有の Developer Secret を設定してください。デフォルト値を使用せず、リリース後には変更しないでください。

Global Threat Response

セキュリティの脅威が確認されたときのゲームの反応を設定します。テスト中はコールバックとログを先に確認し、実際の配布ビルドではプレイヤーへの通知時間と終了ポリシーをプロジェクトの運用方法に合わせて選択してください。

フィールド Type デフォルト 説明
forceQuitOnDetection bool true forceQuitOnDetection は、確定した脅威が検知されたときに SDK がゲームを自動終了するかどうかを決定します。オフにするとコールバックとログだけを確認でき QA には便利ですが、実際の配布ビルドでは迂回されたクライアントが実行を続ける可能性があるため、慎重に選択してください。
fatalCallbackGraceSeconds float 10 fatalCallbackGraceSeconds は、脅威検知後、ゲーム側のセキュリティコールバックがプレイヤーへの通知 UI を表示できる最大時間です。デフォルト値は 10 秒です。0 に設定すると、通知時間を置かずに即座に終了する以前の方式で動作します。

ビルド整合性検証器の設定

修正されたゲームファイル、デバッガーの接続、異常な実行環境を検知するビルド整合性チェッカーを構成します。

フィールド Type デフォルト 説明
Activate Build Integrity checkbox On Build Integrity モジュールを有効化します。
validateOnStartupbooltrueゲーム実行直後にビルド整合性チェックを実行します。
validateInEditorboolfalseUnity エディターでも検証を実行します(テスト用には有用ですが、一般的な開発中はオフにすることを推奨)。
enablePeriodicValidationbooltrueゲームの実行中にも無欠性の検証を繰り返します。開始時に1回の検証だけで十分なビルドでない場合はオンにしておくことをお勧めします。
periodicCheckIntervalfloat300 sゲーム実行中に定期的なセキュリティチェックが実行される間隔(秒)です。
periodicCheckJitterPercentfloat35%検証の周期にランダムな変化を加えて、検査のタイミングを予測しにくくします。具体的な周期と範囲は公開された文書では案内せず、デフォルト値の使用をお勧めします。
timingAnomalyConsecutiveRequiredint7タイミングに基づく異常な信号が何回累積されなければデバッガーのタイミングのドリフトとして判断するか決めます。強いデバッガーの信号は即座に失敗することがあります。
timingAnomalyWindowSecondsfloat900 sタイミングに基づく異常な信号を累積する時間の窓です。長いほど寛大で、Strict はより短い窓を使用します。
timingAnomalyFrameHitchSuppressionSecondsfloat20 sシーンのロード、シェーダーのコンパイル、GC、OS のスケジューリングの遅延のような大きなフレームのヒッチが発生した後、一定の時間の間タイミングに基づくデバッガーの検査を緩和します。
checkAssemblyHashbooltrueビルド整合性チェックの一環として、コンパイルされた DLL アセンブリのハッシュを検証します。
checkDebuggerbooltrueランタイムにデバッガーがプロセスに接続されているかを探知します。
failOnDebugBuildboolfalseUnity デバッグビルドを違反とみなします(リリースビルドで推奨)。
checkPlatformNativebooltrueエミュレーターや異常な環境で実行中の兆候を確認します。
failIfManifestMissingbooltrueoz_manifest.ozero ファイルが存在しないか読み取れない場合、違反として処理します。リリースビルドではこの値をオンにして、マニフェストが欠けたビルドが配布されないようにしてください。
failIfAssemblyHashBlobMissingbooltrueマニフェストにバンドルされたアセンブリハッシュブロブがない場合、違反として処理します。
requireCodeSignature (Windows)boolfalseメイン実行ファイルがコード署名されている必要があります。Windows 専用。
blockVirtualMachine (Windows)boolfalse仮想マシン内部でのゲーム実行をブロックします。Windows 専用。
blockHyperV (Windows)boolfalseHyper-V VMBus の信号を遮断します。WSL2、Docker Desktop、Windows Sandbox のユーザーも防がれる可能性があるため、統制された環境でのみ慎重に使用してください。
blockNetworkProxies (Windows)boolfalseネットワークプロキシ、パケット検査、トラフィック分析ツールと疑われる実行信号を検知します。対戦型のビルドで使用するものの、誤検知の可能性をテストしてください。
blockReverseEngineeringTools (Windows)boolfalse逆アセンブルまたはデバッグツールと疑われる実行信号を検知します。開発/QA 環境とライブ環境を分離して検証してください。
blockSystemMonitorTools (Windows)boolfalseプロセス/システム監視ツールと疑われる実行信号を検知します。一般ユーザー環境での誤検知の可能性を考慮してください。
il2cppHashGameAssemblybooltrueWindows IL2CPP ビルドの GameAssembly.dll をハッシュ検証します。IL2CPP ファイルの保護の最小限の推奨項目です。
il2cppHashGlobalGameManagersbooltrueIL2CPP マニフェストの検証範囲に globalgamemanagers を追加します。
il2cppHashSharedAssetsbooltrueIL2CPP 検証範囲に sharedassets* ファイルを追加します。
il2cppHashSceneFilesbooltrueIL2CPP 検証範囲に level* のような Unity シーンファイルを追加します。
il2cppHashResourcesAssetsboolfalseIL2CPP 検証範囲に resources.assets を追加します。Strict モードに有用ですが、パッチの流れを先にテストしてください。
il2cppAdditionalWatchedFilesList<string>プロジェクトに別途のネイティブペイロードが含まれる場合、追加で監視する Windows IL2CPP の出力ファイルを指定します。
blockEmulator (Android)booltrueAndroid 専用です。エミュレーターまたは未サポートのランタイムシグナルを整合性違反として扱います。QA/エミュレーターテスト中には緩和し、プロダクションビルドではより厳格なポリシーを推奨します。
blockSystemRwMount (Android)booltrueAndroid 専用です。システムパーティションが書き込み可能であったり root 系の mount 状態が見えれば無欠性違反として処理します。
androidShaKeysList<string>期待される APK 署名証明書の SHA-256 フィンガープリントリスト。インストールされた APK がこれらのキーのいずれかで署名されていない場合、検証に失敗します(Android 専用)。
expectedBundleIds (iOS)List<string>許可する iOS Bundle ID リストです。空いていれば Bundle ID の検査をパスします。
excludedAssembliesList<string>ハッシュ検証から除外するアセンブリ名のリスト(.dll 拡張子を除く)。ランタイムに変更されるアセンブリ(例: 生成されたコード)に使用してください。
checkIntegrityWithServer (Pro)boolfalsePro サーバーの Attestation をオンにします。クライアントが nonce を要請し、無欠性の証拠を提出した後、ゲームサーバーまたは OZero サーバーが検証できる署名された OZA トークンを受け取ります。サーバーでは nonce を manifest hash、platform、SDK version、アプリ識別情報と一緒に結びつけて再使用/証拠の取り替えを減らします。
enableManagedVerification (Pro)boolfalse独自のゲームサーバーがないチームのための委任検証オプションです。発行された OZA トークンを OZero サーバーが再び検証し、許可/警告/遮断の結果と短いセッションを返します。SDK はセッションが満了する前に自動的に再検証を試みます。checkIntegrityWithServer がオンになっている必要があります。
requireManagedVerification (Pro)boolfalseオンにすれば委任検証のネットワークの失敗も検証の失敗として処理します。一般的にはオフにしておいてデフォルト(Standard)の保護に自動で切り替わるように置くことをお勧めします。
attestRefreshLeadSeconds (Pro)float300 sOZA トークンの満了前に何秒先に更新を試みるか決めます。0 であれば満了前の先行更新を使用しません。
attestRefreshCooldownSeconds (Pro)float30 sAttestation 更新を試みる間の最小の待機時間です。
manifestSigningPublicKeystringrequireManifestSignature が有効な場合、マニフェスト署名検証に使用される RSA 公開キー(PEM)。
requireManifestSignatureboolfalse整合性マニフェスト自体が manifestSigningPublicKey で署名されているか検証します。
manifestSigningPrivateKeyPathstringOZeroSigningKeysビルドの際に manifest 署名に使用する private key PEM の経路です。Editor 専用であり、プレイヤーのビルドには含まれません。
Pro Strict Attestation は Pro ポリシー(ポータル)で設定できます。このモードでは nonce が提出された manifest hash、platform、SDK version、アプリ識別情報にバインドされ、サーバーは登録されたビルドバージョンと強い無欠性証拠がすべてある場合にのみ OZA トークンを発行します。

Events

Event Description
OnValidationPassed ローカルの整合性チェックが違反なく完了したときに発生します。Pro サーバーの検証(attestation)はまだ進行中である可能性があります。
OnAttestationPassed Pro OZA 検証(attestation)トークンが実際に発行された後にのみ発生します。ゲームサーバーのログイン、PvP、ランキング、財貨の流れは、このイベントまたは AttestationToken.IsValid(nowMillis) で検査して通過した場合にのみ進行してください。
OnValidationFailed 整合性チェックが違反を検知したときに発生します。グローバルな onHackDetected イベントも ModulationType.BuildIntegrity と共にトリガーされます。

RSA 署名キーの生成(ビルド整合性)

ビル드 무결성 (Build Integrity) を有効化し、Require Manifest Signature をオンにした場合、OZero は公開キーに基づく署名で整合性マニフェストが変更されていないか確認します。リリースビルドを作成する前に、Unity エディターでキーペアを必ず生成してください。

マニフェスト署名の動作方式

ビルド時に OZero は 個人キー でアセンブリマニフェストに署名し、その結果の署名をビルドに含めます。ランタイムには OZeroSecurityConfig に保存された 公開キー で署名を検証します。署名が一致しない場合 — つまりマニフェストまたはバイナリが改ざんされた場合 — ゲームはこれを改ざんとみなし、Response Settings に従って対応します。

Build Integrity Manifest Signing UI in the Unity Editor

キーペアを生成する

  1. Unity エディターの Project 窓で OZeroSecurityConfig を選択します。
  2. インスペクターで Build Integrity セクションを展開します。
  3. Require Manifest Signature チェックボックスを有効化します。
  4. Generate Key Pair ボタンをクリックします。
  5. OZero が署名キーペアを生成します。公開キーOZeroSecurityConfig に保存され、個人キー は次のパスに保存されます:
    [ProjectRoot]/OZeroSigningKeys/manifest_private_key.pem
  6. 個人キーの位置を示す確認のダイアログボックスが表示されます。OK をクリックして閉じます。
⚠ 重要 — 個人キーのセキュリティ
  • 個人キーファイルは Unity がビルドに含めないように Assets/ フォルダの 外部 に保存されます。絶対に Assets/ の中に移動しないでください。
  • OZeroSigningKeys/ を直ちに .gitignore に追加してください。個人キーをバージョン管理にコミットすることは深刻なセキュリティリスクです。
  • 個人キーを安全なオフラインの場所(暗号化された USB ドライブ、パスワードマネージャーなど)にバックアップしてください。このファイルを持つ人は誰でも有効なマニフェストを偽造できます。
  • 個人キーを紛失した場合、新しいキーペアを生成する必要があります。新しい公開キーは次のビルドに自動的に含まれます。既存にリリースされたビルドはすべて新しい公開キーでマニフェストの検証に失敗するため、アップデートをデプロイする必要があります。

ユーザー指定の個人キーのパス(CI/CD & チーム環境)

インスペクターの Manifest Signing — Editor Only の下にある Manifest Signing Private Key Path フィールドで個人キーの代替の場所を指定できます。次の2つの状況で有用です:

  • CI/CD パイプライン — 個人キーを CI シークレットとして保存し、ビルド時に経路を注入すれば、ビルドマシンがキーを永続的にディスクに保管しなくても済みます。
  • チーム環境 — キーを共有セキュリティサーバーやシークレットマネージャーに保管し、フィールドをマウントパスとして指定します。リリースビルドを実行するチームメンバーだけがアクセス権限を持てば十分です。

既存のキーペアの検証

ディスクの個人キーと OZeroSecurityConfig に保存された公開キーが一致するか確認するには、Validate Key Pair ボタンをクリックしてください。OZero が個人キーで小規模のテストペイロードに署名し、公開キーで検証します。一致すれば成功メッセージが表示され、一致しない場合は新しいペアを生成する必要があります。

キーペアを再生成すべき場合
  • 個人キーを紛失または流出した場合。
  • Validate Key Pair で不一致を報告する場合(キーが同期されていない場合)。
  • 予定されたセキュリティポリシーの一環として意図的にキーを交換する場合。

再生成後は新しい公開キーが次のビルドに自動的に含まれます。既存にリリースされたビルドは新しい公開キーでマニフェストの検証に失敗するため、アップデートをデプロイする必要があります。

デュアルフィンガープリント無停止キーの回転

Generate Key Pair ボタンを押すと、公開キーが OZeroSecurityConfig に保存され、同じキーを識別する fingerprint が OZeroManifestTrustAnchor.cs にも記録されます。ランタイムにはこの2つの値が合うか確認した後、マニフェストの署名を検証します。値が互いに合わなければマニフェストを信頼しません。

現在のキーと以前のキー

OZeroManifestTrustAnchor.cs には現在使用するキーの fingerprint と、キーの回転期間にのみ一時的に許可する以前のキーの fingerprint を記録できます。普段は現在のキーのみを使用し、新しいキーに交換する時のみ以前のキースロットをしばらく満たしておきます。このようにすれば、新しいビルドをデプロイする間、既存のビルドのユーザーが突然マニフェストの検証に失敗することを減らすことができます。

キーの回転手順

  1. 現在の fingerprint をバックアップします。 Assets/OZeroSDK/Scripts/Security/BuildIntegirity/OZeroManifestTrustAnchor.cs を開いて ExpectedPublicKeyFingerprintHex の値をコピーしておきます。
  2. 以前のキースロットに登録します。 同じファイルの PreviousPublicKeyFingerprintHex に1段階でコピーした値を貼り付けて保存します。
  3. 新しいキーペアを生成します。 OZeroSecurityConfig インスペクターで Generate Key Pair をクリックし、再生成の確認ウィンドウで進行します。新しい公開キーと新しい fingerprint が自動的に更新されます。
  4. 新しいリリースビルドをデプロイします。 新しいマニフェストは新しい個人キーで署名されます。
  5. アップデートの切り替え期間を置きます。 既存のビルドと新しいビルドが一緒に使われる期間には以前のキーも許可する必要があります。ライブゲームでは通常1〜4週間程度を基準に設定します。
  6. 以前のキースロットを空にします。 古いビルドの使用量が十分に低くなった後、PreviousPublicKeyFingerprintHex = "" に戻し、もう一度リリースすると回転が完了します。
なぜ以前のキースロットが必要なのか

ライブサービスでは、すべてのユーザーが同時に新しいバージョンに移行するわけではありません。以前のキースロットをしばらく維持すれば、既存のビルドと新しいビルドが一緒にある間、マニフェストの検証の失敗を減らすことができます。十分な切り替え期間が過ぎた後、以前のキースロットを空ければよいです。

トラブルシュート

ほとんどのキー関連のエラーは、個人キー、OZeroSecurityConfig の公開キー、OZeroManifestTrustAnchor の fingerprint が互いに合わないときに発生します。以下の項目を順に確認してください。

症状 1 — リリースビルドが実行直後に終了する

ExpectedPublicKeyFingerprintHex が空いている可能性があります。解決: Unity エディターで Generate Key Pair を1回実行した後、クリーンビルドしてください。値がすでに満たされているのにも関わらず失敗する場合は、以前のビルドの生成物が残っている可能性があるため、ビルドのフォルダーを空にして再度ビルドしてください。

症状 2 — ビルドの開始直前に "no manifest signing public key is configured" でビルドが中断される

OZeroSecurityConfig.Integrity.ManifestSigningPublicKey が空のときに発生します。解決: インスペクターで OZeroSecurityConfig を開き、Build Integrity セクションの Generate Key Pair をクリックして再度ビルドしてください。

症状 3 — ランタイムのログ: "Manifest signing public key does NOT match the pinned trust anchor fingerprint — APK appears to have been repacked with attacker-controlled keys"

OZeroSecurityConfig の公開キーとコードに記録された fingerprint が合わないときに発生します。解決: Unity エディターで Tools → OZero → Validate Manifest Signing Keys を実行してください。ツールが不一致を報告する場合、Generate Key Pair で新しいキーペアを発行して再度ビルドしてください。配布されたビルドでこのメッセージが表示される場合、APK または実行ファイルが再パッケージされたかも確認する必要があります。

症状 4 — 回転の後、古いビルドのユーザーがマニフェストの検証に失敗する

新しいキーを配布する前に、以前の fingerprint を PreviousPublicKeyFingerprintHex に登録しなかった可能性が高いです。解決: 以前の fingerprint を Previous スロットに入れたホットフィックスビルドをデプロイし、十分な切り替え期間が過ぎた後に Previous スロットを空にしてください。

症状 5 — ローカルのビルドは成功するが、CI のビルドが "private key not found" または誤ったキーで署名される

CI マシンに OZeroSigningKeys/manifest_private_key.pem がないときに発生します。解決: 個人キーを CI Secret に保管し、Unity のビルド直前に同じパスに復元してください。または OZeroSecurityConfigManifest Signing Private Key Path に CI でアクセスできるセキュリティパスを指定してください。すべてのリリースビルドのマシンは同じ個人キーを使用する必要があります。

インストール元の設定

ゲームが承認されたストアまたは経路からインストールされた場合にのみ実行されるように制限します。サイドロードや再パッケージされた APK 방지에 有用です。

フィールド Type デフォルト 説明
Activate Install Source bool true Install Source モジュールを有効化します。
allowGooglePlayStore bool true Google Play ストア経由のインストールを許可します。
allowSamsungGalaxyStore bool false Samsung Galaxy Store 経由のインストールを許可します。
allowAmazonAppstore bool false Amazon Appstore 経由のインストールを許可します。
allowHuaweiAppGallery bool false Huawei AppGallery 経由のインストールを許可します。
allowOneStore bool false ONE Store(韓国)経由のインストールを許可します。
allowXiaomiGetApps bool false Xiaomi GetApps 経由のインストールを許可します。
allowOppoAppMarket bool false OPPO App Market 経由のインストールを許可します。
allowVivoAppStore bool false Vivo App Store 経由のインストールを許可します。
allowADB bool false ADB(Android Debug Bridge)経由のインストールを許可します。内部テスト目的でのみ有効化してください。
allowDetectionFailedboolfalseAndroid installer package の照会や JNI の呼び出しが失敗した時にゲームの実行を許可します。リリースのビルドではオフにすることをお勧めします。
allowUnknownSourcesboolfalse基本のリストやカスタム許可リストにないインストールの出処を許可します。地域ストアの対応が必要な時にのみテストの後使用してください。
enableServerSync (Pro)boolfalse検知された installer package を OZero サーバーに送り、allowlist の検証と監査のログを実行します。Pro 専用です。
customAuthorizedPackages List<string> 追加で許可するインストーラーのパッケージ名(例: com.yourcompany.launcher)。
reportViolationToCallback bool true 許可されていないインストール元が検知された場合、サーバーにレポートを送信します。
logRawInstallerPackage bool true 元のインストーラーパッケージ名をコンソールにログとして出力します。カスタムストアの正しいパッケージ名を識別する開発段階で有用です。

Steam Anti-Piracy の設定

Steam に配布される PC ビルドで Steam の実行の経路、App ID、権限の状態、リリースの設定を確認します。Standard はローカルの検証であり、Steam サーバーを通じたより強い所有権の検証は Pro のサーバー Steam Attestation で提供します。

フィールド Type デフォルト 説明
Activate Steam Anti-PiracycheckboxOffSteam Anti-Piracy の活性化のチェックボックスです。Steam App ID と配布の方式がプロジェクトごとに異なるためデフォルト値は Off です。まず観察/QA モードで状態を確認した後、リリースビルドのポリシーを強化してください。
expectedSteamAppIdint0プロジェクトの Steam App ID です。開発の確認用 AppID 480 を使用した場合、リリースの前に必ず実際の App ID に変えてください。
requireSteamLaunchbooltrueゲームが実行ファイルの直接実行ではなく Steam を通じて開始されたか確認します。開発中の直接実行のテストとリリースポリシーを区分してください。
requireSteamApiInitbooltrueSteam API の初期化の成功可否を確認します。ローカルの開発の実行では Steamworks の設定によって失敗することがあるため、最終的な判定は実際の Steam 配布の経路で確認してください。
requireSubscribedCurrentAppbooltrue現在の Steam アカウントがアプリを所有するか使用の権限を持っているか確認します。この項目はローカルの検証であり、サーバー側の所有権の検証は Pro で実行します。
requiredDlcAppIdsList<int>保護する DLC フローで所有が必要な DLC App ID のリストです。
blockSteamAppIdTxtInReleasebooltrueリリースビルドに開発用 steam_appid.txt が残っていれば失敗処理します。このファイルはローカルの開発の確認用であり、顧客に配布しないでください。
validateSteamApiDllHashboolfalseSteam API DLL のハッシュを既知の SHA-256 値と比較して検証します。
allowFamilySharing / allowFreeWeekend / allowTimedTrialbooltrueSteam の家族の共有、無料の週末、時間制限の体験の権限の状態を許可するか制御します。
enableServerSteamAttestation (Pro)boolfalsePro 専用です。Steam の権限証拠を OZero サーバーに提出してクライアントのローカル結果より強いサーバー側の所有権の検証を実行します。

デバイスバインディング設定

ハードウェア指紋を使用してゲームアカウントを最初のデバイスにバインドします。他のハードウェアへのアカウント移行を検知します。

商用運用目的

デバイスバインディングは Pro の運用レイヤーとして最も有用です。ライセンスをサーバーに登録されたハードウェア指紋と連結することで、危険なデバイスを隔離し、単純なライセンス共有のコストを高め、正当なデバイス変更をライセンス全体のブロックなしにサポートできます。

繰り返しリスクのあるデバイスをブロック

SpeedHack、Injection、Install Source、Build Integrity などのセキュリティイベント証拠を確認した後にお使いください。ブロックされたデバイスは、次回の有効化、登録、検証(verify)、ポリシー(policy)チェックで DEVICE_BLOCKED を受け取ります。

正当なユーザーのリセットをサポート

携帯電話の交換、OS 再インストール、ハードウェア交換、正常な環境変更後に指紋の不一致が発生した場合に Reset Token を使用します。トークンは 5分間有効、1回限りであり、正確なライセンスとデバイスに結び付けられます。

デバイススロットの制御

Pro ライセンスでは maxDevices で登録可能なアクティブなサーバー指紋の数を制限します。ブロックされた指紋は信頼できる再利用スロットではないため、リセットまたは削除はカスタマーサポートの検証後に使用してください。

Reset Token カスタマーサポートのフロー

  1. 一般的なカスタマーサポートの手順に従い、プレイヤーアカウントとリセットの理由を確認します。
  2. Customer Portal → Device Binding で対象のデバイスを見つけ、Reset Token を発行します。
  3. トークンは認証されたカスタマーサポートのチャネルのみで伝達します。長期間残る公開チャットやスクリーンショットに保管しないでください。
  4. ゲームまたはカスタマーサポートの UI はトークンを OZeroDeviceBindingDetector.Instance?.ClearStoredFingerprint(token.Trim()) に渡す必要があります。
  5. SDK がトークンを消費した後、アプリを再起動するか保護の初期化フローに再進入すると、現在のハードウェア指紋が再登録されます。
デバイスバインディングを完璧なハードウェア身元保証機能として宣伝しないでください。OS の初期化、プライバシー設定の変更、ハードウェア交換後にプラットフォーム識別子が変わる可能性があります。商用のライブゲームでは、迂回コストを高める運用統制レイヤーとして説明し、Build Integrity、Injection、SpeedHack、Install Source、サーバー検証と一緒に使用してください。
フィールド Type デフォルト 説明
Activate Device Binding bool true Device Binding モジュールを有効化します。
hardwareChangeTolerance int (0–3) 1 違反をトリガーする前に許容されるハードウェア構成要素の変更回数。0 = 厳格(変更不可)、3 = 寛容(主要ハードウェアの交換)。1 は軽微な OS またはファームウェアの更新を許容するレベルです。
storageKey string "ozero_dfp" 暗号化されたデバイス指紋が保存される PlayerPrefs キー。ゲーム内の既存のキーと衝突する場合にのみ変更してください。
enableServerSync bool false サーバー側の検証のために、デバイス指紋をバックエンドサーバーと同期します。
maxDevices (Pro)int0意図したサーバーサイドのデバイスの限度を文書化する値です。実際の限度はサーバーのライセンスの記録で強制されるため、このローカルの値だけを変えても運用の限度が上がるわけではありません。

スピードハック検出器の設定

Unity の Time.realtimeSinceStartup をネイティブプラットフォームのタイマーおよびオプションで信頼できるウェブ時間ソースと比較して、タイムスケール操作(スピードハック)を検出します。

フィールド Type デフォルト 説明
Activate Speed & Time Hack bool true Speed Hack Detector モジュールを有効化します。
autoStart bool true ゲーム実行時に自動的に検出を開始します。無効にする場合は、OZeroSpeedHackDetector.StartDetection() で手動で開始する必要があります。
checkInterval float 1.0 s 検出器がタイマーをサンプリングして比較する周期(秒)。
requiredDetections int 3 違反がトリガーされる前に必要な連続した異常サンプルの数。不安定なデバイスでの誤検知を減らすには値を上げてください。
ratioTolerance float 0.15 Unity の時間とネイティブタイマーの流れが異常に広がっていないか確認する許容範囲です。デフォルト値を先に使用し、実際のゲーム環境で誤検知の有無を確認した後に調整してください。
maxAllowedRatio float 4.0 正常な範囲を大きく外れた時間の流れを素早く検出するための上限値です。一般的にデフォルト値を維持してください。
detectSlowHack bool true 速度の増加だけでなく、時間を遅くするツール(1.0 - 許容誤差未満の比率)も一緒に検出します。
enableTimeScaleDetection bool true メモリエディターなどによってプログラム的に設定された異常な Time.timeScale 値を検出します。
hackDetectMultiplier float 1.3 強い疑いシグナルをより速く集計するための補正値です。値が低いほど敏感になるため、QA の後に調整してください。
enableThreadTimerCheck bool true バックグラウンドスレッドタイマーを追加の基準クロックとして使用し、メインスレッドのみに影響を与えるハッキングをより困難にします。
useWebTimeValidation bool false webTimeUrl から定期的に現在時刻を取得し、デバイスの時計と比較して、デバイスレベルの時間操作を検出します。
webTimeUrl string 信頼できる時間 API エンドポイント URL(Unix タイムスタンプまたは RFC 2616 Date ヘッダーを返す必要があります)。useWebTimeValidation 有効時に必須です。
webSyncInterval float 15 s ウェブ時間サーバーと同期する周期(秒)。
webRatioTolerance float 0.15 デバイス時間とウェブサーバー時間の差を判断する許容範囲です。ネットワークの遅延と地域の環境を考慮してデフォルト値から検証してください。
timeOffsetTolerance float 60 s 違反のトリガー前に許容されるデバイスとウェブサーバー間の絶対的な時計オフセット(秒)。
focusIgnoreTime float 4 s アプリがフォーカスを取り戻した直後に無視する時間(秒)。OS がアプリを一時停止したときに発生する誤検知を防ぎます。
loadingGraceTime float 6 s アプリの起動やシーンの読み込みなど、正常に遅延が生じる可能性がある区間で誤検知を減らすための初期の緩衝時間です。
lagSpikeIgnore float 0.5 s フレームデルタがこの値を超えるサンプルは破棄されます(時間操作ではなく実際のラグスパイクとみなされます)。
buildFailIfTimeScaleTamperedbooltrue保護の対象のコードがポリシーの外で Time.timeScale を変更するものと見えればビルド/検証の段階で失敗するようにするガードです。
timeScaleTamperExemptionsList<string>一時停止やバレットタイムのように意図的に Time.timeScale を変えるクラス/メソッドのパターンを例外として登録します。
webTimeUrlsstring[]信頼する時間のエンポイントを複数指定できます。複数の応答の成功を要求してウェブ時間の信頼度を高めます。
minSuccessfulEndpointsint2複数のウェブ時間のエンドポイントを使用する時に成功しなければならない最小の応答の数です。
maxConsecutiveFailuresint6ウェブ時間の照会の失敗が何回連続で発生すれば unavailable ポリシーを適用するか決めます。
onWebTimeUnavailableenumWarnOnly信頼するウェブ時間にアクセスできない時に適用するポリシーです。ネットワークの状況をテストした後、厳格なモードに上げてください。
detectTimeHackbooltrue速度の比率の検査の他に、デバイスの時計とウェブ時間の操作の検査をオンにします。
webSyncJitterPercentfloat20%ウェブ時間の同期の周期にランダムな偏差を加え、照会の時点を予測しにくくします。
sustainedLagThresholdfloat0.15繰り返される遅いフレームをチートの証拠ではなく持続的なラグとして分類するための基準です。
sustainedLagGraceDurationfloat3 s持続的なラグやロードの遅延として判断される間、誤検知を減らすための緩衝の時間です。
overloadStrictMultiplierint3反復的な異常のタイミングの条件の後、overload の処理の基準をより厳しく適用する倍数です。
enableRemoteSpeedHackConfig (Pro)boolfalsePro サーバーのポリシーとして Speed & Time Hack 臨界値の一部を遠隔で調整できます。
remoteSpeedHackConfigIntervalfloat300 s遠隔の Speed & Time Hack 設定を新しく受け取る周期です。
enableSignedServerTime (Pro)boolfalse使用可能な場合、署名されたサーバー時間を使用して unsigned 応答の偽造を防ぎます。

Time.timeScale ではなく OZeroTime.timeScale を使用する

Speed & Time Hack モジュールが有効な状態で Time.timeScale を直接変更すると、外部の時間操作に似たシグナルとして扱われる可能性があります。一時停止、スローモーション、カットシーン速度制御、早送り、デバッグ速度調整など、ゲーム側が意図して速度を変える場合は OZeroTime.timeScale を使用してください。

OZeroTime.timeScale は要求値を OZero detector に渡し、detector の想定 game-time scale を更新してから Unity time scale を安全に適用します。これにより SDK は、正当なゲームプレイ上の速度変更と疑わしいランタイム改ざんを区別できます。

using OZeroSDK.Security;

// Correct: the detector knows this is an intentional game-side change.
OZeroTime.timeScale = 0.5f;

// Avoid: this bypasses OZero's expected time-scale tracking.
Time.timeScale = 0.5f;
TimeScaleTamperExemptions は最小限にしてください。直接 Time.timeScale へアクセスせざるを得ない、レビュー済みの adapter script にのみ使用し、それ以外では OZeroTime.timeScale を優先してください。

長時間ロード中の意図しない Watchdog 終了を防ぐ

OZero のネイティブ Watchdog は、Unity のメインスレッドが動作しているかを定期的な heartbeat で確認します。リリースビルドでは、非 Android プラットフォームは約 6 秒、Android は起動猶予後に約 10 秒の heartbeat deadline を使用します。その間に heartbeat が届かない場合、アプリが停止したと判断され、設定された応答ポリシーに従って終了することがあります。

大きなシーンのロード、同期的なアセット解凍、シェーダー warmup、Addressables の準備など、メインスレッドを数秒以上意図的にブロックする正当な処理でも、この状況は発生する可能性があります。

このような信頼できるロード境界は OZeroWatchdog.BeginLoadingGrace(maxGraceMs) で囲んでください。ロード開始時に grace が始まり、scope が dispose されるか End() が呼ばれた瞬間に終了するため、正確なロード時間を事前に知る必要はありません。

using OZeroSDK.Security;
using UnityEngine.SceneManagement;

public void LoadLargeScene()
{
    using (OZeroWatchdog.BeginLoadingGrace(60000))
    {
        SceneManager.LoadScene("Battle", LoadSceneMode.Single);
        // Grace ends as soon as the using scope exits.
    }
}

public void WarmUpLargeAssets()
{
    OZeroWatchdog.RunWithLoadingGrace(() =>
    {
        BuildLargeRuntimeCache();
    }, 60000);
}
注意: Loading Grace を回避策として使わないでください。

Loading Grace は Watchdog deadline だけを限定的に猶予します。通常の監視を避けながらアプリを動かし続けるための無限ループや keep-alive 目的で悪用してはいけません。

1つの大きなブロッキング処理が最大 grace window を超える可能性がある場合は、処理を小さな chunk に分けて順番に実行してください。

または Unity の async/await や Coroutine などの非同期ロードフローを使い、メインスレッドが完全に止まり続けないように実装してください。

物理ハック検出器

コンポーネント方式 — OZeroSecurityConfig には含まれません。
OZeroPhysicsHackDetector は、各プレイヤーオブジェクトごとに独立した検出のしきい値が必要なマルチプレイヤー/MMORPG ゲームのために設計されました。プレイヤーのプレハブに直接コンポーネントを追加し、Inspector でオブジェクトごとに設定を構成してください。スポーンのロジックで Initialize(playerId) を呼び出して検出を有効にしてください。
フィールド Type デフォルト 説明
maxAllowedSpeed float 15 u/s 許容される最大移動速度(Unity ユニット/秒)。ゲームで許容される最大の正当なプレイヤー速度に合わせてチューニングしてください。
distanceTolerance float 2.0 u ネットワークの遅延や物理的な不正確さを補正するための追加の距離許容値。
obstacleLayer LayerMask 壁と障害物を表すレイヤーマスク。ラインキャストによるウォールハックの検出に使用されます。
checkInterval float 0.05 s 物理検証器がプレイヤーの位置と速度をサンプリングする周期(秒)。
maxDeltaTimeCap float 0.1 s 距離の計算に使用されるデルタタイムの上限。ラグスパイクによって不正なテレポートが隠れる現象を防ぎます。

Injection Detector 設定

アセンブリインジェクション、DLL ハイジャック、IL2CPP パッチングなどの無断コードインジェクションを検出します。

フィールド Type デフォルト 説明
Activate Injection & HookingcheckboxOnCode Injection Detector モジュールを有効化します。検出ロジックは全的に Native C++ レイヤーで動作し、追加の設定は必要ありません。
enableServerWhitelist (Pro)boolfalse承認されたオーバーレイやパートナーモジュールを許可できるように、サーバーで信頼モジュールのリストをダウンロードします。
serverWhitelistRefreshIntervalfloat0 sサーバー管理の whitelist ポリシーの更新の周期です。0 であれば開始またはポリシーの初期化の時点にのみ更新します。
requireSignerForNativeWhitelistboolfalseネイティブの whitelist 項目にファイルのハッシュだけでなく署名者の識別情報も要求します。より強力ですがきれいなモジュールの署名データが必要です。
enableRemoteInjectionConfig (Pro)booltruePro サーバーのポリシーとして Injection の検査の臨界値と検査の構成を遠隔で調整できます。
remoteInjectionConfigIntervalfloat300 s遠隔の Injection ポリシーを新しく受け取る周期です。
enableWindowsModuleIdentityScanbooltrueロードされた Windows ネイティブモジュールをスキャンし、ハッシュ/署名者の情報を信頼ポリシーと比較します。
scanIntervalSecondsfloat1 sInjection 検査の基本的な実行の周期です。
windowsModuleIdentityScanIntervalSecondsfloat5 s相対的に重い Windows モジュールの識別のスキャンの別途の周期です。
scanJitterPercentfloat20%検査の周期にランダムな偏差を加え、検査の時点を予測しにくくします。
enableExecutablePrivateMemoryScanbooltrueInjected shellcode やランタイムの patcher が頻繁に使用する実行可能な private memory 領域を感知します。
enableInlineHookScanboolfalse知られたコードの進入点の疑わしい inline patch を感知します。Strict モードで互換性をテストした後オンにする項目です。
enableThreadStartAddressScanbooltrueスレッドの開始のアドレスが信頼モジュールの外の疑わしい位置なのか確認します。
enableExternalProcessHandleScanbooltrue外部のプロセスがゲームプロセスに疑わしい handle を持っているか感知します。
detectionConfidenceThresholdint70複数の Injection 信号を総合した時、違反として確定するための最小の信頼スコアです。
enableWebRuntimeTamperScan (WebGL)booltrueWebGL 専用の軽いブラウザの変調の検査です。Native C++ の保護ではないため補助の信号としてのみ使用してください。
WebGL probesboolstrueWebGL ビルドで DevTools、時計の操作、ネットワークフッキング、WASM フッキング、保存所のフッキング、暗号化 API フッキング検査を制御します。

PlayerPrefs 暗号化

Unity の PlayerPrefs に保存されるデータ(設定、ユーザー環境設定など)を保護するには、PlayerPrefsOZeroSafePlayerPrefs に交換してください。API は同一です。

using OZeroSDK.Security;

// Save a value
OZeroSafePlayerPrefs.SetInt("score", 4200);
OZeroSafePlayerPrefs.SetFloat("volume", 0.8f);
OZeroSafePlayerPrefs.SetString("username", "Hero");

// Read a value
int    score    = OZeroSafePlayerPrefs.GetInt("score", 0);
float  volume   = OZeroSafePlayerPrefs.GetFloat("volume", 1.0f);
string username = OZeroSafePlayerPrefs.GetString("username", "");

セーブファイルの暗号化

セーブファイルを暗号化するには、File.ReadAllText / File.WriteAllText の代わりに OZeroSV_File を使用してください。ファイルは書き込み時に自動的に暗号化され、読み込み時に復号されます。ロード時に改ざんの有無も検査します。

using OZeroSDK.Security;

string path = Application.persistentDataPath + "/save.json";

// Write encrypted file
OZeroSV_File.WriteAllText(path, jsonString);

// Read and decrypt file
string json = OZeroSV_File.ReadAllText(path);
重要: リリース後には developerSecret を変更しないでください。developerSecretOZeroSafePlayerPrefsOZeroSV_File データを保護する基準値の1つです。リリース後にこの値を変更すると、既存のバージョンで保存した保護データが開かなくなる可能性があります。

4 インゲーム変数の保護(Secure Types)

Secure Types は、通常の C# 変数型を暗号化された型に置き換えます。値が Native C++ ヒープに保存されるため、Cheat Engine のようなツールではメモリをスキャンしても見つけることができません。型の名前を変更するだけで、残りのコードはそのまま動作します。

Unity Inspector showing OZeroSV_Int and OZeroSV_Float fields

サンプルコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OZeroSDK.Security;

public class PlayerStats : MonoBehaviour
{
    [SerializeField] OZeroSV_Int Gold = 5000;
    [SerializeField] OZeroSV_Float Speed = 3.5f;
    [SerializeField] OZeroSV_Int HP = 1000;
}

サポートタイプ

既存 OZero 適用後
intOZeroSV_Int
longOZeroSV_Int64
uintOZeroSV_UInt
ulongOZeroSV_UInt64
shortOZeroSV_Short
ushortOZeroSV_UShort
byteOZeroSV_Byte
floatOZeroSV_Float
doubleOZeroSV_Double
decimalOZeroSV_Decimal
boolOZeroSV_Bool
stringOZeroSV_String
Vector2OZeroSV_Vector2
Vector3OZeroSV_Vector3
byte[]OZeroSV_Buffer
Secure Types は OZeroSDK.Security 名前空間を使用します。該当タイプを宣言するスクリプトに using ディレクティブを追加してください。

7 セキュリティイベント処理(選択)

基本的に OZero は脅威を検知すると、設定された対応ポリシーに従ってアプリを終了するかログのみを残します。直接警告画面を表示したり、独自のサーバーログを送信したり、終了直前に保存処理をしなければならない場合はコールバックを登録できます。コールバックは OZeroSecurityEvent を通じて変調タイプ、中断コード、メッセージキー、詳細メッセージ、終了予定の可否を一緒に伝達します。

using UnityEngine;
using OZeroSDK.Security;

public class SecurityHandler : MonoBehaviour
{
    void OnEnable()
    {
        // RegisterUserCallback runs on the user chain only.
        // The built-in default handler runs independently and cannot be silenced.
        OZeroSecurityManager.Instance.RegisterUserCallback(OnThreatDetected);
    }

    void OnDisable()
    {
        OZeroSecurityManager.Instance.UnregisterUserCallback(OnThreatDetected);
    }

    void OnThreatDetected(OZeroSecurityEvent evt)
    {
        // evt contains Type, AbortCode, AbortCodeHex, MessageKey, Message, and WillAbort.
        Debug.LogWarning(
            $"OZero threat: {evt.Type} {evt.AbortCodeHex} {evt.Message}");

        switch (evt.Type)
        {
            case ModulationType.SpeedHack:
                // e.g. kick the player, show warning, report to server
                break;

            case ModulationType.BuildIntegrity:
                // evt.WillAbort is usually true for fatal build integrity violations.
                break;

            case ModulationType.Injection:
                break;
        }

        if (evt.WillAbort)
        {
            // Last chance to flush your own analytics or save state.
        }
    }
}

OZeroSecurityEventModulationTypeOZeroAbortCode の全体リストは API レファレンスに文書化されています。

evt.WillAbort が true であれば現在の対応ポリシー上、コールバック以降にアプリが終了されます。この時は独自の analytics flush や保存処理のみを短く実行してください。
検知イベントの伝達フロー

脅威が検知されると、OZero はまず SDK の基本の対応ポリシーを適用し、プロジェクトで登録したコールバックとインスペクターのイベントにも同じセキュリティイベントを伝達します。直接警告画面を表示したりサーバーログを残したい場合はコールバックを登録してください。アプリの終了の可否は Config Dashboard の Response 設定と evt.WillAbort 値で確認できます。

次のステップ

これで OZero の核心の保護機能が実行中です。API レファレンスですべてのクラス、メソッド、設定オプションを詳しく確認してみてください。