Closed avelad closed 2 years ago
@avelad I am under impression that AES-128 on HLS implies FairPlay. (Please correct me if I'm mistaken). If that's the case, we have an issue about adding FairPlay support: #382. (You can take a look at the comments there to find out how it's going and what kind of complications we ran into with this).
If that's not related to FairPlay, let me know, we'll treat this separately!
It's a very simple mechanism. Each segement is encrypted with a key, for get this key only it's necessary get the response of license request of URI.
In the initial sample:
#EXT-X-KEY:METHOD=AES-128,URI="oceans.key"
#EXTINF:11, no desc
oceans_aes-audio=65000-video=236000-1.ts
The response of "oceans.key" is "õq¿ìý¹°\æúý" With this key, you can descrypt the segments.
A interesting article about that: https://www.theoplayer.com/blog/content-protection-for-hls-with-aes-128-encryption
Sample: https://tools.ietf.org/html/draft-pantos-http-live-streaming-13#section-8.4
Ok, let us take a look and see if we can make it work!
I'm adding this to the backlog since it requires investigation which makes me hesitant about scheduling it for 2.2. @joeyparrish please feel free to override me on this!
This looks like it could be implemented using clearkey. But there is a problem. AFAIK, all clearkey implementations use AES CTR for decryption, while HLS encryption uses AES CBC. Even if the browser supported CBC, there is no way in EME to pass the encryption scheme or the IV. If you are using Widevine encryption, this info is passed in the init data, but clearkey init data doesn't support these extra fields.
See #358 for a similar situation using DASH.
If the keys are in the clear anyway, we could look into WebCrypto APIs: http://caniuse.com/#feat=cryptography
Is there any workaround to use AES-128 HLS encrypted?
I found that videojs uses https://github.com/videojs/aes-decrypter
s it possible to use it like mux.js?
@avelad We probably wouldn't need that since we can just use the WebCrypto APIs to decrypt the content. What we could do is just query that URL and get the key, then use that with WebCrypto to decrypt the data before passing to MediaSource. I think AES-128 encrypts everything, so we might not even have to parse the container data.
I ran into this problem as well. You can easily generate a test with Bento4:
mp4hls --encryption-key 37d7ad30b2a8e801864b023e330c4b02 -o test --output-encryption-key --exec-dir=/usr/local/Cellar/bento4/1.5.1-628/bin trailer_1080p.mov
Safari, VLC, and videojs are all able to play it. Shaka gives me HLS_COULD_NOT_PARSE_SEGMENT_START_TIME (code 4030). If you decide not to add this feature, perhaps at least check for EXT-X-KEY in the manifest and output a more informative error message like "AES not supported"?
Parsing of segment start times is something we do now, but we could probably avoid in many cases. That is something we're planning for a future release, likely v2.6 or v2.7.
Aside from that, though, you're right. We could probably detect and reject AES-128 content with a meaningful error code instead of failing to parse it.
@joeyparrish @TheModMaker Any updates on when this feature might be implemented? Thank you!
No, it's not scheduled yet. But we are always willing to accept contributions from the community, so please feel free to discuss design and/or work on a PR if this is important to you. Thanks!
I ran into this issue and so will need to add support for it, I think. Will keep it posted here if I run into some problem.
What's the conclusion about this? Does Shaka packager support AES-128 method ?
What's the conclusion about this? Does Shaka packager support AES-128 method ?
Obviously, No!
@joeyparrish - any updated plans to support basic AES-128 mode? It's been in the HLS spec for a long time now, and it would be great to have that support for EXT-X-KEY and also the newer EXT-X-MAP support for the initialization segment being decrypted for CMAF content (MP4).
As far as I can tell, HLS's AES-128 mode is incompatible with EME in the browser. We'd have to do decryption ourselves, possibly with something like WebCrypto APIs.
I'm not against it, but we don't have the resources to work on it right now. We are happy to provide guidance for anyone who wants to create a PR for this.
If anyone has time to do the work, it's simple to decrypt with AES CBC (I've implemented it before in at least C and Go). There should be some libraries available, or you can check how hlsjs does it.
Unfortunately we didn't find this thread until now, and the tests we initially did with shaka-player seem to be misleading.
From our tests it seems that shaka-player is supporting HLS with AES-128, but only in some cases.
In our tests we have a simple AES-128 encryption on HLS with Unified Streaming, and the generated HLS manifest contains the following :
#EXT-X-SESSION-KEY:METHOD=AES-128,URI="https://api-server/content-key/xxxxxx"
Our application is using Shaka Player inside Angular with Ionic and we are generating the iOS application from this setup, so Shaka Player is running inside an ionic wkwebview.
The call is made correctly for the encryption content key and the stream is decrypted just fine in the iOS simulator from XCode, but when it is deployed on the actual iOS device, the call for the content key is not done anymore, the player throws error code: 3016
and the stream is not decrypted anymore.
Also the encrypted streams can be played just fine in the built-in safari player, so I think that there is at least some support for AES-128 in the browser.
What could be the explanation for it working in the iOS Simulator and not on the device ? Is there some experimental support for AES that works only in some cases ?
Thank you
No, we don't support this yet. However, in some cases, HLS content in Safari is played through Apple's native HLS. In those cases, AES-128 content plays because Apple's implementation takes over. Does that make sense?
It still wouldn't explain why it is playing in the WKWebView of Ionic. Because when testing actually with Safari the streams don't play, Shaka Player is throwing 3016 error code with no explanation. But when running inside the iOS application on the Simulator Device it works without issues, but on the actual device we also get the 3016 error code from shaka player.
I suppose it depends on what we see from the environment in Ionic. I'm not familiar with that, personally.
With native HLS playback using video.src=...
, AES-128 should work. The decision to use src= is based on Player's shouldUseSrcEquals_
private method, which goes like this in v3.0.3:
true
.false
.true
.streaming.useNativeHlsOnSafari
config is true
, we should use src=, so return true
.
b. Otherwise, return false
to prefer MediaSource-based playback.So the key things here are whether or not shaka.util.Platform.isApple()
returns true
and whether shaka.util.Platform.supportsMediaType('application/x-mpegurl')
returns true within this WKWebView application. Both are true in Safari on macOS and iOS.
Error code 3016 would be triggered by a generic error event from the video element. We don't actually know, in that case, what caused it.
This is getting a little off-topic for the implementation of AES-128 in Shaka Player's HLS parser, so let's start a new issue if you need further support with WKWebView & Ionic.
Hi,
I am interested to contribute on this one. I have seen the bits around using WebCrypto... Could I get some pointers where is the best place to start making the changes in the Shaka codebase?
Thanks, Alexey
@joeyparrish I took a cryptography elective in my third year so the 'Support AES-128 on HLS' project interests me. I am familiar with https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt and how to add encryption keys in manifest but I don't have a general idea if some clear path on how to start would be provided It will be helpful.
Hello all, I am trying to play my HLS streams on Andriod devices (Chrome Browser) but it gives me a 4034 error in the console.
Can anyone help me or guide me about it. Is it possible to play HLS AES-128 on android devices?
Thank you in advance :+1:
@hiren3897, it is not possible today, because Shaka Player doesn't support non-DRM AES-128 yet. This issue is open to discuss and track the implementation of that feature. No work has been done toward this feature yet.
I added support to play AES-128 encrypted HLS TS streams, but I haven't updated tests yet. https://github.com/wjywbs/shaka-player/commits/aes
Add this config to the player:
player.configure({
manifest: {
hls: {
// Required for AES-128 streams.
useFullSegmentsForStartTime: true
}
}
});
These demo videos can play: https://playertest.longtailvideo.com/adaptive/oceans_aes/oceans_aes.m3u8 (No IV) https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/m3u8s/11331.m3u8 (Const IV)
Key rotation (and maybe discontinuity) is not supported. (Existing TODO: May still need changes to support key rotation)
@wjywbs can you do a PR draft for it? thanks!
@wjywbs Did you also add the mux.js script in the header to support ts playback?
And it seems the config:
player.configure({
manifest: {
hls: {
// Required for AES-128 streams.
useFullSegmentsForStartTime: true
}
}
});
Is already in the configuration and I am using it to play the hls live streams but I think those are not AES-128 Encrypted
@avelad Sure, I created PR #3880
@hiren3897 Yes, I used <script src="https://cdn.jsdelivr.net/npm/mux.js@6.0.1/dist/mux.min.js"></script>
Hello @wjywbs @theodab Can we have the estimated time for the work of this feature?
Thanks
There's no estimate available right now, because nobody on the Shaka team is working on this right now.
It will become a higher priority for us later this year, as we need this feature in Shaka to fully deprecate another player. In the meantime, community contributions are very welcome! I just exchanged messages with someone on Slack who wants to take over and improve the existing PR.
This it's a request feature for support AES-128 on HLS. Is it possible support it?
Sample stream: https://playertest.longtailvideo.com/adaptive/oceans_aes/oceans_aes.m3u8
Now, I get: HLS_REQUIRED_ATTRIBUTE_MISSING (KEYFORMAT)