{"id":74791,"date":"2025-09-09T09:24:17","date_gmt":"2025-09-09T03:54:17","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=74791"},"modified":"2025-09-17T11:55:27","modified_gmt":"2025-09-17T06:25:27","slug":"key-rotation-challenges-in-drm-content-for-offline-playback","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/key-rotation-challenges-in-drm-content-for-offline-playback\/","title":{"rendered":"Key Rotation Challenges in DRM Content for Offline Playback"},"content":{"rendered":"<h2><strong>Introduction<\/strong><\/h2>\n<p>When streaming services lock content, downloading it lets people watch shows movies without needing WiFi. In the past, systems protecting digital content used static encryption keys. One key was used to decrypt all of the content. As content security gets better, regularly changing the keys used to protect it provides a strong way to improve safety.<\/p>\n<p>Changing encryption keys regularly, like with each section of data, protects your information. If a key gets stolen, only that specific section is at risk, leaving everything else safe. This helps keep things safe, yet it creates a real problem for video apps, especially when you want to watch videos without internet access. The video player used to unlock content with a single PSSH key (Protection System Specific Headers). Now, it finds several different keys scattered throughout the video, so unlocking becomes trickier.<\/p>\n<p>When Key Rotation is disabled:<\/p>\n<ul>\n<li>From the server, a <strong>single PSSH key<\/strong> is being used to decrypt all media chunks, so that offline playback works seamlessly.<\/li>\n<\/ul>\n<p>When Key Rotation is enabled:<\/p>\n<ul>\n<li>A <strong>unique PSSH key<\/strong> will be integrated in each segment (group of segments also). The player which was designed to handle only one key earlier would have to manage all these extra keys to decrypt the content, and if the player cant find these keys then offline playback fails mid content<\/li>\n<\/ul>\n<p>This blog details the challenges we solved to get offline viewing working with updated security. To ensure seamless downloading and proper offline video playback, we have updated the core logic of video downloading and license generation whenever we have a content which is enabled with Key Rotation.<\/p>\n<hr \/>\n<h2><strong>The Problem: Why Did Offline Playback Fail?<\/strong><\/h2>\n<p>We found the <strong>MPD<\/strong> (Media Presentation Description) file that describes how media plays, including details about video quality, security, and individual pieces of content, started with one PSSH key when Key Rotation was disabled. This let the DRM system to create a decryption license effortlessly..<\/p>\n<p>With Key Rotation enabled:<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li>No PSSH key was available in the MPD file.<\/li>\n<li>PSSH keys went into video sections, not the manifest file.<\/li>\n<li>At first, we only got the PSSH key for the initial part. This let us unlock a small portion of the video.<\/li>\n<li>The video stopped working when it moved to a new part protected by a different key. This broke the ability to watch it without internet.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>Basically, the DRM didn\u2019t know about all the different keys required to play the full video. We grabbed every PSSH key while downloading, combined them into one set of data , then built a license with all the decryption keys.<\/p>\n<hr \/>\n<h2><strong>The Solution: A Robust Workflow for Key Rotation Support<\/strong><\/h2>\n<p>We fixed the problem with DASH videos on Android devices that use Widevine L3 security. We did this with several changes. The system gets, handles, combines all PSSH keys, while maintaining DRM compliance for smooth downloading and offline playback.<\/p>\n<p style=\"padding-left: 40px;\">1. <span style=\"text-decoration: underline;\">Initial PSSH Extraction from the First Segment<\/span><br \/>\nThe initial PSSH key is very important as it is used to create the first DRM session which allows to start the downloading of content. So to retrieve this key we fetch the first media segment so we can extract its PSSH key.<\/p>\n<div id=\"attachment_76180\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-76180\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-76180\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/first-1024x424.png\" alt=\"Extracting the First PSSH Key\" width=\"625\" height=\"259\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/first-1024x424.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/first-300x124.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/first-768x318.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/first-624x259.png 624w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/first.png 1117w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-76180\" class=\"wp-caption-text\">Extracting the First PSSH Key<\/p><\/div>\n<p style=\"padding-left: 40px;\">Explanation:<br \/>\nThis extracted PSSH key is used to setup and intialize the DRM session and this enables the decryption of first few content chunks.<\/p>\n<p style=\"padding-left: 40px;\">2. <span style=\"text-decoration: underline;\">Dynamic PSSH Extraction While Downloading Segments<\/span><br \/>\nTo extract every PSSH key dynamically from each video chunk we created a <strong>DashExtractor\u00a0<\/strong>class which parses the downloaded segment in the form of byte array. To make sure no key is missed, all the unique extracted keys are added to a list (psshList).<\/p>\n<div id=\"attachment_76182\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-76182\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-76182\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/second-1024x412.png\" alt=\"Extracting PSSH Keys During Download\" width=\"625\" height=\"251\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/second-1024x412.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/second-300x121.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/second-768x309.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/second-624x251.png 624w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/second.png 1231w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-76182\" class=\"wp-caption-text\">Extracting PSSH Keys During Download<\/p><\/div>\n<p style=\"padding-left: 40px;\">Explanation:<br \/>\nBy using DashExtractor class we have extracted only the unique PSSH keys, duplicates are avoided and then added to the list.<\/p>\n<p style=\"padding-left: 40px;\">3. <span style=\"text-decoration: underline;\">Merging Multiple PSSH Keys<\/span><br \/>\nThe MergePsshHelper class is used after all chunks are downloaded, to combine all the unique extracted PSSH keys into a single byte array. To create <strong>schemeData<\/strong> object the data of all the extracted keys is used using MergePsshHelper.<\/p>\n<div id=\"attachment_76183\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-76183\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-76183\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/third-1024x323.png\" alt=\"Merging PSSH Keys\" width=\"625\" height=\"197\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/third-1024x323.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/third-300x95.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/third-768x242.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/third-624x197.png 624w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/third.png 1279w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-76183\" class=\"wp-caption-text\">Merging PSSH Keys<\/p><\/div>\n<p style=\"padding-left: 40px;\">Explanation:<br \/>\nMergePsshHelper merges the PSSH keys byte-by-byte, ensuring the combined data remains valid for the DRM system.<\/p>\n<p style=\"padding-left: 40px;\">4. <span style=\"text-decoration: underline;\">Generating the Offline License<\/span><br \/>\nAfter successfully merging all the keys, we need to download the offline license so that whenever video will be played without internet all the segments will have their respective decryption keys via license.<\/p>\n<div id=\"attachment_76181\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-76181\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-76181\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/fourth-1024x214.png\" alt=\"Generating the Offline License\" width=\"625\" height=\"131\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/fourth-1024x214.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/fourth-300x63.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/fourth-768x160.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/fourth-624x130.png 624w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/fourth.png 1285w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-76181\" class=\"wp-caption-text\">Generating the Offline License<\/p><\/div>\n<p style=\"padding-left: 40px;\">Explanation:<br \/>\nWith all the keys merged in a single object and using the same object to generate the offline license which has all keys is stored in <strong>keySetId.\u00a0<\/strong> This keySetId will be used in decryption of all segments at the time of offline playback.<\/p>\n<p style=\"padding-left: 40px;\">5. <span style=\"text-decoration: underline;\">Preserving Database with updated Values<\/span><br \/>\nIf app restarts and database is not updated with the latest license, then it will use the old license which only contained the first segment PSSH key, this will result in errors while offline playback. So we need to update the database with license generated with all keys i.e. <strong>keySetId<\/strong><\/p>\n<div id=\"attachment_76179\" style=\"width: 977px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-76179\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-76179\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2025\/09\/fifth.png\" alt=\"Updating Database with offline license\" width=\"967\" height=\"133\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2025\/09\/fifth.png 967w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/fifth-300x41.png 300w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/fifth-768x106.png 768w, \/blog\/wp-ttn-blog\/uploads\/2025\/09\/fifth-624x86.png 624w\" sizes=\"(max-width: 967px) 100vw, 967px\" \/><p id=\"caption-attachment-76179\" class=\"wp-caption-text\">Updating Database with offline license<\/p><\/div>\n<hr \/>\n<h2><strong>Why This Approach is Effective<\/strong><\/h2>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li>Extracting PSSH keys dynamically:<br \/>\nWe aimed to get every PSSH key, because missing one caused problems with watching videos. So, during downloads, we used a class called DashExtractor to pull these PSSH keys from each video segment.<\/li>\n<li>Generation of License with all keys:<br \/>\nTo use without internet we created a license which included all the security keys we already had. We combined those keys into one piece of data (schemeData), then the DRM system built a complete offline license.<\/li>\n<li>Support for Offline Playback:<br \/>\nThe license you got has everything including the decryption keys which are needed to unlock the content, so it plays smoothly even when Key Rotation is enabled.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<hr \/>\n<h2><strong>Conclusion<\/strong><\/h2>\n<p>Switching encryption keys for content with digital rights management makes things more involved, however, it really improves how safe the content is. We get security keys from video pieces, combine them, then make one license. This lets you watch DASH videos offline, even those protected by Widevine L3.<\/p>\n<p>This method fixed problems with video playing, it also provides a strong system for managing changing encryption keys in digital rights management.<\/p>\n<p>If developers run into trouble, this process gives a useful, adaptable way to keep videos playing smoothly in changing, protected streaming setups.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction When streaming services lock content, downloading it lets people watch shows movies without needing WiFi. In the past, systems protecting digital content used static encryption keys. One key was used to decrypt all of the content. As content security gets better, regularly changing the keys used to protect it provides a strong way to [&hellip;]<\/p>\n","protected":false},"author":2154,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":65},"categories":[518],"tags":[7951,7955,5482,7960,7959,7962,7952,7958,7956,7954,7957,7961,7953],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/74791"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/2154"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=74791"}],"version-history":[{"count":4,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/74791\/revisions"}],"predecessor-version":[{"id":76518,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/74791\/revisions\/76518"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=74791"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=74791"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=74791"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}