shaka-project / shaka-player

JavaScript player library / DASH & HLS client / MSE-EME player
Apache License 2.0
7.12k stars 1.33k forks source link

Support AES-128 on HLS #850

Closed avelad closed 2 years ago

avelad commented 7 years ago

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)

ismena commented 7 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!

avelad commented 7 years ago

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

ismena commented 7 years ago

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!

TheModMaker commented 7 years ago

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.

joeyparrish commented 7 years ago

If the keys are in the clear anyway, we could look into WebCrypto APIs: http://caniuse.com/#feat=cryptography

DiegoZurita commented 6 years ago

Is there any workaround to use AES-128 HLS encrypted?

avelad commented 5 years ago

I found that videojs uses https://github.com/videojs/aes-decrypter

s it possible to use it like mux.js?

TheModMaker commented 5 years ago

@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.

elv-peter commented 5 years ago

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"?

joeyparrish commented 5 years ago

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.

kevinscroggins-youi commented 5 years ago

@joeyparrish @TheModMaker Any updates on when this feature might be implemented? Thank you!

joeyparrish commented 5 years ago

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!

anuragkalia commented 5 years ago

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.

kakyleung commented 5 years ago

What's the conclusion about this? Does Shaka packager support AES-128 method ?

willkk commented 5 years ago

What's the conclusion about this? Does Shaka packager support AES-128 method ?

Obviously, No!

johndeu commented 4 years ago

@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).

joeyparrish commented 4 years ago

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.

elv-peter commented 4 years ago

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.

lenardpalko commented 4 years ago

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

joeyparrish commented 4 years ago

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?

lenardpalko commented 4 years ago

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.

joeyparrish commented 4 years ago

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:

  1. If there's no MediaSource, we must use src=, so return true.
  2. If native playback can't play this (based on MIME type), we can't use src=, so return false.
  3. If it's not a recognized manifest format (based on MIME type), we must use src=, so return true.
  4. Finally, if both manifest/MediaSource and native playback are possible, a. If it's an Apple platform (according to User Agent) and the 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.

alexey-y commented 3 years ago

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

aditmehta9 commented 3 years ago

@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.

hiren3897 commented 3 years ago

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.

android

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:

joeyparrish commented 3 years ago

@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.

wjywbs commented 2 years ago

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)

avelad commented 2 years ago

@wjywbs can you do a PR draft for it? thanks!

hiren3897 commented 2 years ago

@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

wjywbs commented 2 years ago

@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>

hiren3897 commented 2 years ago

Hello @wjywbs @theodab Can we have the estimated time for the work of this feature?

Thanks

joeyparrish commented 2 years ago

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.