全データ暗号化
スクリプト、立ち絵、CG、音声、動画、フォント、翻訳、設定をすべて暗号化コンテナに格納し、実行中のエンジン内部でのみ復号するため、ディスク上に平文のアセットを残さない
スクリプト、立ち絵、CG、音声、動画、フォント、翻訳、設定をすべて暗号化コンテナに格納し、実行中のエンジン内部でのみ復号するため、ディスク上に平文のアセットを残さない
Ren'Py ランチャーが生成した配布用ビルドや .zip アーカイブを直接処理し、プロジェクトのソースや既存の開発フローを変更する必要がない
ビルドごとに異なる保護が生成されるため、特定の作品やバージョンに対する解析結果を他のビルドに流用できない
そのまま利用でき、任意の renmori.toml でチャンクサイズ、除外リスト、ロック、保護強度、鍵の取得元を制御可能
機械可読な JSON 結果と明確な終了コードを出力し、renmori verify をパイプラインのゲートとして配布用ビルドごとにアーカイブ化と検証を自動化
商用作品を含め、あらゆる Ren'Py ゲームの保護は無料であり、ランタイムはゲームと共に無償で再配布可能
以下のデータはすべて RenMori リポジトリのマイルストーン検証記録とコンテナ形式仕様に基づくものであり、各項目に測定または算出の条件を記載しています。
ベースラインの Python 参照リーダーは、数 MB 規模のアセットに対してエンジン内で約 74 MB/s のシーケンシャル復号スループットを記録しており、リアルタイムの動画・音声デコードに必要な数 MB/s を大きく上回ります。製品版のネイティブ復号器はチャンクごとの Python 呼び出しのオーバーヘッドを排除していますが、そのスループットは個別には未測定です。
模式図(縮尺は実際と異なる)
offset(i) = data_offset + i × (chunk_size + 16)各チャンクは 16 バイトの GCM 認証タグを伴って個別に暗号化され、サイズオーバーヘッドは 16 / 65,536 ≈ 0.024% です。これに加えて 64 バイトのヘッダーと暗号化インデックスが付属します。チャンク間隔が固定されているため任意の位置へ直接シークでき、大きなファイルは全体をメモリに読み込むことなくストリーミングで復号されます。
game/archive.rpa平文game/images.rpa平文game/script.rpyc平文game/script.rpy平文game/renmori.rmc暗号化コンテナgame/renmori.rpeランタイムローダー保護後のディスク上には平文のアーカイブ、.rpyc、.rpy は一切残らず、すべてのアセットは暗号化された状態でコンテナ内にのみ存在します。ランタイムが追加で生成するのは cache/ ディレクトリのみです。
| ツール | 実測結果 |
|---|---|
unrpa | コンテナを拒否:RPA アーカイブではないため、バージョンの自動判別に失敗 |
unrpyc | 対象なし:デコンパイル可能な .rpyc や .rpy がディスク上に存在しない |
PNG検出なしRENPY RPC2検出なしOggS検出なしRIFF検出なしOTTO検出なしzip検出なしギガバイト級のコンテナに対するシグネチャカービングでは、マルチバイトのファイルシグネチャは一切検出されず、統計的に想定される 3 バイトの偶然一致のみが残り、いずれも復元できませんでした。コンテナはランダムデータと区別できません。
| アセット種別 | 供給経路 | 結果 |
|---|---|---|
| 画像:立ち絵、CG(PNG/JPG) | バッファ | バイト単位で一致 |
| 音声(Opus/OGG) | バッファ | バイト単位で一致 |
| スクリプト(.rpyc) | バッファ | バイト単位で一致 |
| 翻訳(tl/<language>/) | バッファ | バイト単位で一致 |
| フォント、小(TTF) | バッファ | バイト単位で一致 |
| フォント、数 MB 規模(TTF) | ストリーミング | バイト単位で一致 |
| 動画、大容量(WebM/OGV/AVI) | ストリーミング | バイト単位で一致 |
すべてのアセット種別をエンジン内の実際の renpy.loader で復号し、元ファイルの SHA-256 と照合しました。