Section 10/171 menit

10. Model Encryption dan Protection

10. Model Encryption dan Protection

Model ML adalah aset berharga yang bisa di-reverse engineer. Core ML menyediakan enkripsi model untuk melindungi IP.

Model Access Control (iOS 15+)

swift
// Enkripsi model dengan MLModelConfiguration
let config = MLModelConfiguration()

// Tentukan siapa yang boleh akses model ini
// .default: tidak terenkripsi
// .deviceOnly: model hanya bisa dipakai di device saat ini (tidak bisa copy ke device lain)
// .deviceWithPasscode: perlu passcode untuk decrypt

// Model Access Control dikonfigurasi saat deploy via CoreML Tools atau Xcode
// Di app, load model terenkripsi seperti biasa — sistem otomatis decrypt

// Untuk model yang di-download dari server dengan enkripsi:
func loadEncryptedModel(from url: URL, decryptionKey: MLModelEncryptionKey) async throws -> MLModel {
    let config = MLModelConfiguration()
    // key di-provide saat runtime, tidak di-bundle di app
    return try await MLModel.load(contentsOf: url, configuration: config)
}

// Enum MLModelEncryptionKey tidak perlu diinstansiasi manual oleh developer —
// sistem menangani ini via Secure Enclave

Model Tidak Disertakan di App Bundle

Untuk model yang sangat sensitif:

swift
// Pattern: download model dari server saat pertama run
// Model tidak ada di app bundle — tidak bisa di-extract dari IPA

final class ModelDeploymentManager {
    private let modelServerURL: URL
    private let modelVersion: String

    var localModelURL: URL? {
        let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let url = docs.appending(component: "v\(modelVersion).mlmodelc")
        return FileManager.default.fileExists(atPath: url.path) ? url : nil
    }

    func ensureModelAvailable() async throws -> URL {
        if let local = localModelURL { return local }

        // Download model
        let (downloadURL, response) = try await URLSession.shared.download(from: modelServerURL)
        guard let httpResponse = response as? HTTPURLResponse,
              httpResponse.statusCode == 200 else {
            throw DeploymentError.downloadFailed
        }

        // Compile
        let compiledURL = try await MLModel.compileModel(at: downloadURL)

        // Pindahkan ke Documents
        let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let targetURL = docs.appending(component: "v\(modelVersion).mlmodelc")
        try? FileManager.default.removeItem(at: targetURL)
        try FileManager.default.moveItem(at: compiledURL, to: targetURL)

        return targetURL
    }

    enum DeploymentError: Error { case downloadFailed }
}