W3C

Encrypted Media Extensions / Зашифрованный медиаконтент в HTML5

Черновик авторов от W3C, 26 февраля 2013 года

Эта версия:
http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html
Последняя опубликованная версия:
http://www.w3.org/TR/encrypted-media/
Последний авторский черновик:
http://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html
Авторы:
David Dorwin, Google, Inc.
Adrian Bateman, Microsoft Corporation
Mark Watson, Netflix, Inc.
Списки ошибок/проблем:
Bugzilla, Tracker
Список рассылки:
public-html-media@w3.org
Набор тестов:
Пока нет

Краткий обзор

Это предложение расширяет HTMLMediaElement, предоставляя API для управления воспроизведением защищенного контента.

Данное API поддерживает варианты использования от простого дешифрования clear key до ценного видео (при наличии соответствующей реализации в агенте пользователя). Обмен ключами/лицензиями контролируется приложением, способствуя разработке функциональных приложений по воспроизведению, поддерживающих ряд технологий по дешифрованию контента и его защите.

Данная спецификация не определяет систему защиты контента или систему управления цифровыми правами (DRM). Скорее она определяет общее API, которое может быть использовано для обнаружения, выбора и взаимодействия с подобными системами, а также с более простыми системами шифрования контента. Реализация Системы Управления Цифровыми правами (DRM) не требуется для соответствия данной спецификации: только простую систему Clear Key требуется реализовать в качестве основы.

Общее API поддерживает простое множество возможностей шифрования контента, оставляя прикладные функции, такие как аутентификация и авторизация, разработчикам страниц. Это достигается за счет требования того, что обмен сообщениями о защите контента совершается при посредничестве страницы, а не за счет предположения существования внеполосной коммуникации между системой шифрования и сервером лиценций или другим сервером.

Статус этого документа

Этот раздел описывает статус этого документа в момент его публикации. Другие документы могут заменить этот документ. Список текущих публикаций W3C и последняя ревизия этого технического документа могут быть найдены в каталоге технических документов W3C на http://www.w3.org/TR/.

Разработчикам следует знать, что эта спецификация нестабильна. Разработчики, которые не принимают участие в обсуждениях, вероятно, найдут, что спецификация изменится несовместимым образом. Производителям, заинтересованным в реализации этой спецификации до того, как она в конечном итоге достигнет уровня Candidate Recommendation, следует присоединиться к списку рассылки, указанным ниже, и принять участие в обсуждениях.

Этот документ был опубликован рабочей группой HTML в качестве Авторского Черновика (Editor's Draft). Пожалуйста, отправляйте комментарии относительно этого документа, используя (публичную базу ошибок) W3C с пометкой продукта = HTML WG и компонентом = Encrypted Media Extensions. Если вы не можете получить доступ к базе ошибок, отправьте комментари в public-html-media@w3.org (подписаться, архивы) и будут приложены усилия по перемещению этих комментариев в базу ошибок. Приветствуется любые замечания.

Публикация в качестве Авторского Черновика не означает одобрения W3C. Это черновой документ, и он может быть обновлен, заменен или отменен другими документами в любое время. Недопустимо ссылаться на этот документ из других документов, отличных от незавершенных.

Замечание: Вопрос не закрыт, стоит ли и как данной спецификации следует поощрять/обеспечивать больше взаимодействия CDM-уровня. Смотрите Ошибку 20944.

Замечание: Вопрос не закрыт, стоит ли и как данной спецификации следует предоставлять помощь в приватности для CDM-реализаций. Смотрите Ошибку 20965 и Ошибку 20966.

Этот документ был выпущен группой людей, действующей согласно 5 February 2004 W3C Patent Policy. W3C держит публичный список of всех открытых патентов, сделанных в связи с результатами работы этой группы; эта страница также включает инструкции по раскрытию возможных патентов. Лицо, владеющее актульной информацией о каком-либо патенте, который, как он считает, содержит Essential Claim(s), должно раскрыть эту информацию согласно section 6 of the W3C Patent Policy.

Содержание

1. Вступление

Этот раздел — неофициальный.

Это предложение разрешает JavaScript выбирать механизмы защиты контента, управлять обменом лиценцией/ключом и реализовывать свои алгоритмы управления лицензиями. Это касается широкого диапозона вариантов использования без требования изменения на клиентской стороне в каждом агенте пользователя в каждом случае. Это также позволяет контент-провайдерам разрабатывать единое прикладное решение для всех устройств. Общий стек, реализованный с использованием предложенных API, показан ниже. Это просто пример движения и он не предназначен представить все возможные случаи коммуникаций и использований.

Общий стек, реализованный с использованием предложенных API

1.1 Цели

Этот раздел — неофициальный.

Это предложение было разработано со следующими целями:

1.2. Определения

Текст таким шрифтом и цветом — не официален.

1.2.1. Модуль дешифровки контента (CDM)

Этот раздел — неофициальный.

Модуль дешифровки контента (Content Decryption Module, CDM) — общий термин для части или расширения к агенту пользователя, который предоставляет функциональность для одной или более Ключевой Системы. Реализации могут разделять или нет реализации CDM, и могут рассматривать или нет их отдельно от агента пользователя. Это прозрачно для API и приложения. Агент пользователя может поддерживать один или более CDM.

1.2.2. Key System (Ключевая Система)

Key System — это общий термин для механизма дешифровки и/или провайдера шифрования контента. Каждая Key System идентифицируется строкой (текста). Они используются агентом пользователя для выбора CDM и идентификации источника события, относящегося к ключу. Ключевая Система Simple Decryption (должна) поддерживается всеми агентами пользователя. Агенты пользователя могут также предоставлять дополнительные CDMы с соответствующими строками Key System.

Строка Key System — всегда есть обратное доменное имя. Например, "com.example.somesystem". В пределах данной системы ("somesystem" в данном примере) могут быть определены подсистемы, которые устанавливает провайдер данной ключевой системы. Например, "com.example.somesystem.1" и "com.example.somesystem.1_5". Провайдерам Key System следует иметь в виду, что они будут использованы для сравнения и обнаружения, поэтому они должны быть простыми для сравнения и их структура должна оставаться сравнительно простой.

1.2.3. Session ID

Session ID есть опциональная строка ID, используемая для ассоциирования вызовов, относящихся к времени жизни ключа/лицензии со стартом в начале запроса. Это локальная привязка запроса и ключа/лицензии. Он не связывает ключи/лицензии для различных потоков (например, для аудио и видео). Если session ID поддерживается Ключевой Системой, то он генерируется агентом пользователя/CDM и предоставляется приложению вместе с событием keymessage. (session ID не обязательно поддерживаются клиентом или сервером.)

Если session ID поддерживается, то он генерируется каждый раз, когда createSession() успешно создает объект MediaKeySession. Агент пользователя/CDM управляет временем жизни session ID. Все session ID удаляются из медиа-элемента при загрузке, хотя CDM может сохранить их на больший период.

Каждый session ID должен быть уникальным в пределах браузерного контекста, в котором он был создан. Если поддерживается надежное доказательство избавления от ключа, то каждый session ID должен быть уникальным в пределах провайдера контента. Заметим, что последнее требование влечет то, что session ID должны быть уникальны во времени, с учетом браузерных сессий.

Приложениям следует всегда передавать session ID из событий, при последующих вызовах для данного ключа или лицензии. (Это лучшая практика, даже если текущая Key System не поддерживает session ID.) Это может означать, что приложение должно ассоциировать ответ сервера с session ID и передавать их обоих в update().

1.2.4. Начальные данные (Initialization Data)

Этот раздел — неофициальный.

Начальные данные — это общий термин для контейнеро-специфичных данных, используемых CDM для создания запроса ключа. Их всегда должно хватать для полной идентификации ключа или ключей, необходимых для дешифровки контента, возможно, после того, как они будут прочитаны CDM или сервером.

Ключевые Системы обычно требуют блок начальных данных, содержащих информацию о потоке, который нужно расшифровать, перед созданием сообщения о запросе ключа. Этот блок мог бы быть как простым, как ключ или идентификатор контента для посылки на сервер, так и сложным, как непрозрачный набор данных, специфичных для Key System. Такая начальная информация может быть получена особым, специфичным для приложения образом, или может храниться с медиа-данными. Форматы контейнеров могут быть использованы для хранения подобной информации; возможно хранение нескольких Ключевых Систем в одном медиа-файле.

Начальные данные, найденные в медиа-данных, передаются приложению через атрибут initData события needkey. Эти данные имеют контейнеро-специфичный формат и, полагается, содержат 1 или более Key System-специфичных множеств начальной информации.

2. Расширение медиа-элемента

Мы расширяем media element, чтобы позволить получение ключа расшифровки в JavaScript.

Замечание: Для некоторых CDM'ов слова "ключ" ("key") и "запрос ключа" ("key request") соответствуют словам "license" и "license request", соответственно.

partial interface HTMLMediaElement {
  // Encrypted Media
  readonly attribute MediaKeys keys;
  void setMediaKeys(MediaKeys mediaKeys);
  
  attribute EventHandler onneedkey;
};

[Constructor (DOMString keySystem)]
interface MediaKeys {
  readonly attribute DOMString keySystem;

  MediaKeySession createSession(DOMString? type, Uint8Array? initData);

  static bool isTypeSupported(DOMString type, DOMstring keySystem);
};

interface MediaKeySession : EventTarget {
  // error state
  readonly attribute MediaKeyError? error;

  // session properties
  readonly attribute DOMString keySystem;
  readonly attribute DOMString sessionId;

  // session operations
  void update(Uint8Array key);
  void close();
};

partial interface HTMLSourceElement {
  attribute DOMString keySystem;
};

Атрибут keys есть MediaKeys, используемый во время расшифровки зашифрованных медиа-данных для данного медиа-элемента.

Метод setMediaKeys дает возможность установить MediaKeys для использования. При вызове этого метода, медиа-элемент должен выполнить следующие шаги:

  1. Если загрузки не началась, то бросить исключениеINVALID_STATE_ERR.

    Вообще, приложениям следует ждать события needkey или loadstart (в случае задействования resource fetch algorithm) перед вызовом этого метода.

  2. Установить атрибут keys медиа-элемента в mediaKeys.

Обработчик onneedkey для события needkey должен поддерживаться для всех HTMLMediaElement'ов как атрибут (контента и IDL).

Конструктор MediaKeys(keySystem) должен выполнить следующие шаги:

  1. Если keySystem — null или пустая строка, то бросить исключение INVALID_ACCESS_ERR и прекратить эти шаги.

  2. Если keySystem не входит в число поддерживаемых агентом пользователя Key System, бросить исключение NOT_SUPPORTED_ERR и прекратить эти шаги.

  3. Пусть cdm есть модуль дешифровки контента, соответствующий keySystem.

  4. Загрузить cdm, если необходимо.

    Если cdm не удается загрузить или инициализировать
    1. Создать новый объект MediaKeyError со следующими атрибутами:

      • code = подходящий код MediaKeyError
        systemCode = Key System-специфичное значение, если есть, или 0 в противном случае
    2. Установить атрибут error новосозданного объекта в значение объекта, созданного на предыдущем шаге.

    3. добавить задание по возбуждению простого события keyerror на этом новом объекте.

    4. Прекратить эти шаги.

  5. Создать новый объект MediaKeys.
    1. Пусть атрибут keySystem равен keySystem.

  6. Вернуть новый объект вызывающему.

При уничтожении объекта MediaKeys следуйте шагам в close().

Атрибут keySystem есть идентификатор используемой Key System.

Метод createSession(type, initData) должен выполнить следующие шаги:

Замечание: содержимое initData есть контейнеро-специфичные начальные данные.

  1. Если type есть null или пустая строка и initData есть null или пустая строка, то бросить исключение INVALID_ACCESS_ERR и прекратить эти шаги.

  2. Если type содержит MIME-тип, который не поддерживается или не поддерживается keySystem, то бросить исключение NOT_SUPPORTED_ERR и прекратить эти шаги.

  3. Пусть cdm равна cdm, загруженному в конструкторе MediaKeys constructor.

  4. Создать новый объект MediaKeySession.
    1. Пусть keySystem равен атрибуту keySystem.

    2. Пусть атрибут sessionId есть уникальная строка Session ID. Он может быть сгенерирован cdm.

  5. Добавить этот новый объект к внутреннему списку сессионных объектов.

  6. Запланировать задание генерации запроса ключа по type, initData и новому объекту.

    Агент пользователя асинхронно выполняет следующие шаги по заданию:

    1. Пусть defaultURL равно null.

    2. Использовать cdm для генерации запроса кюча и следовать шагам первого выполняющегося условия из следующего списка:

      Если запрос успешно сгенерирован
      1. Пусть key request равен запросу ключа, сгенерированный CDM с использованием initData, если в наличии.

        Замечание: cdm должен не использовать никакие данные, включая медиа-данные, помимо initData.

        type может быть использовать для определения того, как интерпретировать initData.

      2. Если initData — не null и содержит URL по умолчанию для keySystem, то пусть defaultURL равен этому URL.

      Иначе
      1. Создать новый объект MediaKeyError со следующими атрибутами:

        • code = подходящий код MediaKeyError
          systemCode = Key System-специфичное значение, если есть, или 0 в противном случае
      2. Установить атрибут error объекта MediaKeySession в значение объекта, созданного на предыдущем шаге.

      3. добавить задание по возбуждению простого события keyerror на объекте MediaKeySession.

      4. Отменить задание.

    3. добавить задание по возбуждению простого события keymessage на этом новом объекте.

      Событие — типа MediaKeyMessageEvent и имеет:

      Замечание: message может быть запросом для нескольких ключей, в зависимости от keySystem и/или initData. Это прозрачно для приложения.

  7. Вернуть новый объект вызывающему.

Метод isTypeSupported(type, keySystem) определяет, поддерживается ли keySystem с указанным контейнером и кодеком(и) type.

Следующий список показывает некоторые примеры.

Определить, поддерживается ли "некая система" Key System. Некоторые контейнеры и кодеки могут или не могут поддерживаться с "некой системой".
MediaKeys.isTypeSupported(null, "com.example.somesystem")
Определить, поддерживается ли версия 1.5 "некой системы" Key System. Некоторые контейнеры и кодеки могут или не могут поддерживаться с "некой системой" 1.5.
MediaKeys.isTypeSupported(null, "com.example.somesystem.1_5")
Определить, есть ли "некая система" Key System в наличии и поддерживается ли контейнер и кодек(и) типа mimeType.
MediaKeys.isTypeSupported(mimeType, "com.example.somesystem")
Определить, поддерживает ли агент пользователя Простое Дешифрование Clear Key контейнера и кодека(ов) типа mimeType.
MediaKeys.isTypeSupported(mimeType, "org.w3.clearkey")

Должны выполниться следующие шаги:

  1. Если keySystem содержит неопознанный или неподдержанный Key System, то вернуть false и прекратить шаги.

  2. Если type — null или пустая строка, то вернуть true и прекратить шаги.

  3. Если Key System переменной keySystem не поддерживает дешифровку контейнера и/или кодека type, то вернуть false и прекратить шаги.

  4. Вернуть true.

Атрибут error есть MediaKeyError, представляющий текущее ошибочное состояние сессии. Он равен null, если ошибок нет.

sessionId есть атрибут Session ID для данного объекта и соответствующих ключей/лицензий.

Метод update(key) должен выполнить следующие шаги:

Замечание: Содержимое keykeySystem-специфично. Оно может быть непосредственно ключом или лицензией, содержащим ключ. Содержание может меняться в зависимости от контейнера, длина ключа и т.д.

  1. Если аргумент — null или пустой массив, то бросить исключение INVALID_ACCESS_ERR.

  2. Запланировать задание для обработки вызова с аргументом key.

    Агент пользователя асинхронно выполняет следующие шаги по заданию:

    1. Пусть cdm равна cdm, загруженному в конструкторе MediaKeys constructor.

    2. Пусть did store key равно false.

    3. Пусть next message равно null.

    4. Используем cdm для обработки key.

      Замечание: Для некоторых Key Systems key может быть лицензией или другой структурой, содержащей несколько ключей.

      1. Обработать key.

      2. For each individual key in key, store the individual key.

        1. Let key ID be null.

        2. If there is a key ID associated with the individual key, let key ID be that ID.

        3. Store the individual key by following the steps for the first matching condition from the following list:

          If key ID is not null
          1. Clear any stored key not associated with a key ID.

          2. If a stored key already exists for key ID, delete that key.

          3. Store the individual key, license, and/or license information indexed by key ID. The replacement algorithm is Key System-dependent.

          Otherwise
          1. Clear all stored keys.

          2. Store the individual key, license, and/or license information with no associated key ID.

          At most one key may be stored if key IDs are not used.

          Clearing keys avoids needing to handle a mixture of keys with and without IDs in the Encrypted Block Encountered algorithm.

          Note: It is recommended that CDMs support a standard and reasonably high minimum number of cached keys/licenses (with IDs) per MediaKeySession object as well as a standard replacement algorithm. This enables a reasonable number of key rotation algorithms to be implemented across user agents and may reduce the likelihood of playback interruptions in use cases that involve various streams in the same element (i.e. adaptive streams, various audio and video tracks) using different keys.

        4. Let did store key be true.

      3. Если еще одно сообщение нужно послать серверу, то пусть next message равно этому сообщению.

    5. Если did store key равно true и медиа-элемент ожидает ключа, то добавить задание для продолжения воспроизведения.

      Другими словами, продолжить воспроизведение, если необходимые ключи были предоставлены.

    6. Если next message — не null, то добавить задание для возбуждения простого события keymessage на объекте MediaKeySession.

      Событие — типа MediaKeyMessageEvent и имеет:

    7. Если did store key равно true, то добавить задание для возбуждения простого события на объекте MediaKeySession.

    8. Если любой из предыдущих шагов в задании провалился

      1. Создать новый объект MediaKeyError со следующими атрибутами:

        • code = подходящий код MediaKeyError
          systemCode = Key System-специфичное значение, если есть, или 0 в противном случае
      2. Установить атрибут error объекта MediaKeySession в значение объекта, созданного на предыдущем шаге.

      3. добавить задание по возбуждению простого события keyerror на объекте MediaKeySession.

      4. Отменить задание.

Процесс получения ключа может включать обработку событий keymessage web-страницей, посылку сообщения Key System-специфичному сервису и вызову update с ответным сообщением. update-вызовы могут создать события keyadded или keymessage. Во время этого процесса web-страница может пожелать отменить процесс получения ключей. Например, если страница не может связаться с сервисом лицензий из-за проблем в сети, то она может пожелать воспользоваться резервным вариантом — альтернативной ключевой системой. Страница вызывает close() для отмены сессии получения ключа.

Метод close() вызывает закрытие сессии получения ключа и очистку от всех ключей. Должны выполниться следующие шаги:

  1. Очистить все внутренние переменные, связанные с сессией, включая все ключи и лицензии.

Атрибут keySystem элемента HTMLSourceElement определяет Key System, используемую вместе с медиа-данные. Алгоритм выбора ресурса изменяется для проверки атрибута keySystem после шага 5 ветки Otherwise (Иначе) ветки 6:

  1. ⌛ If candidate has a keySystem attribute whose value represents a Key System that the user agent knows it cannot use with type, then end the synchronous section, and jump down to the failed step below.

2.1. Коды ошибок

Класс MediaError расширяется — добавляется новый тип ошибки.

partial interface MediaError {
  const unsigned short MEDIA_ERR_ENCRYPTED = 5;
};

interface MediaKeyError {
  const unsigned short MEDIA_KEYERR_UNKNOWN = 1;
  const unsigned short MEDIA_KEYERR_CLIENT = 2;
  const unsigned short MEDIA_KEYERR_SERVICE = 3;
  const unsigned short MEDIA_KEYERR_OUTPUT = 4;
  const unsigned short MEDIA_KEYERR_HARDWARECHANGE = 5;
  const unsigned short MEDIA_KEYERR_DOMAIN = 6;
  readonly attribute unsigned short code;
  readonly attribute unsigned long systemCode;
};
session . error . code

Возвратить код ошибки текущей ошибки из списка ниже.

session . error . systemCode

Возвратить системный код текущей ошибки.

Атрибут code интерфейса MediaError может дополнительно возвратить следующее:

MEDIA_ERR_ENCRYPTED (numeric value 5)
Поток не может быть воспроизведен, потому что зашифрован плюс следующее:
  1. Не предоставлен ключ и обработчик needkey
  2. Предоставленный ключ не мог быть успешно применен.
  3. Агент пользователя не поддерживает дешифровку этих медиа-данных

Атрибут code интерфейса MediaKeyError обязан возвращать код ошибки, один из следующих:

MEDIA_KEYERR_UNKNOWN (numeric value 1)
Произошла непредусмотренная ошибка. Это значение используется для ошибок, которые не подходят ни для одного из следующи кодов.
MEDIA_KEYERR_CLIENT (numeric value 2)
Ключевая Система не может быть установлена или обновлена.
MEDIA_KEYERR_SERVICE (numeric value 3)
Сообщение, переданное update указывает на ошибку от сервера лицензий.
MEDIA_KEYERR_OUTPUT (numeric value 4)
Нет доступных устройств для воспроизведения с необходимыми характеристиками для системы защиты контента.
MEDIA_KEYERR_HARDWARECHANGE (numeric value 5)
Изменение в конфигурации железа вызвало ошибку защиты контента.
MEDIA_KEYERR_DOMAIN (numeric value 6)
Произошла ошибка конфигурации multi-device domain licensing. Обычно эта ошибка — неудача присоединения к домену (join the domain).

Атрибут systemCode объекта MediaKeySession есть Key System-специфичный код произошедшей ошибки. Это позволяет возвратить более детальный статус чем более общий code. Он должен быть равен 0, если нет связанного статус-кода или подобный статус-код не поддерживается Ключевой Системой.

3. События

3.1. Определение событий

[Constructor(DOMString type, optional MediaKeyMessageEventInit eventInitDict)]
interface MediaKeyMessageEvent : Event {
  readonly attribute Uint8Array message;
  readonly attribute DOMString? destinationURL;
};

dictionary MediaKeyMessageEventInit : EventInit {
  Uint8Array message;
  DOMString? destinationURL;
};
[Constructor(DOMString type, optional MediaKeyNeededEventInit eventInitDict)]
interface MediaKeyNeededEvent : Event {
  readonly attribute Uint8Array? initData;
};

dictionary MediaKeyNeededEventInit : EventInit {
  Uint8Array? initData;
};
event . destinationURL

Возвращает URL, куда посылать message.

event . initData

Возвращает начальные данные, относящиеся к событию.

event . message

Возвращает посылаемое сообщение (например, запрос ключа).

Атрибут initData содержит начальные данные, специфичные для события.

Атрибут message содержит сообщение от CDM. Сообщения — Key System-специфичны. В большинстве случаев их следует посылать серверу ключей.

destinationURL — URL, куда посылать message. Приложение может переопределить это. В некоторых случаях он может быть храниться в медиа-данных. Он может быть равен null.

Если ответ (например, лицензия) необходим, то приложениям следует использовать один из новых методов для предоставления ответа.

3.2. Кратко о событии

Следующие события возбуждаются на объекте MediaKeySession.

Имя события Интерфейс Когда приходит... Предусловия
keyadded Event Ключ был добавлен в результате вызова update().
keyerror Event Случилась ошибка в сессии.
keymessage MediaKeyMessageEvent Сообщение было сгенерировано (и, вероятно, должно быть отправлено серверу). Например, запрос ключа был сгенерирован в результате вызова createSession() или другое сообщение должно быть послано в ответ на вызов update().

Следующее событие возбуждается на объекте HTMLMediaElement.

Имя события Интерфейс Когда приходит... Предусловия
needkey MediaKeyNeededEvent Агенту пользователя нужен ключ или лицензия для того, чтобы начать воспроизведение.

Может так случиться, чтомедиа-данные требуют дешифрования для загрузки или воспроизведения, либо новые ключ/лицензию для продолжения воспроизведения.
readyState равен HAVE_METADATA или больше. Возможно, что элемент воспроизводится или воспроизводился.

4. Избавление от ключа

Замечание: вопрос не закрыт, необходимо ли дальнейшее уточнение спецификации для этой функциональности. Смотрите Ошибку 17199.

4.1. Вступление

Этот раздел — неофициальный.

Вышеуказанные разделы (наверно нижеуказанные) оговаривают выдачу ключа/лицензии CDMу. Этот раздел оговаривает функционирование всего жизненного цикла ключа/лиценции, т.е. (и) надежное доказательство избавления от ключа. Варианты использования такого доказательства включают любой сервис, в условиях которого необходимо для сервиса знать, надежно, которые предоставленные ключи/лицензии все еще доступны для использования пользователем, и которые уже — нерабочие. Примеры включают в себя сервис с ограничениями на количество одновременных потоков, доступных для пользователя или сервис, где контент доступен на условиях аренды, для использования в автономном режиме.

Надежное доказательство избавление от ключа должно безусловно вовлекать CDM из-за относительной легкости, с которой скрипты могут быть изменены. CDM должно посылать сообщение, утверждающее, в CDM-специфичной форме, что данный ключ или лицензия были уничтожены. Подобные сообщения должны кэшироваться в CDM до тех пор, пока не получено подтверждение их доставки сервису. Это подтверждение должно также быть в форме CDM-специфичного сообщения.

Механизм надежного доказательства избавления от ключа функционирует вне действия любого медиа-элемента. Это так из-за того, что сообщения "доказательства избавления" могут быть кэшированы в CDM'ах после того, как связанные медиа-элементы были уничтожены. На сообщения "доказательство избавления" распространяются та же политика "правило ограничения домена" (same origin policy): они должны выдаваться только скриптам с того же домена, что и скрипт, который создал медиа-элемент, который предоставил ключ/лицензию.

5. Алгоритмы

5.1. Обнаружен зашифрованный блок

Следующие шаги выполняются, когда медиа-элемент находит блок (например, кадр), зашифрованных медиа-данных в процессе работы алгоритма получения ресурса:

  1. Let cdm be null.

  2. Let block initData be null.

  3. Let block key be null.

  4. If the block (or its parent entity) has Initialization Data, let block initData be that initialization data.

  5. Determine whether there is an active CDM by following the steps for the first matching condition from the following list:

    If the media element's keys attribute is not null
    Let cdm be the cdm loaded in the MediaKeys constructor.
    Otherwise
    Jump to the Key Presence step below.
  6. Use cdm to select the key:

    1. Let block key ID be null.

    2. If block initData is not null and contains a key ID, let block key ID be that ID.

    3. Select the key by following the steps for the first matching condition from the following list:

      If block key ID is not null

      Select the key by using cdm to follow the steps for the first matching condition from the following list:

      If cdm has a key cached for block key ID
      Let block key be the matching cached key.
      If cdm has a key cached with no ID (there can be one at most)
      Let block key be the single cached key.
      Otherwise (cdm has no keys cached OR has one or more keys cached, none of which have a matching key ID)
      Jump to the Key Presence step below.
      Otherwise

      Select the key by using cdm to follow the steps for the first matching condition from the following list:

      If cdm has a single key cached (with or without a key ID)
      Let block key be the single cached key.
      If cdm has more than one key cached (all would have IDs)
      Abort media element's resource fetch algorithm and run the steps to report a MEDIA_ERR_ENCRYPTED error.
      Otherwise
      Jump to the Key Presence step below.
  7. Key Presence: Handle the presence of a key by following the steps for the first matching condition from the following list:

    If cdm is not null and block key is not null.
    Use cdm to Decrypt the block using block key by following the steps for the first matching condition from the following list:
    If decryption fails
    Abort media element's resource fetch algorithm and run the steps to report a MEDIA_ERR_ENCRYPTED error.
    Otherwise
    Continue.

    Note: Not all decryption problems (i.e. using the wrong key) will result in a decryption failure. In such cases, no error is fired here but one may be fired during decode.

    If there is an event handler for needkey
    queue a task to fire a simple event named needkey at the media element.

    The event is of type MediaKeyNeededEvent and has:

    The media element is said to be potentially playing unless playback stops because the stream cannot be decrypted, in which case the media element is said to be waiting for a key.

    Otherwise
    Abort media element's resource fetch algorithm and run the steps to report a MEDIA_ERR_ENCRYPTED error.

For frame-based encryption, this may be implemented as follows when the media element attempts to decode a frame as part of the resource fetch algorithm:

  1. Let encrypted be false.

  2. Detect whether the frame is encrypted.

    If the frame is encrypted
    Run the steps above.
    Otherwise
    Continue.
  3. Decode the frame.

  4. Provide the frame for rendering.

Следующий параграф добавляется к Воспроизведение медиа-ресурса.

5.2. Обнаружен потенциально зашифрованный поток

Следующие шаги выполняются, когда медиа-элемент находит исходник, который может содержать зашифрованный блоки или потоки в процессе работы алгоритма получения ресурса:

  1. Let cdm be null.

  2. Let initData be null.

  3. If Initialization Data was encountered, let initData be that initialization data.

  4. Determine whether there is an active CDM by following the steps for the first matching condition from the following list:

    If the media element's keys attribute is not null
    Let cdm be the cdm loaded in the MediaKeys constructor.
    Otherwise
    Jump to the Need Key step below.
  5. Use cdm to determine whether the key is known:

    1. Let key ID be null.

    2. If a key ID for the source is known at this time, let key ID be that ID.

    3. If initData is not null and contains a key ID, let key ID be that ID.

    4. Determine whether the key is already known by following the steps for the first matching condition from the following list:

      If key ID is not null

      Determine whether the key is known by following the steps for the first matching condition from the following list:

      If there is a key cached for key ID
      Jump to the Continue Normal Flow step below.
      Otherwise
      Jump to the Need Key step below.
      Otherwise

      Determine whether the key is known by following the steps for the first matching condition from the following list:

      If there is a single key cached (with or without a key ID)
      Jump to the Continue Normal Flow step below.
      Otherwise
      Jump to the Need Key step below.
  6. Need Key: queue a task to fire a simple event named needkey at the media element.

    The event is of type MediaKeyNeededEvent and has:

    Firing this event allows the application to begin acquiring the key process before it is needed.

    Note that readyState is not changed and no algorithms are aborted. This event is merely informative.

  7. Continue Normal Flow: Continue with the existing media element's resource fetch algorithm.

5.3. Дополнение к алгоритму загрузки медиа-элементов

Следующие шаг добавляется к существующему алгоритму загрузки медиа-ресурса:

6. Простая дешифровка

Все агенты пользователя должны поддержать возможности простой дешифровки, описанной в данном разделе, независимо от того, поддерживают ли они более продвинутый CDM. Это гарантирует то, что есть общий уровень защиты, гарантированно поддержанный во всех агентах пользователя, включая те, что обладают полностью открытым кодом. Таким образом, провайдеры контента, которым нужна только базовая защита, могут создавать простые приложения, которые будут работать на всех платформах без необходимости работать с каким-либо провайдером защиты контента.

6.1. Clear Key (Ясный ключ)

Ключевая Система "org.w3.clearkey" указывает на то, что будет использоваться текстовый (незашифрованный) ключ для дешифровки исходника. Никакой дополнительной защиты контента на клиентской стороне не требуется. Использование этой Ключевой Системы описано ниже.

Параметр keySystem и атрибуты keySystem всегда равны "org.w3.clearkey". Строка sessionId состоит из цифр.

Атрибут initData события needkey и параметр initData вызова createSession() имеют один и тот же контейнеро-специфичный формат и значения. По потребности эти значения должны обеспечивать некоторого типа идентификацию контента или намек, как этот ключ мог быть получен (потому что не определяется логика его разбора/парсинга). Для контейнеров, которые поддерживают простой key ID, он должен быть бинарным массивом (?), содержащим непосредственно key ID. Для других контейнеров, это может быть неким другим блобом или null.

Событие MediaKeyMessageEvent, создаваемое createSession(), имеет:

Параметр key функции update() должен быть симметричным ключем в формате JSON Web Key (JWK) для дешифровки, как определено в IETF Internet-draft JSON Private and Symmetric Key specification. JSON-строка кодируется в Uint8Array с использованием ASCII-совместимой кодировки.

Если JWK значение атрибута 'key type' ("kty") равно 'octet sequence' ("oct"), то атрибут 'key value' ("k") должен быть байтовой последовательностью в кодировке base64, содержащей значение симметричного ключа.

Например, следующее содержит один симметричный ключ в виде JWK, предназначенный для использования в алгоритме AES Key Wrap (переносы строк — только для удобства чтения).

{
  "keys": 
    [{
      "kty":"oct",
      "alg":"A128KW",
      "kid":"67ef0gd8pvfd0=",
      "k":"GawgguFyGrWKav7AX4VKUg"
    }]
}

7. Указания по контейнерам

Этот документ описывает поведение, независимое от специфических медиа-контейнеров. Следующие разделы предоставляют контейнеро-специфичные детали для реализаций, которые решили поддерживать такие контейнеры.

7.1 WebM

Этот раздел определяет формат потока и Начальные Данные для реализаций, которые решил поддерживать WebM.

7.1.1. Формат потока

Зашифрованные WebM-потоки шифруются на уровне блоков шифром AES-128 CTR. Контейнер должен включать соответствующие значения внутри элемента ContentEncryption.

WebM-потоки могут быть зашифрованы частично, как на уровне Дорожек, так и на уровне блоков. В первом случае подможество дорожке в потоке содержат элемент ContentEncryption. Во втором случае, подможество блоков внутри дорожки, содержащей ContentEncryption, помечаются как зашифрованные.

7.1.2. Обнаружение шифрования

Когда WebM-Дорожка (Track) парсится, присутствие элемента ContentEncKeyID указывает, что поток потенциально зашифрован.

Зашифрованные блоки — те, что помечены зашифрованными посредством Signal-байта.

7.1.3. Начальные данные (Initialization Data) и события

Начальные данные в событиях всегда есть key ID, который равен ContentEncKeyID текущей Дорожки. Текущая дорожка — та, что сейчас парсится, либо та, что содержит дешифруемый блок.

События содержат только единственный key ID. Однако, если поддержано Ключевой Системой, несколько key ID-ов могут быть собраны приложением перед запросом ключа и несколько key ID-ключевых пар могут быть возвращены сервером лицензий.

Событие будет возбуждено для каждого нового key ID (из ContentEncKeyID), для которого ключ еще не известен.

7.2 ISO Base Media File Format

This section defines the stream format and initialization data for ISO Base media File Format (ISOBMFF) content.

7.2.1 Stream format

The stream format is dependent upon the protection scheme, as defined in the scheme type box ('schm').

For example, under the common encryption ("cenc") protection scheme, ISOBMFF content is encrypted at the sample level with AES-128 CTR encryption, according to ISO/IEC 23001-7:2012, "Information technology - MPEG system technologies - Part 7: Common encryption in ISO base media file format files". This protection method enables multiple Key Systems to decrypt the same media content.

7.2.2 Detecting Encryption

Protection scheme signaling conforms with ISO/IEC 14496-12. When protection has been applied, the stream type will be transformed to 'encv' for video or 'enca' for audio, with a scheme information box ('sinf') added to the sample entry in the sample description box ('stsd'). The scheme information box ('sinf') will contain a scheme type box ('schm') with a scheme_type field set to the 4CC value of the protection scheme.

Additionally, if the protection scheme is common encryption ("cenc"), the "encrypted block" is a sample. Determining whether a sample is encrypted depends on the corresponding track encryption box ('tenc') and the sample group associated with the sample. In this case the default encryption state of a sample is defined by the IsEncrypted flag in the associated track encryption box ('tenc'). This default state may be modified by the IsEncrypted flag in the Sample Group Description Box ('sgpd'), pointed to by an index in the Sample to Group Box ('sbgp').

For complete information about "cenc" see ISO/IEC 23001-7:2012.

7.2.3 Initialization Data and Events

For ISOBMFF the InitData begins with a the protection scheme information box ('sinf'). The 'sinf' includes the scheme type box ('schm'), giving the scheme_type, and the scheme information box ('schi').

If this scheme_type is common encryption ("cenc"), the scheme information box will also contain the track encryption box ('tenc'), giving the defaults for IsEncrypted, IV_size and KID for that track. In addition, one or more protection system specific heder boxes ('pssh') will be concatenated after the 'sinf' box.

In a file encrypted with common encryption, each key is identified by a Key ID and each encrypted sample is associated with the Key ID of the key needed to decrypt it. This association is signaled either through the specification of a default Key ID in the track encryption box ('tenc') or by assigning the sample to a Sample Group, the definition of which specifies a Key ID. Common encryption files may contain a mixture of encrypted and unencrypted samples. Playback of unencrypted samples should not be impeded by unavailability of the keys needed to decrypt other samples in the same file or track.

Note that if there is already an active Key System CDM and the key storage for that Key System already contains the key associated with the Key ID, there is no need to generate a needkey event.

8. Примеры

Этот раздел и его подразделы - неофициальные.

Этот раздел содержит примеры-решения для различных случаев использования предлагаемых расширений. Это не единственные решения для данных случаев. Видео-элементы использованы в примерах, но то же самое может быть применено для всех медиа-элементов. В некоторых моментах, таких как использование синхронного XHR, примеры упрощены для того, чтобы держать внимание на расширения.

8.1. Исходник и ключ известны на момент загрузки страницы (шифрование Clear Key)

В этом простом примере исходный файл и ключ clear-text жестко закодированы в страницу.

Этот пример очень прост, потому что он не заботится о том, когда ключ был добавлен или как он связывает тот момент с вызовом update(). Он также не обрабатывает ошибки.

<script>
  function load() {
    var video = document.getElementById("video");

    if (!video.keys)
      video.keys = video.MediaKeys("org.w3.clearkey");
    if (!video.keys)
      throw "Could not create MediaKeys";

    var keySession = video.keys.createSession();
    if (!keySession)
      throw "Could not create key session";

    keySession.onkeymessage="handleMessage(event)";
  }

  function handleMessage(event) {
    var keySession = event.target;

    var key = new Uint8Array([ ... ]);
    keySession.update(key);
  }
</script>

<body onload="load()">
  <video src="foo.webm" autoplay id="video"></video>
</body>

8.2. Исходник известен, а ключ — нет на момент загрузки

В этом примере начальные данные содержатся в медиа-данных. Если бы это было не так, то handleKeyNeeded() мог бы получить и предоставить их вместо получения их из события.

Любая требуемая асинхронная операция в handleKeyNeeded() для получения ключа может быть вызвана повторно, если поток определен как потенциально зашифрованный, перед тем как произойдет парсинг зашифрованного блока/кадра. В этом случае приложения могут захотеть обрабатывать повторные вызовы специальным образом для того, чтобы избежать повторных запросов лицензии. Это не показано в примерах ниже.

8.2.1. Шифрование Clear Key

Это решение использует простую дешифровку типа Clear Key.

Как и в предыщуем примере, этот очень прост, потому что он не заботится о том, когда ключ был добавлен или об обработке ошибок.

<script>
  function handleKeyNeeded(event) {
    var video = event.target;
    var initData = event.initData;

    if (!video.keys)
      video.keys = video.MediaKeys("org.w3.clearkey");
    if (!video.keys)
      throw "Could not create MediaKeys";

    var keySession = video.keys.createSession(mimeType, initData);
    if (!keySession)
      throw "Could not create key session";

    keySession.onkeymessage="handleMessage(event)";
  }

  function handleMessage(event) {
    var keySession = event.target;
    var message = event.message;

    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("POST", "http://.../getkey", false);
    xmlhttp.send(message);
    var key = new Uint8Array(xmlhttp.response);
    keySession.update(key);
  }
</script>

<video src="foo.webm" autoplay onneedkey="handleKeyNeeded(event)"></video>

8.2.2. Другой модуль дешифровки контента (CDM)

Это решение использует более продвинутое дешифрование из воображаемого CDM, названного Some System.

<script>
  function handleKeyNeeded(event) {
    var video = event.target;
    var initData = event.initData;

    if (!video.keys)
      video.keys = video.MediaKeys("com.example.somesystem.1_0");
    if (!video.keys)
      throw "Could not create MediaKeys";

    var keySession = video.keys.createSession(mimeType, initData);
    if (!keySession)
      throw "Could not create key session";

    keySession.onkeymessage="licenseRequestReady(event)";
  }

  function licenseRequestReady(event) {
    var keySession = event.target;
    var request = event.message;
    if (!request)
      throw "Could not create license request";

    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("POST", "http://.../getkey", false);
    xmlhttp.send(request);
    var license = new Uint8Array(xmlhttp.response);
    keySession.update(license);
  }
</script>

<video src="foo.webm" autoplay onneedkey="handleKeyNeeded(event)"></video>

8.3. Выбор поддерживаемой Ключевой Системы

Ниже — пример обнаружения поддерживаемой Key System, который использует isTypeSupported() и выбирает один из вариантов.

<script>
  var keySystem;
  var licenseUrl;

  function selectKeySystem() {
    if (MediaKeys.isTypeSupported("video/webm; codecs='vp8, vorbis'", "com.example.somesystem")) {
      licenseUrl = "https://license.example.com/getkey"; // OR "https://example.<My Video Site domain>"
      if (MediaKeys.isTypeSupported("video/webm; codecs='vp8, vorbis'", "com.example.somesystem.2_0")) {
        keySystem = "com.example.somesystem.2_0";
      } else if (MediaKeys.isTypeSupported("video/webm; codecs='vp8, vorbis'", "com.example.somesystem.1_5")) {
        keySystem = "com.example.somesystem.1_5";
      }
    } else if (MediaKeys.isTypeSupported("video/webm; codecs='vp8, vorbis'", "foobar")) {
      licenseUrl = "https://license.foobar.com/request";
      keySystem = "foobar";
    } else {
      throw "Key System not supported";
    }
  }

  function handleKeyNeeded(event) {
    var video = event.target;
    var initData = event.initData;

    if (!video.keys) {
      selectKeySystem();
      video.keys = video.MediaKeys(keySystem);
    }
    if (!video.keys)
      throw "Could not create MediaKeys";

    var keySession = video.keys.createSession(mimeType, initData);
    if (!keySession)
      throw "Could not create key session";

    keySession.onkeymessage="licenseRequestReady(event)";
  }
  
  function licenseRequestReady(event) {
    var keySession = event.target;
    var request = event.message;
    if (!request)
      throw "Could not create license request";

    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("POST", licenseUrl, false);
    xmlhttp.send(request);
    var license = new Uint8Array(xmlhttp.response);
    keySession.update(license);
  }
</script>

<video src="foo.webm" autoplay onneedkey="handleKeyNeeded(event)"></video>

8.4. Используя все события

Это ­— более полный пример, показывающий использование всех событий вместе с асинхронным XHR.

Заметим, что handleKeyMessage может быть вызван несколько раз, включая моменты вызоваupdate(), если требуется несколько циклов посылки сообщений/получения ответа по какой-то причине, связанной с Ключевой Системой.

<script>
  var keySystem;
  var licenseUrl;

  function handleMessageResponse() {
    var license = new Uint8Array(xmlhttp.response);
    this.keySession.update(license);
  }
  
  function sendMessage(message, keySession) {
    xmlhttp = new XMLHttpRequest();
    xmlhttp.keySession = keySession;
    xmlhttp.onreadystatechange = handleMessageResponse;
    xmlhttp.open("POST", licenseUrl, true);
    xmlhttp.send(message);
  }

  function handleKeyMessage(event) {
    var keySession = event.target;
    var message = event.message;
    if (!message)
      throw "Invalid key message";
  
    sendMessage(message, keySession);
  }

  function handleKeyComplete(event) {
    // Do some bookkeeping with event.target.sessionId if necessary.
  }

  function handleKeyError(event) {
    // Report event.target.error.code and event.target.error.systemCode,
    // and do some bookkeeping with event.target.sessionId if necessary.
  }

  function handleKeyNeeded(event) {
    var video = event.target;
    var initData = event.initData;

    if (!video.keys) {
      selectKeySystem();  // See previous example for implementation.
      video.keys = video.MediaKeys(keySystem);
    }
    if (!video.keys)
      throw "Could not create MediaKeys";

    var keySession = video.keys.createSession(mimeType, initData);
    if (!keySession)
      throw "Could not create key session";

    keySession.onkeymessage="handleKeyMessage(event)";
    keySession.onkeyadded="handleKeyComplete(event)";
    keySession.onkeyerror="handleKeyError(event)";
  }
</script>

<video src="foo.webm" autoplay onneedkey="handleKeyNeeded(event)"></video>

9. Часто задаваемые вопросы

Этот раздел и его подразделы - неофициальные.

9.1. Варианты использования

Каким вариантам использования содействует данная спецификация?

Любым, начиная от пользовательского контента для совместного использования в семье (пользователь не (может) являться злоумышленником) до онлайн-радио и полнометражных фильмов.

Совместимо ли данное предложение с адаптивным вещанием (adaptive streaming)?

Да, это предложение совместимо с обоими "Type 1" и "Type 3" W3C Web & TV Interest Group.

Поддерживается ли смена ключей?

Да.

Могу я зашифровать субтитры/<track>-элементы?

Нет, это предложение касается дешифровки только аудио и видео как частей медиа-данных.

Могу я разрешить агенту пользователя выбрать подходящий CDM, используя элементы <source>?

Да, задействовав атрибут keySystem элемента HTMLSourceElement. Вместе с использованием атрибута type это задаст первый <source>-элемент (контейнер, кодес и Key System), которые агент пользователя поддерживает.

Поддерживается ли heartbeat?

Да.

Heartbeat — режим работы, когда CDM требует получения явного heartbeat-сообщения от своего сервера на регулярной основе, в ином случае дешифрование блокируется. Это включает варианты использования, требующие строгого online-контроля за доступом к контенту. Heartbeat должен быть поддержан в CDM и реализован в этом случае с использованием срока истечения действия или продолжительностью действия, взятыми из лицензии, которые доставляются CDM. До истечения лицензии CDM обязан инициировать новый обмен сообщениями для получения обновленной лицензии.

9.2. Использование

Могу я посылать токен зашедшего пользователя в систему вместе с запросом лицензии?

Да. Приложение может добавить его к запросу лицензии (посылаемым посредством XMLHttpRequest в примерах) или посылать его CDM посредством createSession() с последующим включением его в запрос лицензии.

Как я могу продолжить воспроизведение после получения события needkey в алгоритме Обнаружен зашифрованный блок?

При условии отсутствия других проблем воспроизведение продолжится, когда необходимый ключ будет предоставлен с помощью update() и последний будет выполнен.

Может ли приложение использовать несколько провайдеров защиты контента/Key System?

Да, вероятно это будет необходимо для поддержки всех или большинства агентов пользователя. Приложение может также использовать различные Ключевые Системы на одном агенте пользователя для различных целей.

Может ли HTMLMediaElement использовать различные Ключевая Системаы в одно и то же время?

Нет.

Как я могу добавить поддержку для некоторого CDM в моем приложении?

Мы предполагаем, что провайдеры CDM будут создавать JavaScript-библиотеки, которые разработчики приложений смогут включать. isTypeSupported() поэтому может быть использован для выбора из поддерживаемых библиотек.

Как я могу определить, что агент пользователя поддерживает особые возможности для данного провайдера?

Это вендоро-/Key System-специфично.

Получение этой информации может занять время и нет простого решения, поэтому isTypeSupported() не подходит для этого. Также нет способа для isTypeSupported() подтвердить некие возможности в любом случае.

Чему равен URL лицензий (licenseUrl) в примерах?

Это URL сервера, способного предоставить ключ для потока, обычно с использованием начальные данныех и часто после проверки запрашивающего пользователя. URL специфичен относительно приложения и/или Key System и может быть равен провайдеру контента или провайдеру Key System, в зависимости от выбранного решения.

(Вот) это все слишком сложно и трудно для использования.

Это не вопрос, но в любом случае мы постараемся это учесть. Как показано в примерах, базовые варианты использования достаточно просты и требуют лишь немного действий для получения ключа и предоставления его клиенту. Мы считаем, что большинство малых контент-сайтов может добавить базовую защиту для своих приложений с минимальными усилиями.

Для более сложных вариантов, таких как быстрый доступ к первому кадру и различные алгоритмы управления лицензиями, требуют более сложного кода, но защита контента профессионального уровня сложна и это ожидаемо. Защита контента профессионального уровня требует серверной поддержки и работы с одним или более провайдером защиты контента, так что это ненамного усложняет. На самом деле, если вы реализуете немного (из вышесказанного), то это будет работать на любой браузерно-основанной платформе, без необходимости отдельных решений для каждой платформы и на сервере, и на клиенте. Фиксированное множество интерфейсов, скорее всего, даже приведет к более устойчивым моделям и поведениям в различных ситуациях. Как правило, б́ольшие требования имеют большие провайдеры контента, и мы считаем, что они имеют достаточно ресурсов для реализации приложений, которые будут отвечать их требованиям.

Провайдерам CDM потребуется предоставить детальные спецификации о действиях и событиях для помощи провайдерам контента в написании алгоритмов в их приложениях. Они также могут предоставить JavaScript-библиотеки для своих предложений, которые можно будет интегрировать в любое приложение. Приложение могло бы, по сути, выбрать решение и делегировать большую часть работы соответ. библиотеке.

9.3. API

Как устанавливаются алгоритмы дешифрования?

Это — специфика контейнера. Контейнер может стандартизировать конкретный алгоритм (например, AES-128) и/или разрешить его прописывать. Агент пользователя должен знать и/или обнаружить, какой алгоритм использовать с ключем, полученным посредством данного API.

Каковы преимущества ведения лицензирования/обмена ключами в приложении?

Преимущества включают в себя:

Почему Key System — не часть типа MIME (подобно кодекам)?

Во многих случаях (и особенно в направлении, куда движутся провайдеры и стандарты) поток не привязывается к конкретной Key System или провайдеру. Несколько Ключевых Систем может быть использовано для дешифровки одного и того же однотипного потока. Таким образом, Key System есть не информация о файле и ей не следует быть частью MIME-типа.

Есть сомнения в том, что алгоритм шифрования (например, AES-128) и конфигурирование должен быть частью MIME-типа. Для этого предложения подобное не важно, поэтому это здесь не рассматривается.

Почему необходимы дополнительные события?

Хотя многие варианты использования могут быть реализованы без дополнительного события (требованием предоставить от приложения всю информацию заранее), в некоторых случаях будет лучше с событием.

Почему нам необходим новый код MediaError?

Без нового кода ошибки (MEDIA_ERR_ENCRYPTED) невозможно ясно объяснить для агента пользователя приложению, что воспроизведение не удалось, потому что контент был зашифрован и, вероятно, агентам пользователя потребуется возбуждать MEDIA_ERR_DECODE или MEDIA_ERR_SRC_NOT_SUPPORTED, что вводило бы в заблуждение.

Будет ли ввод нового кода ошибки MediaError ломать существующие приложения?

Приложения, не знающие о новом коде ошибки (MEDIA_ERR_ENCRYPTED) могут неправильно обрабатывать его, но они все равно смогут обнаружить, что произошла ошибка, потому что а) было возбуждено событие об ошибке и б) media . error не равен null.

Что произойдет, если ответ на событие needkey от обнаружения потенциально зашифрованного потока не получен прежде обнаружения зашифрованного блока?

Алгоритм Обнаружен зашифрованный блок будет продолжаться в обычном режиме. Если не будет предоставлен подходящий ключ, то будет возбуждено второе событие needkey и декодирование будет остановлено.

То же самое событие needkey с теми же самыми атрибутами возбуждается для обоих Обнаружен зашифрованный блок и Обнаружен потенциально зашифрованный поток. Как приложение может отличить эти два?

Одно и то же событие использовано намеренно для уменьшения сложности приложений. В идеале, они не должны были бы знать.

Что если ключ/лицензия для одних и тех же начальных данных (т.е. key ID) выдается более чем один раз для update()?

CDM заменит предыдущие записи, обновив порядок ключей в целом, чтобы отразить то, что этот key ID был добавлен самым последним. Другими словами, простой замены сущ. ключа не достаточно. Точный алгоритм описан в update().

9.4. Исходник, контейнеры и потоки

Каки контейнеры и кодеки поддерживаются?

Контейнеры и кодеки не перечисляются. Агент пользователя может поддержать дешифрование любого контейнера и кодека, какого захочет.

Если агент пользователя поддерживает дешифрование пары контейнер/кодек (как написано в isTypeSupported()), то он также должен поддержать Simple Decryption c той парой.

Что если контейнер/кодек не поддерживает обнаружение того, что поток или блок зашифрован?

Приложение должно использовать update() для указания того, что поток зашифрован и обеспечить ключами прежде, чем декодирование начнется.

Должен ли контейнер предоставлять начальные данные или key ID контента?

В идеале да, но API поддерживает и вариант, когда приложение посылает начальные данные или ID напрямую (серверу) или предоставляет их CDM посредством createSession().

Что если контейнер не поддерживает указание на то, что поток или кадр/блок зашифрован?

Приложению необходимо будет использовать какой-либо другой механизм для выбора подходящего ключа для контента. Агент пользователя сможет использовать только один ключ в один момент. Смена ключей будет гораздо более сложной или невозможной.

Могу ли я использовать различные ключи для каждого отдельного потока (адаптивное вещание)?

Да, хотя вы возможно захотите подумать о недостатках (сложность и производительность). Для лучшего пользовательского опыта вам нужно будет предоставлять ключи для потоков агента пользователя до переключения.

Какие элементы исходника шифруются?

Это зависит от используемого контейнера/кодека. Данное предложение занимается всеми случаями, включая полностью зашифрованные потоки, отдельные кадры, зашифрованные отдельно, группы зашифрованных кадров и части зашифрованных кадров. Если не все блоки/кадры зашифрованы, то агент пользователя должен уметь легко обнаружить это, либо по знаку в контейнеру, либо по кадру/блоку.

Все ли блоки/кадры в потоке должны быть зашифрованы?

Нет, зависит от ограничений контейнера/кодека.

Какой шифр и параметры должны быть использованы для дешифровки?

Шифр и параметры должны быть неявно в контейнере или задаваться в контейнере. Если что-то опционально, то приложение должно знать, что поддерживается CDM.

Какой шифр и параметры должны быть использованы для Простой дешифровки? Который (шифр) должен поддержать агент пользователя?

Как и в предыдущем вопросе, все это должно быть неявно в контейнере или задаваться в контейнере. Агенты пользователя должны поддерживать любой шифр и параметры по умолчанию или базовый, из спецификации контейнера. Практически же агентам пользователя следует поддерживать все шифры и параметры, обычно используемые с контейнером.

9.5. Защита контента и ключа

Могу я гарантировать, что ключ контента защищен, без взаимодействия с провайдером защиты контента?

Нет. Защита ключа контента требовала бы, что медийный стек браузера обладал бы некоторым секретом, который не может быть легко получен. Это вещь такого рода, что обеспечивают DRM-решения. Создание стандартного механизма для поддержки этого выходит за рамки стандартов HTML5 и подобное следует отдать для разрешения специальным агентам пользователя. Кроме того, это немного не то, что могли бы поддержать полностью открытые браузеры "из коробки".

Контент, защищенный с использованием данного предложения без провайдера защиты контента, все еще более защищен, чем выдача незашифрованного файла через HTTP или HTTPS. Мы также утверждаем, что данное предложение не менее безопасно, чем зашифрованный HLS. Для продолжительных потоков смена ключей может обеспечить дополнительную защиту.

Также возможно расширить предложенную спецификацию в будущем поддержкой более функционального базового варианта без изменения API.

Может ли агент пользователя поддерживать несколько провайдеров защиты контента?

Да. Приложение сможет запросить возможности агента пользователя и выбрать Key System для использования.

Может ли агент пользователя защитить сжатый контент?

Да, это предложение естественным образом поддерживает такую ​​защиту.

Может ли агент пользователя защитить путь отображения или незашифрованный контент после декодирования?

Да, агент пользователя мог бы использовать платформо-специфичные возможности для защиты пути отображения.

10. История изменений

Версия Комментарий
14 января 2013 Выпущен кандидат FPWD (First Public Working Draft).
16 августа 2012 Преобразовано в объектно-ориентированное API.
0.1b Последняя не объектно-ориентированная ревизия.
0.1a Исправляет мелкие ошибки в 0.1
0.1 Начальное предложение