Python API リファレンス

bootstrap()、open_model()、コンパイル版で自動的に働くゲート、そしてコードで処理が必要になりうる例外について。

あなたが実際に使うランタイム API は、トップレベルの関数 2 つだけです — 有効化やライセンス処理、ゲートそのものといった残りのすべては、その背後で行われます。インポートしたり使ったりするデコレータはありません — magiclock build がライセンスゲートのチェックをコンパイル後のすべてのモジュールへ自動で挿入します(コンパイルビルドを参照)。

magiclock.bootstrap()

python
magiclock.bootstrap(vault_dir=None, *, app_version="1.0.0") -> MagicLockRuntime

現在のプロセスに対して、このマシンの有効化状態に基づきライセンスゲートを起動します。magiclock build の成果物では、この呼び出しはエントリモジュールに自動で挿入されます — 自分で呼び出す必要があるのは、コンパイルしない通常のスクリプトで、最初の open_model() 呼び出しより前に呼ぶ場合のみです。

  • vault_dir — ローカルの有効化状態の保存場所を上書きします。通常は必要ありません。
  • app_version — ライセンスが設定する max_app_version と照合されます。リリースをバージョン単位でロックする場合に関係します。
  • ランタイムオブジェクトを返します(直接必要になることはほとんどなく、大半のコードは副作用のためだけに bootstrap() を呼び出します)。
  • このマシンがまだ有効化されていない場合、または有効化情報は存在するがこのマシンに対して無効な場合に例外を送出します(下記の「処理が必要になりうる例外」を参照)。

magiclock.open_model()

python
magiclock.open_model(path, *, vault_dir=None, passphrase=None, key=None) -> bytes

protect-model で生成された .enc エンベロープを復号し、平文のバイト列を返します — メモリ上にのみ存在し、ディスクに書き込まれることはありません。

  • path.enc ファイルへのパス。
  • passphrase / key — 二要素(--lock-passphrase)またはポータブル(--no-bind-machine)の成果物向け。単純なマシンロック形式の場合は省略します。
  • マシンロック形式の成果物では、事前に bootstrap() が実行されている必要があります。
python
import magiclock

magiclock.bootstrap()
weights = magiclock.open_model("model.onnx.enc")

コンパイル版のゲート

呼び出すべき関数やデコレータはありません — magiclock build がソースツリーを走査し、コンパイル前にすべてのモジュールへゲートチェック(python_protect ケーパビリティの確認)を 1 つずつ挿入します。

python
# あなたのソースコード。あなた自身は変更しません:
def export_report(data: str) -> bytes:
    ...

# `magiclock build` が実際にコンパイルする内容(概念的には):
current_runtime().require_feature("python_protect")

def export_report(data: str) -> bytes:
    ...

このチェックは各モジュールにつき一度だけ、プロセスがそのモジュールを最初にインポートしたタイミングで実行されます — 呼び出しごとではありません。1 つの共有された削除可能なデコレータの背後に集約されるのではなく、コンパイルされたすべてのモジュールへ織り込まれているため、攻撃者はモジュールを 1 つずつ見つけて patch する必要があります。エントリではないモジュールの失敗は通常の例外として伝播します(ライブラリとしてインポートされる可能性があるため)。エントリモジュールの失敗は、それがないと他の何も動かないため、簡潔なメッセージを表示してから終了します。

処理が必要になりうる例外

bootstrap()open_model() は、「まだ有効化されていない」から「この成果物は期限切れ」まで、さまざまな状況で例外を送出します。多くの統合コードでは、広く例外を捕捉し、例外のクラス名で分岐します。

python
try:
    magiclock.bootstrap()
    data = magiclock.open_model("model.onnx.enc")
except Exception as exc:
    name = type(exc).__name__
    if name == "NotActivatedError":
        ...  # this machine hasn't been activated — run `magiclock activate`
    elif name == "TrialExpiredError":
        ...  # the artifact's expiry window has passed
    else:
        raise
例外発生する状況
NotActivatedErrorこのマシンで有効化が見つからない — magiclock activate を実行してください(または CLI に初回暗号化時の自動有効化を任せてください)。
VaultLockedErrorここではローカルの有効化状態を開けない — マシンが違うか、ボルトファイルが移動/改変されています。この 2 つのケースは設計上区別できません。セキュリティモデルを参照してください。
TrialExpiredError--trial--expires-in--expires-at のいずれかを指定した成果物が、復号可能な期間を過ぎています。
SubscriptionExpiredErrorプランの期限が切れています。これは新規の暗号化のみをブロックし、復号側で送出されることは一切ありません。
SubscriptionInvalidErrorサブスクリプションの認証情報が、必要な箇所で欠落している、形式が不正である、または署名検証に失敗しています。
PortableFormatErrorポータブル(--no-bind-machine)エンベロープの形式が不正、またはサポート対象外のバージョンです。
PortableKeyErroropen_model()/run --key に渡したパスフレーズまたはキーが、ポータブル成果物と一致しません。
DebuggerDetectedError復号処理の境界でデバッガのアタッチが検出されました。
RuntimeNotInitializedErrorfrom magiclock_host.errors import RuntimeNotInitializedErrorこのプロセスで bootstrap() が実行される前に、ゲートされたモジュールのチェックが実行されました。

互換性に関する注意

.pya/.enc エンベロープには、それを生成した CPython のメジャー・マイナーバージョンが埋め込まれています。3.12 で暗号化した成果物は 3.13 では読み込めません — 1 つの成果物を複数の Python バージョンにまたがって出荷するのではなく、インタプリタをアップグレードしたら protect/protect-model を再実行してください。