Python API 레퍼런스
'bootstrap(), open_model(), 컴파일 강력 보호에서 자동으로 동작하는 게이트, 그리고 코드에서 처리해야 할 수도 있는 예외들.'
직접 작성해서 호출하는 런타임 API는 최상위 함수 두 개뿐입니다 — 그 외 나머지(활성화, 라이선싱, 게이트 자체)는 모두 이들 뒤에서 일어납니다. import하거나 사용할 데코레이터는 없습니다 — magiclock build가 라이선스 게이트 검사를 컴파일된 모든 모듈에 자동으로 삽입합니다(컴파일 빌드 참고).
magiclock.bootstrap()
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()
magiclock.open_model(path, *, vault_dir=None, passphrase=None, key=None) -> bytesprotect-model이 만든 .enc 봉투를 복호화하고 평문 바이트를 반환합니다 — 오직 메모리에만 존재하며 디스크에 기록되지 않습니다.
path—.enc파일 경로.passphrase/key— 2단계(--lock-passphrase) 또는 포터블(--no-bind-machine) 산출물용. 단순 머신 잠금 산출물이라면 생략하세요.- 머신 잠금 산출물의 경우 먼저
bootstrap()이 실행되어 있어야 합니다.
import magiclock
magiclock.bootstrap()
weights = magiclock.open_model("model.onnx.enc")컴파일 강력 보호의 게이트
호출해야 할 함수나 데코레이터가 없습니다 — magiclock build가 소스 트리를 순회하며, 컴파일하기 전에 모든 모듈에 게이트 검사(python_protect 역량 확인)를 하나씩 삽입합니다.
# 여러분의 소스 코드, 여러분이 직접 바꾸는 것은 없습니다:
def export_report(data: str) -> bytes:
...
# `magiclock build`가 실제로 컴파일하는 내용(개념적으로는):
current_runtime().require_feature("python_protect")
def export_report(data: str) -> bytes:
...이 검사는 각 모듈당 한 번, 프로세스가 그 모듈을 처음 import할 때 실행됩니다 — 호출마다 실행되는 것이 아닙니다. 삭제 가능한 하나의 공유 데코레이터 뒤에 몰려 있는 대신 컴파일된 모든 모듈에 짜여 들어가 있기 때문에, 공격자는 모듈을 하나씩 찾아서 patch해야 합니다. 진입 모듈이 아닌 모듈의 실패는 일반적인 예외로 그대로 전파됩니다(라이브러리로 import될 수 있기 때문입니다). 진입 모듈의 실패는 그것 없이는 다른 어떤 것도 실행될 수 없으므로, 깔끔한 메시지를 출력하고 종료합니다.
처리해야 할 수도 있는 오류
bootstrap()과 open_model()은 "아직 활성화되지 않음"부터 "이 산출물이 만료됨"까지 다양한 상황에서 예외를 발생시킵니다. 대부분의 통합에서는 넓게 잡아서 예외 클래스 이름으로 분기합니다.
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 | 로컬 활성화 상태를 여기서 열 수 없음 — 잘못된 머신이거나, 볼트 파일이 이동/변조되었습니다. 이 두 경우는 설계상 구분할 수 없습니다. 보안 모델 참고. |
TrialExpiredError | --trial, --expires-in, --expires-at 산출물이 복호화 가능 기간을 지났음. |
SubscriptionExpiredError | 플랜이 만료됨. 이는 오직 새로운 암호화만 막으며, 복호화 경로에서는 결코 발생하지 않습니다. |
SubscriptionInvalidError | 구독 자격 증명이 필요한 곳에 없거나, 형식이 잘못되었거나, 서명 검증에 실패함. |
PortableFormatError | 포터블(--no-bind-machine) 봉투가 손상되었거나 지원하지 않는 버전임. |
PortableKeyError | open_model()/run --key에 전달한 패스프레이즈 또는 키가 포터블 산출물과 일치하지 않음. |
DebuggerDetectedError | 복호화 경계에서 디버거가 연결되어 있음이 감지됨. |
RuntimeNotInitializedError(from magiclock_host.errors import RuntimeNotInitializedError) | 이 프로세스에서 bootstrap()이 실행되기 전에 게이트가 걸린 모듈의 검사가 먼저 실행됨. |
호환성 참고 사항
.pya/.enc 봉투는 이를 생성한 CPython 메이저/마이너 버전을 내부에 담고 있습니다. 3.12에서 암호화된 산출물은 3.13에서 로드되지 않습니다 — 인터프리터를 업그레이드한 뒤에는 하나의 산출물을 여러 Python 버전에 걸쳐 사용하려 하지 말고 protect/protect-model을 다시 실행하세요.