iOSDC Japan 2021 day2, 20min Talk https://fortee.jp/iosdc-japan-2021/proposal/889c9c50-fa76-4b54-a4f5-04ec99cc87ba
• AVPlayerについて • HTTP Live Streamingの仕組み • コンテンツ保護は何のため? • AES-128による暗号化配信 • FairPlay Streaming • マルチプラットフォームで動画ストリームを保護するには
AVPlayerͰ͖ͪΜͱίϯςϯπอޢߦ ઍय़ʢͳΊ͖ ͪΔʣTwitter, GitHub @RidwyStreaming Client Team, גࣜձࣾ AbemaTViOSDC JAPAN 2021, day2 (9/19)
View Slide
ܦྺגࣜձࣾϐΫηϥ 2005 ~ 2015 TVνϡʔφʔ, Χϝϥ, ը૾ॲཧMac, iPhoneͰσδΛݟΔͨΊͷΞϓϦͳͲΛ୲גࣜձࣾαΠόʔΤʔδΣϯτ 2015 ~Amebaϒϩά iOSΤϯδχΞAbemaTV Streaming Client Team
• ৽͍͠ະདྷͷςϨϏʮABEMAʯ• ΠϯλʔωοτςϨϏہʢ2015։ہʣ• 20Ҏ্ͷνϟϯωϧ, VOD, ଞ ͞·͟·ͳࢹௌܗଶ• ੜதܧ൪੍࡞ख͕͚ΔגࣜձࣾAbemaTV
Streaming Client Teamʹ͍ͭͯ• ABEMAଟ͘ͷϓϥοτϑΥʔϜΛαϙʔτ iPhone, Apple TV, Android, Android TV, Web, IPTV, … • ֤ϓϥοτϑΥʔϜͷ࠶ੜΫϥΠΞϯτʹྗ͠ɺࢹௌମݧΛ୲อɾ্͢ΔઐνʔϜ• ϓϨΠϠʔͷ࣮, ࢹௌ࣭ͷࢹ, ৽ٕज़ͷPoC
ΞδΣϯμ AVPlayerͰ͖ͪΜͱίϯςϯπอޢ• AVPlayerʹ͍ͭͯ• HTTP Live StreamingͷΈ• ίϯςϯπอޢԿͷͨΊʁ• AES-128ʹΑΔ҉߸Խ৴• FairPlay Streaming• ϚϧνϓϥοτϑΥʔϜͰಈըετϦʔϜΛอޢ͢Δʹ
AVPlayerAppleͷϓϥοτϑΥʔϜͰө૾ɾԻΛ࠶ੜ͢ΔϓϨΠϠʔϩʔΧϧͷϑΝΠϧ͚ͩͰͳ͘ɺϦϞʔτͷϑΝΠϧετϦʔϛϯά࠶ੜՄೳ• ϝσΟΞΛѻ͏AVFoundation.frameworkʹ࣮͞Ε͍ͯΔ• AVFoundation·ͣiOSͰ։ൃ͞Εɺ2011ʹMacʹҠ২• ಈըͳͲͷٕज़ͷਐาͱͱʹݱࡏ׆ൃʹ։ൃ͞Ε͍ͯΔAVFoundation
HTTP Live Streaming (HLS)AVPlayerͰ࠶ੜͰ͖ΔετϦʔϛϯάܗࣜ• Live, VODͷͲͪΒʹରԠ• HTTPΛར༻͢ΔͨΊεέʔϥϏϦςΟʹ༏ΕΔ• Adaptive Bit Rate (ABR) ճઢঢ়گʹΑΓ࠷దͳϏοτϨʔτͷετϦʔϜʹεΠονՄೳ• Έ্ɺ2, 3ඵҎԼͷԆ৴࣮ݱग़དྷͳ͔͕ͬͨɺ Low Latency HLSͷొʹΑΓෆՄೳͰͳ͘ͳͬͨAppleʹΑͬͯ։ൃ͞ΕɺRFC8216ͱͯ͠ެ։AndroidϒϥβͰ࠶ੜՄೳಛ
HTTP Live StreamingM3U8ϓϨΠϦετϝσΟΞηάϝϯτ TS or fMP4ϓϨΠϠʔϓϨΠϦετͷதʹهࡌ͞Ε͍ͯΔηάϝϯτΛ্͔Β࿈ଓͯ͠࠶ੜରԠCODEC: HEVC or H.264, AAC or AC-3
M3U8ϓϨΠϦετͷྫ#EXTM3U#EXT-X-TARGETDURATION:10#EXTINF:9.009,http://media.example.com/first.ts#EXTINF:9.009,http://media.example.com/second.ts#EXTINF:3.003,http://media.example.com/third.ts
Adaptive Bit Rate (ABR)ϚελʔϓϨΠϦετ = ଳҬ͝ͱͷϝσΟΞϓϨΠϦετΛෳؚΉϓϨΠϦετ#EXTM3U#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=200000gear1/prog_index.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=311111gear2/prog_index.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=484444gear3/prog_index.m3u8ετϦʔϜͷ࠷େϏοτϨʔτ (bps)
Adaptive Bit Rate (ABR)ϓϨΠϠʔճઢঢ়گʹԠͯ͡࠷దͳετϦʔϜʹεΠον͠ͳ͕Β Β͔ͳ࠶ੜΛଓ͚Δి͕ѱ͘ͳͬͯདྷͨͧʁ ը࣭ʹΓସ͑ͯ͠ͷ͝͏͓ɺվળͯ͠དྷͨߴը࣭ʹͬͨʂ😃LowHigh
ίϯςϯπอޢԿͷͨΊʁ
ίϯςϯπอޢͷඞཁੑΞφϩάഔମͷίϯςϯπίϐʔ͢Δͱ࣭͕ྼԽ͢Δ• ίϐʔͷՁ͕͍ͷͰஶ࡞ݖཧͷඞཁੑߴ͘ͳ͔ͬͨσδλϧίϯςϯπશͳίϐʔ͕Մೳ• ւ൛ͷൢച, ࡞ͷվม, …• ੍࡞ऀɾݖརऀ͕·ͳ͍ܗͰফඅ͞ΕΔͷΛ͙Έ͕ඞཁ
͠ɺಈը৴ͰԿ͠ͳ͔ͬͨΒʁURLΛ͍ͬͯΕಈըΛݟΒΕΔͷͰ ʮ࡞Λߪೖͯ͠Β͏ʯͱ͍͏ϏδωεϞσϧཱ͕͠ͳ͍͓ۚͷ͚ͩͰͳ͘…• ৴ଆʮձһݶఆίϯςϯπΛ৴͠Α͏ʂʯˠ ୭ͰݟΒΕΔΑʁ• ग़ԋऀʮxxͷ൪ʹग़ԋ͠·ͨ͠ʂʯˠ ࣮࣭ɺશੈքͰϑϦʔૉࡐԽ͋·Γָ͘͠ͳ͍ੈք
༷ʑͳίϯςϯπอޢͷख๏ΞΫηεํ๏Λ੍ݶIP੍ݶ, υϝΠϯ੍ݶ, ॺ໊͖URL, ...ίϯςϯπΛ҉߸Խɹ҉߸Խ৴, DRM৴, ...
DRMσδλϧίϯςϯπͷஶ࡞ݖཧٕज़Digital Rights ManagementίϯςϯπΛ҉߸Խͯ͠कΔอޢ͞Εͨܦ࿏ͰͷΈө૾ԻΛ࠶ੜ࡞͕Ͳ͏ΘΕΔ͖͔Λنఆ͠ཧ͢Δ
DRMͷಛఆͷαʔϏεڥʹґଘ• DRMίϯςϯπΛར༻Ͱ͖ΔͷɺͦͷίϯςϯπΛߪೖͨ͠αʔϏεͷΈͰ͋Δ͜ͱ͕ଟ͍• ߪೖͨ͠ίϯςϯπΛӬԕʹར༻Ͱ͖Δอূͳ͍ ిࢠॻ੶ͷετΞ͕Ϋϩʔζͨ͠Βʁ େྔͷίϯςϯπΛߪೖͨ͠ΞΧϯτ૬ଓͰ͖Δʁ ར༻ํ๏Λنఆ͢ΔͷͳͷͰɺ͍ʹ͘͞ʹܨ͕Γ͍͢• Ωπ͗͢Ε੍ݶʹͳΓɺͻͲ͍߹ফඅऀͷݖརͷ৵ʹͳΔɻ ࡞Λ࠷େݶʹָ͠ΊΔઃܭͰ͋Δ͜ͱ͕େ
࡞Λ࠷େݶʹָ͠ΊΔઃܭ͕େ
҉߸Խͷجૅࣝڞ௨伴҉߸ಉ͡伴Ͱ҉߸Խɾ෮߸ԽData🔐
ϒϩοΫ҉߸େ͖ͳσʔλΛ҉߸Խ͢ΔࡍɺϒϩοΫʹ͚ͯ҉߸ԽBlock🔒҉߸ԽͷجૅࣝBlock🔒Block🔒Block🔒Block🔒🔑
҉߸ԽͷجૅࣝAES (Advanced Encryption Standard)• දతͳڞ௨伴ϒϩοΫ҉߸• ϒϩοΫ 128bit• ԿϏοτͷ伴Λ༻͍Δ͔ʹΑͬͯ AES-128, AES-192, AES-256ͱදه͞ΕΔ
BlockBlock🔑🔒҉߸ԽͷجૅࣝϒϩοΫ҉߸ͷ҉߸ར༻ϞʔυCBC (Cipher Block Chaining) Ϟʔυ෮߸ԽʹॳظϕΫτϧ(IV)ͱ伴͕ඞཁIVBlockBlock🔑🔒BlockBlock🔑🔒ॳظϕΫτϧXOR XOR XOR
҉߸ԽͷجૅࣝϒϩοΫ҉߸ͷ҉߸ར༻ϞʔυCTR (Counter) ϞʔυCTR BlockBlock🔑🔒XORCTR🔒CTR+1 BlockBlock🔑🔒XORCTR+1🔒CTR+2 BlockBlock🔑🔒XORCTR+2🔒҉߸Խɾ෮߸ԽͱʹฒྻԽ͕Մೳ
҉߸Խͷجૅࣝެ։伴҉߸• ڞ௨伴҉߸伴Λ͍͔ʹ҆શʹ૬खʹ͔͕͢՝ → ͦΕͳΒ҉߸Խͱ෮߸Խͷ伴Λผʹ͢Ε͍͍͡Όͳ͍ ҉߸ԽͰ͖Δ͚ͩͷ伴͕όϨͯͳ͍͠ɺͳΜͳΒެ։ͯ͠🙆 • ڞ௨伴҉߸ͱൺͯॲཧ͕ॏ͍ͷͰେ༰ྔσʔλʹ͔ͳ͍ → େ༰ྔσʔλΛڞ௨伴҉߸Ͱ҉߸Խͯ͠ɺ伴Λެ։伴҉߸Ͱ͢
҉߸Խͨ͠ετϦʔϜΛHLSͰ৴͢Δ
AES-128ʹΑΔ҉߸Խ৴ηάϝϯτશମΛAES-128 CBCϞʔυͰ҉߸ԽSegment🔒 Segment🔒 Segment🔒 Segment🔒#EXT-X-KEY:METHOD=AES-128,URI="伴Λऔಘ͢ΔͨΊͷURI",IV=0x012345678901234567890123456789012
• URIʹ伴ͷॴͦͷͷΛॻ͘ͱɺๅശʹʮ伴ςʔϒϧͷ্ʯͱுΓࢴΛ͍ͯ͠ΔΑ͏ͳͷ 伴ͷ͠ํʹ͕ඞཁ• 伴ͷαʔόʹೝূػೳΛ͚ͭΔ• ΧελϜεΩʔϚΛར༻ͯ͠ΞϓϦଆͰಠࣗॲཧΛߦ͏• etc.• εΫϦʔϯγϣοτը໘ըɺϛϥʔϦϯάՄೳ ʢඞཁͳΒΞϓϦͷίʔυͰରࡦʣAES-128ʹΑΔ҉߸Խ৴
AVContentKeySessionΞϓϦଆͰ伴Λऔಘ• ίϯςϯπͷ伴Λऔಘ͢ΔͨΊʹઃܭ͞ΕͨAPI• ࠶ੜը໘ʹདྷͨΒɺ͋Β͔͡ΊΩʔΛऔಘ͓ͯ͘͜͠ͱՄೳ → Join Timeͷվળʹཱͭ• METHOD=AES-128ͰɺγϛϡϨʔλͰಈ͔ͳ͍ʁ ͜ͷΫϥεొલ͔Β͋ΔAVAssetResourceLoaderಈ͘ URLProtocolͰϑοΫՄೳWWDC18 Session 507 AVContentKeySession Best Practicesࢀߟ:
session = AVContentKeySession(keySystem: .clearKey)session.setDelegate(self, queue: .global())let asset = AVURLAsset(url: playlistURL)session.addContentKeyRecipient(asset)player = AVPlayer(playerItem: AVPlayerItem(asset: asset))extension Foo: AVContentKeySessionDelegate {func contentKeySession(_ session: AVContentKeySession,didProvide keyRequest: AVContentKeyRequest) {getKey(from: keyRequest.identifier) { key inif let key = key {let response = AVContentKeyResponse(clearKeyData: key, initializationVector: nil)keyRequest.processContentKeyResponse(response)} else {keyRequest.processContentKeyResponseError(KeyError.unknown)}}}}AVContentKeySessionͰMETHOD=AES-128ͷ伴Λऔಘ͢Δྫ
FairPlay StreamingʹΑΔDRM৴伴ͷ৴ํ๏ΛఆΊͯɺͬͱݎ࿚ʹ͠Α͏
FairPlay Streaming (FPS)• AppleʹΑͬͯ։ൃ͞ΕͨಈըετϦʔϜΛอޢ͢ΔͨΊͷDRMٕज़• AppleͷσόΠεʢ+ AirPlayରԠεϚʔτTVʣͰར༻Մೳ• ωΠςΟϒΞϓϦ & Safari• ηΩϡΞͳ伴ͷ৴• HDCPͳͲʹରԠ͠ɺอޢ͞Εͨܦ࿏ͰͷΈө૾ɾԻΛ࠶ੜ εΫγϣΛࡱΔͱө૾ྖҬ͕ਅͬࠇʹͳΔ• ΦϑϥΠϯ࠶ੜϨϯλϧͷͨΊͷΈ͕͋Δ ϏδωεϩδοΫࣗମنఆ͠ͳ͍• ແྉ
FairPlayͱུ͕ͪ͠Ͱ͕͢ผͰ͢…💦FairPlay = iTunes StoreͷΞΠςϜʹΘΕ͍ͯΔDRMٕज़
FPSͰͷίϯςϯπͷ҉߸Խํࣜ• ίϯςφͷϏσΦΛϑϨʔϜຖɺΦʔσΟΦαϯϓϧຖʹ AES-128 CBCϞʔυͰ҉߸Խ• ϏσΦશମͷ10%Λ҉߸Խ (encrypt:skip pattern of 1:9) ϏσΦΛσίʔυͰ͖ͳ͘͢Δʹɺ෦తʹ҉߸Խ͢Εे#EXT-X-KEY:METHOD=SAMPLE-AES,URI="skd://key65",KEYFORMAT="com.apple.streamingkeydelivery",KEYFORMATVERSIONS="1"
ίϯςϯπͷ伴Λऔಘ͢ΔྲྀΕApple deviceOS AppKey serverKey Security ModuleLoad KeyGet SPC[CKC 🔑 ][SPC][SPC][CKC 🔑 ]࣮Օॴͪ͜ΒͰ४උApple ProvidedKey Security Module (KSM) ҉߸Խ͞ΕͨServer Playback ContextΛड͚औͬͯ ίϯςϯπͷ伴ΛؚΉContent Key ContextΛ ੜɾ҉߸Խͯ͠ฦ͢
ίϯςϯπͷ伴Λऔಘ͢ΔྲྀΕApple deviceOS AppKey serverKey Security ModuleLoad KeyGet SPC[CKC 🔑 ][SPC][SPC][CKC 🔑 ]࣮Օॴͪ͜ΒͰ४උApple Provided• 伴Λ͍ͬͯΔͷKey ServerͱOSͷΈʢΞϓϦΒͳ͍ʂʣ• ίϯςϯπOSͷΧʔωϧͰ෮߸
FairPlay Streaming ΈࠐΈखॱ1. Key Security ModuleΛ࣮ ެࣜϖʔδ͔ΒμϯϩʔυͰ͖ΔSDKΛར༻͠ɺ·ͣ։ൃ༻ͷূ໌ॻͰ࣮جຊతʹެࣜͷϖʔδΛݟͯ࡞ۀΛਐΊΔhttps://developer.apple.com/streaming/fps/FairPlay Streaming Server SDK• Programming Guide• KSMͷϦϑΝϨϯε࣮• ςετϕΫλʔʢ࣮͕ਖ਼͍͔֬͠ೝ͢ΔͨΊͷςετ༻σʔλʣ• ΞϓϦɾSafariͷαϯϓϧίʔυ
2. https://developer.apple.com/contact/fps/͔Β FairPlay Streaming Deployment package ΛϦΫΤετFairPlay Streaming ΈࠐΈखॱਖ਼͍͠తͰར༻͠Α͏ͱ͍ͯ͠Δ͔νΣοΫ͞ΕΔAppleͷ୲ऀͱগ͠ΓͱΓ͢Δ͜ͱ
3. ແࣄঝೝ͞ΕͨΒDeployment packageͷ༰ʹैͬͯҎԼΛੜ• FairPlay Streaming ূ໌ॻʢΞϓϦέʔγϣϯূ໌ॻʣ developerͷࣝผʹར༻• ূ໌ॻʹඥͮ͘private key• Application Secret key (ASk)4. Key Security Moduleͷ࣮Λੜͨ͠ূ໌ॻͳͲͰΞοϓσʔτ5. อޢίϯςϯπ४උ6. ΞϓϦ࣮ SDKʹؚ·ΕΔαϯϓϧίʔυHLSCatalog͕ඇৗʹࢀߟʹͳΔFairPlay Streaming ΈࠐΈखॱ
SafariͰಉ༷ͷྲྀΕͰ伴ΛऔಘՄೳApple deviceEME JSKey serverKey Security Module1. Load Key2. Get SPC6. [CKC 🔑 ]3. [SPC]4. [SPC]5. [CKC 🔑 ]࣮Օॴͪ͜ΒͰ४උApple Provided1. 'webkitneedkey' event2. Create keySession3. 'webkitkeymessage' evntwith [SPC]6. Update keySession with [CKC]
FairPlay Streaming over AirPlayอޢ͞ΕͨίϯςϯπΛApple TVεϚʔτTVͰʂApple deviceOS AppKey serverKey Security ModuleApple TVͳͲOSPlayer StreamerCDNίϯςϯπ ΞϓϦ [SPC], [CKC] ΛϦϨʔՃͷ࣮ෆཁ
ϚϧνϓϥοτϑΥʔϜͰ ಈըετϦʔϜΛอޢ͢Δʹ
͞·͟·ͳDRMγεςϜDRMγεςϜ ఏڙ ରԠϓϥοτϑΥʔϜPlayReady Microsoft Windows, Android, iOSWidevine Google AndroidFairPlay Streaming Apple AppleσόΠε
Common Encryption (CENC) ͱDRMίϯςϯπͷڞ௨҉߸ԽϑΥʔϚοτDRMγεςϜ CTR CBCPlayReady✔︎✔︎Widevine✔︎✔︎FairPlay Streaming ❌✔︎4.0Ҏ߱
ετϦʔϛϯάܗࣜͱ҉߸ར༻ϞʔυετϦʔϛϯάܗࣜ CTR CBCHLS ❌✔︎MPEG-DASH✔︎❌MPEG-DASH (CMAF)✔︎✔︎CENCΛར༻ͯ͠ڞ௨ͷ҉߸ԽίϯςϯπΛར༻Ͱ͖Δͱخ͍͠ ετϦʔϜͷCMAFରԠɺfMP4ԽͳͲ͕ඞཁ
AVPlayerͰ͖ͪΜͱίϯςϯπอޢ• AVPlayerʹ͍ͭͯ• HTTP Live StreamingͷΈ• ίϯςϯπอޢԿͷͨΊʁ• AES-128ʹΑΔ҉߸Խ৴• FairPlay Streaming• ϚϧνϓϥοτϑΥʔϜͰಈըετϦʔϜΛอޢ͢ΔʹRecap
ࢀߟࢿྉWWDC SessionsWWDC18 Session 507 AVContentKeySession Best PracticesWWDC15 Session 502 Content Protection for HTTP Live StreamingApple։ൃऀ͚ϖʔδHTTP Live Streaming https://developer.apple.com/streaming/FairPlay Streaming https://developer.apple.com/streaming/fps/
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠🙇