W3C home > Mailing lists > Public > public-html@w3.org > March 2012

Re: Encrypted Media proposal (was RE: ISSUE-179: av_param - Chairs Solicit Alternate Proposals or Counter-Proposals)

From: Mark Watson <watsonm@netflix.com>
Date: Thu, 1 Mar 2012 19:33:33 +0000
To: Henri Sivonen <hsivonen@iki.fi>
CC: "<public-html@w3.org>" <public-html@w3.org>
Message-ID: <3F1BCD06-77C2-4503-9425-A240466CA48B@netflix.com>
Hi Henri,

Below is a review of the proposal you posted yesterday.

Note that I have no idea whether this proposal could be implemented royalty-free. I doubt that you do either. But I know that this subject area has been the target of very many patent filings. This is another of the practical reasons for delegating this functionality to the CDMs in our proposal.


On Feb 29, 2012, at 12:27 AM, Henri Sivonen wrote:

Here's a description of a straw feature that I believe meets all the
above requirements. Would this system be adequate for Netflix to serve
movies to a browser that implements this feature? If not, why not
specifically? (The main purpose of this exercise is to gain better
understanding of the requirements. This isn't an offer to implement
this straw feature.)

- -

This feature adds a decryption layer to the browser's HTTP stack and
an API for initializing decryption keys from a different origin. Also,
the Same Origin Policy is extended to block obvious access to
decrypted data from JavaScript.

The browser maintains a key storage that holds tuple of key,
sha1(key), origin of key, list of authorized origins and time to live.
There's a JavaScript API navigator.addKey(keyUrl,
arrayOfAuthorizedOrigins, timeToLiveSeconds, doneCallback). keyUrl is
a URL of the same origin as the caller of the API. The payload
retrieved from the URL is key material to be added to the key storage.
arrayOfAuthorizedOrigins is an array of origins serialized as strings
that are authorized to serve content to be decrypted using the key.
(This is a privacy mechinism against other origins probing the key
store in case an untrusted CDN has leaked key hashes. More on hashes
later.) timeToLiveSeconds is the number of seconds after which the
browser purges this keystore entry. doneCallback is a JavaScript
function that the browser calls after it has retrieved and processed
keyUrl. Upon success, a single argument true is passed. Upon failure,
a single argument false is passed. (Note: The key material is not
exposed to JS.) The browser generates an id for the key by hashing the
key material with SHA-1. Origin of key is set to the origin of the
caller of the API which has to be the same as the origin of keyUrl.

If the keys are available to the browser code, then this probably wouldn't work for most of our content, since a browser could be trivially modified to release the keys.

If the keys are not exposed to the browser code (i.e. if the mechanism above were implemented within something like the CDM we propose and this met our security requirements) then another issue is that you (presumably) rely on standard HTTP authentication to authenticate the user.

Presently we use our own application protocol within which we have our own authentication mechanisms. We provided details of this in the discussion on the proposed web cryptography working group [1] . This avoids the need to stand up front-end servers for each different key delivery protocol (of which your proposal would be just one).

This is one reason why we propose to proxy the key delivery messages through the Javascript layer.

When an HTTP response includes the response header Content-Encoding:
AES256, the processing happens as follows (if any step fails, treat as
like other HTTP errors):

The HTTP implementation gets the value of another response header
called Key-SHA1 and base64-decodes it. Then, the browser's key storage
is searched for a key whose sha1(key) entry matches this value and
whose list of authorized origins containst the origin of the HTTP
response and decrypts the response payload using AES256 using the
located key as the decryption key.

Performing the decryption at the HTTP layer has the following problems:
- HTTP servers have to support the additional headers, which means CDN changes are necessary. Even trivial CDN changes take time to roll out across the world and CDNs generally want some compensation. Anything which restricts our choice of CDNs increases our costs and reduces user quality of experience (due to reduced diversity). So there's value to us if the solution works with existing HTTP services.
- existing standard encryption mechanisms (for example common encryption for mp4 files) cannot be used, meaning that existing files would have to be re-encrypted and also that separate copies of the media would be needed for browsers based on this system and devices following the existing standards. Requiring separate copies has both storage costs and cache efficiency costs (which impact quality of experience).

It's possible the second point could be addressed by making the HTTP stack file-format-aware, so that it could apply the appropriate kind of decryption. But that seems architecturally problematic.

The decrypted payload is exposed to
the other parts of the browser as having origin E(origin of key).

Origins of the type E(Origin) have the following properties:

* A resource of origin E(Origin) can be included as embedded content
(<img>, <video>, <audio>) in (and only in) a document whose origin is
* For the purpose of JavaScript access to the data of the resource
(be it raw bytes or pixel data), E(Origin) is considered to be
different-origin with every origin including the origin(s)
representing the authority of browser extensions.
* Browsers disable the "Save As..." context menu for embedded content
whose origin is of the form E(Origin)

I'm not an expert on these kind of browser security issues, but the above sounds quite neat to me. It could also be considered as a way to handle the output of CDMs in our proposal, for the case where this output (in whatever form) goes back to the browser code.


When the layer above the HTTP layer request the HTTP stack to perform
a range request on a Content-Encoding: AES256 resource, the HTTP stack
must extend the range such that the range consists of full AES256
blocks in both directions. (The lack of block chaining is deliberate
so that seeking is possible.)

[1] http://www.w3.org/wiki/NetflixWebCryptoUseCase
Received on Thursday, 1 March 2012 19:34:03 UTC

This archive was generated by hypermail 2.4.0 : Saturday, 9 October 2021 18:45:49 UTC