import Foundation /// ClearKey kids/keys zoals Android `buildClearKeyLicenseJson` (hex 32 + GUID-endianness). struct ClearKeyKeyMap { /// kid-hex (lowercase, 32 chars) → key bytes (16) private let keysByKid: [String: Data] init(entries: [ClearKeyEntry]) { var map: [String: Data] = [:] for entry in entries { guard let kid = Self.hex16(entry.kid), let key = Self.hex16(entry.key) else { continue } let kidHex = kid.map { String(format: "%02x", $0) }.joined() map[kidHex] = key let swapped = Self.swapUuidEndianness(kid) let swappedHex = swapped.map { String(format: "%02x", $0) }.joined() if swappedHex != kidHex { map[swappedHex] = key } } keysByKid = map } var isEmpty: Bool { keysByKid.isEmpty } /// Eerste key (streams hebben meestal één kid/key-paar). var primaryKey: Data? { keysByKid.values.first } func key(forKid kid: Data) -> Data? { guard kid.count == 16 else { return primaryKey } let hex = kid.map { String(format: "%02x", $0) }.joined() if let k = keysByKid[hex] { return k } let swapped = Self.swapUuidEndianness(kid) let swappedHex = swapped.map { String(format: "%02x", $0) }.joined() return keysByKid[swappedHex] ?? primaryKey } static func sanitizeHex(_ raw: String) -> String { raw.trimmingCharacters(in: .whitespacesAndNewlines) .replacingOccurrences(of: "0x", with: "", options: .caseInsensitive) .replacingOccurrences(of: "-", with: "") .replacingOccurrences(of: ":", with: "") .replacingOccurrences(of: " ", with: "") .lowercased() } static func hex16(_ raw: String) -> Data? { let clean = sanitizeHex(raw) guard clean.count == 32, clean.allSatisfy({ $0.isHexDigit }) else { return nil } var out = Data(capacity: 16) var i = clean.startIndex while i < clean.endIndex { let j = clean.index(i, offsetBy: 2) guard let b = UInt8(clean[i.. Data { guard b.count == 16 else { return b } return Data([ b[3], b[2], b[1], b[0], b[5], b[4], b[7], b[6], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], ]) } }