69 lines
2.4 KiB
Swift
69 lines
2.4 KiB
Swift
|
|
import Foundation
|
|||
|
|
import SwiftUI
|
|||
|
|
|
|||
|
|
/// Минимальный держатель identity для первой итерации.
|
|||
|
|
/// Полные derived keys (ML-DSA + ML-KEM) — Phase 2 (FFI к Rust).
|
|||
|
|
struct Identity: Equatable {
|
|||
|
|
let masterSeed: Data
|
|||
|
|
let accountIdHex: String
|
|||
|
|
let mnemonic: String?
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@MainActor
|
|||
|
|
final class IdentityManager: ObservableObject {
|
|||
|
|
@Published private(set) var identity: Identity?
|
|||
|
|
|
|||
|
|
private let storageKey = "MontanaIdentity_v1"
|
|||
|
|
|
|||
|
|
init() {}
|
|||
|
|
|
|||
|
|
/// Загрузить existing identity из Keychain (если есть).
|
|||
|
|
func loadIfPresent() {
|
|||
|
|
guard let data = KeychainStore.read(key: storageKey),
|
|||
|
|
let stored = try? JSONDecoder().decode(StoredIdentity.self, from: data) else {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
identity = Identity(
|
|||
|
|
masterSeed: stored.masterSeed,
|
|||
|
|
accountIdHex: stored.accountIdHex,
|
|||
|
|
mnemonic: nil
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Создать новую identity из случайной мнемоники.
|
|||
|
|
func createNew() throws -> String {
|
|||
|
|
let mnemonic = Mnemonic.generate()
|
|||
|
|
try install(mnemonic: mnemonic)
|
|||
|
|
return mnemonic
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Восстановить identity из существующей мнемоники.
|
|||
|
|
func restore(from mnemonic: String) throws {
|
|||
|
|
try install(mnemonic: mnemonic)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// Стереть identity локально (для тестов / переустановки).
|
|||
|
|
func wipe() {
|
|||
|
|
KeychainStore.delete(key: storageKey)
|
|||
|
|
identity = nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private func install(mnemonic: String) throws {
|
|||
|
|
let masterSeed = try Mnemonic.decodeAndDerive(mnemonic: mnemonic)
|
|||
|
|
// Placeholder account_id = SHA-256("mt-account-placeholder" || masterSeed[0..16])
|
|||
|
|
// Реальный account_id = SHA-256("mt-account" || pubkey_suite || ml_dsa_pubkey) — Phase 2
|
|||
|
|
let accountIdHex = HashUtil.sha256Hex(prefix: "mt-account-placeholder", body: masterSeed.prefix(16))
|
|||
|
|
|
|||
|
|
let stored = StoredIdentity(masterSeed: masterSeed, accountIdHex: accountIdHex)
|
|||
|
|
let data = try JSONEncoder().encode(stored)
|
|||
|
|
KeychainStore.write(key: storageKey, value: data)
|
|||
|
|
|
|||
|
|
identity = Identity(masterSeed: masterSeed, accountIdHex: accountIdHex, mnemonic: mnemonic)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private struct StoredIdentity: Codable {
|
|||
|
|
let masterSeed: Data
|
|||
|
|
let accountIdHex: String
|
|||
|
|
}
|