암호화 미디어 확장

W3C 작업 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/WD-encrypted-media-2-20260515/
최신 발행 버전:
https://www.w3.org/TR/encrypted-media-2/
최신 편집자 초안:
https://w3c.github.io/encrypted-media/
이력:
https://www.w3.org/standards/history/encrypted-media-2/
커밋 이력
구현 보고서:
https://w3c.github.io/test-results/encrypted-media/all.html
최신 권고안:
https://www.w3.org/TR/2017/REC-encrypted-media-20170918/
편집자:
Joey Parrish (Google Inc.)
Greg Freedman (Netflix Inc.)
이전 편집자:
Mark Watson (Netflix Inc.) (2019년 9월까지)
David Dorwin (Google Inc.) (2017년 9월까지)
Jerry Smith (Microsoft Corporation) (2017년 9월까지)
Adrian Bateman (Microsoft Corporation) (2014년 5월까지)
피드백:
GitHub w3c/encrypted-media (풀 리퀘스트, 새 이슈, 열린 이슈)
public-media-wg@w3.org 에 제목 줄을 [encrypted-media-2] … 메시지 주제 …로 하여 보내기 (아카이브)

초록

이 명세는 HTMLMediaElement [HTML]을 확장하여 암호화된 콘텐츠의 재생을 제어하는 API를 제공한다.

이 API는 단순한 클리어 키 복호화부터 고부가가치 비디오까지 (적절한 사용자 에이전트 구현이 주어진 경우) 다양한 사용 사례를 지원한다. 라이선스/키 교환은 애플리케이션이 제어하며, 다양한 콘텐츠 복호화 및 보호 기술을 지원하는 견고한 재생 애플리케이션의 개발을 촉진한다.

이 명세는 콘텐츠 보호 또는 디지털 저작권 관리 시스템을 정의하지 않는다. 그 대신 이러한 시스템 및 더 단순한 콘텐츠 암호화 시스템을 발견하고, 선택하고, 상호작용하는 데 사용할 수 있는 공통 API를 정의한다. 이 명세를 준수하기 위해 디지털 저작권 관리를 구현할 필요는 없다. 공통 기준선으로 구현이 요구되는 것은 Clear Key 시스템뿐이다.

공통 API는 단순한 콘텐츠 암호화 기능 집합을 지원하며, 인증 및 권한 부여와 같은 애플리케이션 기능은 페이지 작성자에게 맡긴다. 이는 암호화 시스템과 라이선스 또는 기타 서버 간의 대역 외 통신을 가정하는 대신, 콘텐츠 보호 시스템별 메시징을 페이지가 중개하도록 요구함으로써 달성된다.

이 문서의 상태

이 절은 이 문서가 발행된 시점의 상태를 설명한다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있다.

2017년 9월W3C 권고안으로 발행된 이후 두 가지 새 기능이 추가되었다:

다른 기능의 포함은 Media Working Group의 범위를 벗어난다. 편집상의 업데이트에 더하여, 이 명세에 가해진 다른 실질적 변경은 이 명세에 대한 유지보수 이슈를 다룬다:

이전 버전 이후 이루어진 변경의 전체 목록은 커밋을 참고한다.

이 문서는 Media Working Group권고안 트랙을 사용하여 작업 초안으로 발행했다.

작업 초안으로 발행되었다는 사실이 W3C와 그 회원의 승인을 의미하지는 않는다.

이 문서는 초안 문서이며 언제든지 다른 문서로 업데이트, 대체 또는 폐기될 수 있다. 진행 중인 작업 이외의 것으로 이 문서를 인용하는 것은 부적절하다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹이 작성했다. W3C는 이 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지한다. 해당 페이지에는 특허를 공개하기 위한 지침도 포함되어 있다. 어떤 개인이 필수 청구항을 포함한다고 믿는 특허를 실제로 알고 있는 경우, 그 개인은 W3C 특허 정책 6절에 따라 그 정보를 공개해야 한다.

이 문서는 2025년 8월 18일 W3C Process Document의 적용을 받는다.

1. 소개

이 절은 비규범적이다.

이 명세는 스크립트가 콘텐츠 보호 메커니즘을 선택하고, 라이선스/키 교환을 제어하며, 사용자 정의 라이선스 관리 알고리즘을 실행할 수 있게 한다. 각 사용 사례마다 각 사용자 에이전트에서 클라이언트 측 수정을 요구하지 않고도 광범위한 사용 사례를 지원한다. 이를 통해 콘텐츠 제공자는 모든 기기에 대한 단일 애플리케이션 솔루션을 개발할 수 있다.

지원되는 콘텐츠는 컨테이너별 "공통 암호화" 명세에 따라 암호화되며, 키 시스템 전반에서 사용할 수 있게 한다. 지원되는 콘텐츠는 암호화되지 않은 컨테이너를 가지므로, 메타데이터를 애플리케이션에 제공할 수 있고 다른 HTMLMediaElement 기능과의 호환성을 유지할 수 있다.

구현자는 이 명세에서 설명하는 보안 및 개인정보 보호 위협과 우려 사항에 대한 완화책에 주의를 기울여야 한다. 특히 보안 및 개인정보 보호에 대한 명세 요구사항은 키 시스템과 그 구현의 보안 및 개인정보 보호 속성을 알지 못하면 충족할 수 없다. 8. 구현 요구사항에는 기반 키 시스템 구현의 통합 및 사용과 관련된 보안 및 개인정보 보호 조항이 포함되어 있다. 10. 보안은 입력 데이터 또는 네트워크 공격과 같은 외부 위협에 초점을 맞춘다. 11. 개인정보 보호는 사용자별 정보의 처리와 사용자에게 자신의 개인정보에 대한 충분한 제어를 제공하는 데 초점을 맞춘다.

참고

이 명세는 미디어 데이터의 출처와 독립적이지만, 작성자는 많은 구현이 Media Source Extensions [MEDIA-SOURCE]를 통해 제공되는 미디어 데이터의 복호화만 지원한다는 점을 알고 있어야 한다.

API를 사용하여 구현된 일반적인 스택이 아래에 표시되어 있다. 이 다이어그램은 예시 흐름을 보여 주며, API 호출과 이벤트의 다른 조합도 가능하다.

제안된 API를 사용하여 구현된 일반적인 스택

2. 정의

콘텐츠 복호화 모듈 (CDM)

콘텐츠 복호화 모듈(CDM)은 하나 이상의 키 시스템에 대해 복호화를 포함한 기능을 제공하는 클라이언트 구성요소이다.

참고

구현은 CDM의 구현을 분리할 수도 있고 분리하지 않을 수도 있으며, 사용자 에이전트와 별개로 취급할 수도 있다. 이는 API와 애플리케이션에 투명하다.

키 시스템

키 시스템은 복호화 메커니즘 및/또는 콘텐츠 보호 제공자를 가리키는 일반 용어이다. 키 시스템 문자열은 키 시스템의 고유한 식별을 제공한다. 이 문자열은 사용자 에이전트가 CDM을 선택하고 키 관련 이벤트의 출처를 식별하는 데 사용된다. 사용자 에이전트는 공통 키 시스템을 지원해야 MUST 한다. 사용자 에이전트는 해당 키 시스템 문자열과 함께 추가적인 CDM도 제공할 수 MAY 있다.

키 시스템 문자열은 항상 역방향 도메인 이름이다. 키 시스템 문자열은 대소문자를 구분하여 비교된다. CDM은 단순한 소문자 ASCII 키 시스템 문자열을 사용하는 것이 권장된다 RECOMMENDED.

참고

예를 들어, "com.example.somesystem".

참고

주어진 시스템(예시의 "somesystem") 내에서 하위 시스템은 키 시스템 제공자가 결정한 대로 정의될 수 있다. 예를 들어, "com.example.somesystem.1" 및 "com.example.somesystem.1_5". 키 시스템 제공자는 이 문자열들이 비교 및 발견에 사용된다는 점을 염두에 두어야 하므로, 비교하기 쉬워야 하며 구조는 합리적으로 단순하게 유지되어야 한다.

키 세션

키 세션, 또는 단순히 세션은 CDM과의 메시지 교환을 위한 컨텍스트를 제공하며, 그 결과 키가 CDM에 제공된다. 세션은 MediaKeySession 객체로 구체화된다. 각 키 세션은 generateRequest() 호출에 제공된 단일 초기화 데이터 인스턴스와 연결된다.

각 키 세션은 단일 MediaKeys 객체와 연결되며, 해당 MediaKeys 객체와 연결된 미디어 요소만 세션과 연결된 키에 접근할 수 있다. 다른 MediaKeys 객체, CDM 인스턴스 및 미디어 요소는 키 세션에 접근하거나 그 키를 사용해서는 안 된다 MUST NOT. 키 세션과 그 안에 포함된 키는 MediaKeySession 객체가 파괴되는 경우를 포함하여 세션이 닫히면 더 이상 복호화에 사용할 수 없다.

키 세션과 연결되어 있고 명시적으로 저장되지 않은 모든 라이선스와 키는 키 세션이 닫힐 때 파괴되어야 MUST 한다.

키 ID는 세션 내에서 고유해야 MUST 한다.

세션 ID

세션 ID는 CDM이 생성한 고유 문자열 식별자로, 애플리케이션이 MediaKeySession 객체를 식별하는 데 사용할 수 있다.

사용자 에이전트와 CDM이 새 세션을 성공적으로 생성할 때마다 새 세션 ID가 생성된다.

각 세션 ID는 그것이 생성된 브라우징 컨텍스트 내에서 고유해야 SHALL 한다. 영속 세션 타입인가? 알고리즘이 true를 반환하는 세션 타입의 경우, 세션 ID는 브라우징 세션 전반을 포함하여 시간에 따라 출처 내에서 고유해야 MUST 한다.

참고

기반 콘텐츠 보호 프로토콜이 반드시 세션 ID를 지원할 필요는 없다.

달리 명시되지 않는 한, 키는 미디어 데이터 내의 블록을 복호화하는 데 사용할 수 있는 복호화 키를 가리킨다. 이러한 각 키는 키 ID에 의해 고유하게 식별된다. 키는 그것을 CDM에 제공하는 데 사용된 세션과 연결된다. (같은 키가 여러 세션에 존재할 수 있다.) 이러한 키는 update() 호출을 통해서만 CDM에 제공되어야 MUST 한다. (이후에는 저장된 세션 데이터의 일부로 load()에 의해 로드될 수 있다.)

모범 사례 1: 암호화된 미디어를 패키징할 때는, 실질적으로 다른 정책의 적용이 필요한 각 스트림 집합을 고유한 키(및 키 ID)로 암호화한다.

예를 들어, 두 비디오 해상도 사이에 정책이 다른 경우 각 스트림 집합은 고유한 키로 암호화되므로 정책을 독립적으로 적용할 수 있다. 마찬가지로, 오디오 스트림과 비디오 스트림은 정책이 서로 다를 때 고유한 키를 사용한다. 정책 그룹 간에 키를 공유하면 독립적인 적용이 불가능해지므로, 정책 그룹별 고유 키는 클라이언트 전반에서 적용과 호환성을 보장하는 유일한 방법이다.

복호화에 사용 가능

CDM이 해당 키가 현재 미디어 데이터의 하나 이상의 블록을 복호화하는 데 사용할 수 있다고 확신하는 경우, 키는 복호화에 사용할 수 있는 것으로 간주된다.

예를 들어, 라이선스가 만료된 경우 키는 복호화에 사용할 수 없다. 라이선스가 만료되지 않았더라도, 키 사용을 위한 다른 조건(예: 출력 보호)이 현재 충족되지 않으면 키는 복호화에 사용할 수 없다.

키 ID

는 옥텟 시퀀스이며 해당 키를 고유하게 식별하는 키 ID와 연결된다. 컨테이너는 미디어 데이터 안의 블록 또는 블록 집합을 복호화할 수 있는 키의 ID를 지정한다. 초기화 데이터에는 미디어 데이터를 복호화하는 데 필요한 키를 식별하기 위한 키 ID가 포함될 MAY 있다. 그러나 초기화 데이터가 미디어 데이터 또는 미디어 리소스에서 사용되는 일부 또는 모든 키 ID를 포함해야 한다는 요구사항은 없다. 라이선스CDM에 제공될 때 각 키를 키 ID와 연결하므로, CDM은 암호화된 미디어 데이터 블록을 복호화할 때 적절한 키를 선택할 수 있다.

알려진 키

CDM의 세션 구현이 실제 가 사용 가능하거나 그 값을 알고 있는지와 관계없이, 해당 키에 관한 정보, 특히 키 ID를 포함하는 경우, 키는 세션에 알려진 것으로 간주된다. 알려진 키는 keyStatuses 속성을 통해 노출된다.

키는 만료로 인해 사용할 수 없게 되거나, 제거되었지만 라이선스 폐기 기록을 사용할 수 있는 경우처럼, 사용할 수 없게 된 뒤에도 알려진 것으로 간주된다. 키는 세션에서 명시적으로 제거되고 모든 라이선스 해제 메시지가 확인된 경우에만 알 수 없는 상태가 된다.

예를 들어, update() 호출이 해당 키를 포함하지 않고 이전에 그 키를 포함했던 라이선스를 대체하라는 지시를 포함하는 새 라이선스를 제공하는 경우, 키는 알 수 없는 상태가 될 수 있다.

라이선스

라이선스는 하나 이상의 를 포함하는 키 시스템별 상태 정보이며, 각 키는 키 ID와 연결되고, 키 사용에 관한 다른 정보를 잠재적으로 포함한다.

초기화 데이터
모범 사례 2: 초기화 데이터를 생성할 때는 콘텐츠를 복호화하는 데 필요한 각 를 고유하게 식별한다.

키 시스템은 보통 라이선스 요청 메시지를 구성하기 전에 복호화할 스트림에 관한 정보를 포함하는 초기화 데이터 블록을 필요로 한다. 이 블록은 단순한 키 또는 콘텐츠 ID일 수도 있고, 그러한 정보를 포함하는 더 복잡한 구조일 수도 있다. 애플리케이션은 초기화 데이터를 어떤 애플리케이션별 방식으로 얻거나 미디어 데이터에서 얻는다.

초기화 데이터는 라이선스 요청을 생성하기 위해 CDM이 사용하는 컨테이너별 데이터를 가리키는 일반적인 용어이다.

초기화 데이터의 형식은 컨테이너의 유형에 따라 달라지며, 컨테이너는 둘 이상의 초기화 데이터 형식을 지원할 MAY 있다. 초기화 데이터 유형은 함께 제공되는 초기화 데이터의 형식을 나타내는 문자열이다. 초기화 데이터 유형 문자열은 항상 대소문자를 구분하여 일치된다. 초기화 데이터 유형 문자열은 소문자 ASCII 문자열일 것이 RECOMMENDED 된다.

암호화된 미디어 확장 초기화 데이터 형식 레지스트리초기화 데이터 유형 문자열에서 각 형식의 명세로의 매핑을 제공한다.

사용자 에이전트가 미디어 데이터에서 초기화 데이터를 만나면, 그 초기화 데이터를 initData 속성에 넣어 encrypted 이벤트를 통해 애플리케이션에 제공한다. 사용자 에이전트는 초기화 데이터를 저장하거나 그 시점에 그 내용을 사용해서는 MUST NOT 된다. 애플리케이션은 초기화 데이터CDMgenerateRequest()를 통해 제공한다. 사용자 에이전트는 초기화 데이터를 다른 수단으로 CDM에 제공해서는 MUST NOT 된다.

초기화 데이터는 주어진 스트림 집합 또는 미디어 데이터에 대해 고정된 값이어야 MUST 한다. 이는 주어진 스트림 집합 또는 미디어 데이터를 재생하는 데 필요한 키와 관련된 정보만 포함해야 MUST 한다. 이는 애플리케이션 데이터, 클라이언트별 데이터, 사용자별 데이터 또는 실행 가능한 코드를 포함해서는 MUST NOT 된다.

초기화 데이터는 키 시스템별 데이터 또는 값을 포함하지 않는 것이 SHOULD NOT 된다. 구현은 지원하는 각 초기화 데이터 유형에 대해 [EME-INITDATA-REGISTRY]에 정의된 공통 형식을 지원해야 MUST 한다.

독점 형식/콘텐츠의 사용은 권장되지 않으며, 독점 형식만 지원하거나 사용하는 것은 강하게 권장되지 않는다. 독점 형식은 기존 콘텐츠 또는 공통 형식을 지원하지 않는 기존 클라이언트 장치에서만 사용해야 한다.

연관 가능한 값

둘 이상의 식별자 또는 다른 값이 동일하거나 또는 합리적인 시간과 노력으로 상호 관련시키거나 연관시킬 수 있는 경우, 그 값들은 연관 가능하다고 한다. 그렇지 않으면 그 값들은 연관 불가능하다.

예를 들어, 다음과 같은 방식으로 생성된 값은 연관 가능하다.

  • 쉽게 되돌릴 수 있는 해시 함수를 사용하는 경우.

  • 접두사나 다른 부분집합을 공유하는 경우

  • 무작위 값 N을 N+10으로 바꾸는 경우

  • 출처를 고정 값과 XOR하는 경우(쉽게 되돌릴 수 있기 때문)

반대로, 암호학적으로 강한 비가역 해시 함수 등을 통해 완전히 관련이 없거나 암호학적으로 구별되는 두 값은 연관 불가능하다.

둘 이상의 식별자 또는 다른 값이, 참조되는 엔터티 또는 엔터티 집합이 추가 엔터티의 참여 없이 합리적인 시간과 노력으로 이를 상호 관련시키거나 연관시킬 수 있는 경우 엔터티에 의해 연관 가능하다고 한다. 그렇지 않으면 그 값들은 엔터티에 의해 연관 불가능하다.

둘 이상의 식별자 또는 다른 값이, 해당 엔터티가 애플리케이션, 모든 다른 애플리케이션, 그리고 이들이 사용하거나 통신하는 서버 같은 다른 엔터티를 포함하는 집합인 경우 엔터티에 의해 연관 불가능하다면 애플리케이션에 의해 연관 불가능하다고 한다. 그렇지 않으면 그 값들은 애플리케이션에 의해 연관 가능한 것으로 간주되며, 이는 금지된다.

고유 식별성 값

고유 식별성 값은 값, 데이터 조각, 데이터 조각의 소유에서 비롯되는 함의, 또는 대규모 사용자 또는 클라이언트 장치 집단에 공유되지 않는 관찰 가능한 동작이나 타이밍이다. 고유 식별성 값은 메모리에 있거나 지속될 수 있다.

고유 식별성 값의 예에는 다음이 포함되지만 이에 한정되지 않는다.

고유 식별성 값은 일반적으로 사용자 또는 클라이언트 장치에 대해 고유하지만, 고유 식별성을 갖기 위해 반드시 엄격하게 고유할 필요는 없다. 예를 들어, 소수의 사용자 사이에서 공유되는 값도 여전히 고유 식별성을 가질 수 있다.

영구 식별자

영구 식별자는 어떤 방식으로든 지워지지 않거나, 사용자가 제거, 재설정 또는 변경하기에 사소하지 않은 값, 데이터 조각, 데이터 조각의 소유에서 비롯되는 함의, 또는 관찰 가능한 동작이나 타이밍이다. 여기에는 다음이 포함되지만 이에 한정되지 않는다.

  • 하드웨어 또는 하드웨어 기반 식별자

  • 공장에서 하드웨어 장치에 프로비저닝된 값

  • 운영체제 설치 인스턴스와 연결되었거나 여기서 파생된 값

  • 사용자 에이전트 설치 인스턴스와 연결되었거나 여기서 파생된 값

  • CDM 또는 다른 소프트웨어 구성요소와 연결되었거나 여기서 파생된 값

  • 클라이언트에서 생성되었더라도 구성 파일 또는 이와 유사한 반영구 데이터에 있는 값

  • 클라이언트 또는 기타 사용자 계정 값

고유 영구 식별자영구 식별자이면서 고유 식별성을 갖는 것이다.

클라이언트 외부에 노출될 때, 고유 영구 식별자 및 그로부터 파생되었거나 그와 관련된 값은 암호화되어야 MUST 한다. 고유 영구 식별자는 암호화된 형태로라도 애플리케이션에 노출되어서는 결코 MUST NOT 된다.

고유 영구 식별자는 일반적으로 사용자 또는 클라이언트 장치에 대해 고유하지만, 고유 식별성을 갖기 위해 반드시 엄격하게 고유할 필요는 없다. 예를 들어, 소수의 사용자 사이에서 공유되는 고유 영구 식별자도 여전히 고유 식별성을 가질 수 있다.

고유 영구 식별자는 이 명세의 범위 안에서 파생되거나 생성되지 않았기 때문에 아니다 고유 식별자가 아니다.

distinctiveIdentifier는 고유 영구 식별자를 사용할 수 있는지 제어한다. 구체적으로, 고유 영구 식별자는 distinctiveIdentifier 멤버의 값이, MediaKeySystemAccess를 사용해 생성한 MediaKeys 객체에서 "required"일 때만 사용할 수 있다.

고유 식별자

고유 식별자는 불투명하거나 암호화된 형태를 포함하는 값으로, 클라이언트 외부의 어떤 엔터티가 웹 플랫폼에서 사용자가 예상할 수 있는 범위(예: 쿠키 및 기타 사이트 데이터)를 넘어 값을 상호 관련시키거나 연관시킬 수 있는 값이다. 예를 들어, 사용자가 브라우징 데이터를 지운 뒤에도, 또는 사용자가 그러한 연관을 끊기 쉽지 않은 값에 대해 자신의 개인정보를 보호하려고 시도한 뒤에도, a) 출처, b) 브라우징 프로필, 또는 c) 브라우징 세션 전반에서 애플리케이션이 아닌 엔터티에 의해 연관 가능한 값이 이에 해당한다. 특히, 개별화 요청에 공통 값이 포함되어 있었거나, 개별화 요청에서 제공된 값이 브라우징 데이터 삭제 시도 이후에도 개별화 서버 같은 중앙 서버가 연관시킬 수 있기 때문에, 출처 전반에서 값을 연관시킬 수 있는 경우 그 값은 고유 식별자이다. 이러한 원인에는 개별화 과정에서 고유 영구 식별자를 사용하는 것이 포함될 수 있다.

암호화된 형태로라도 애플리케이션에 노출되는 고유 식별자는 식별자 요구사항의 적용을 받으며, 여기에는 암호화, 출처 및 프로필별 고유성, 그리고 삭제 가능성이 포함된다.

고유 식별자의 인스턴스화 또는 사용은 이 명세에 정의된 API를 애플리케이션이 사용하는 것에 의해 트리거되지만, 고유 식별자와 관련된 조건을 트리거하기 위해 그 식별자가 애플리케이션에 제공될 필요는 없다. (고유 영구 식별자는 불투명하거나 암호화된 형태로도 애플리케이션에 제공되지 않는다.)

distinctiveIdentifier는 고유 식별자를 사용할 수 있는지 제어한다. 구체적으로, 고유 식별자는 distinctiveIdentifier 멤버의 값이, MediaKeySystemAccess를 사용해 생성한 MediaKeys 객체에서 "required"일 때만 사용할 수 있다.

고유 식별자는 다음 기준을 모두 충족하는 값, 데이터 조각, 데이터 조각의 소유에서 비롯되는 함의, 또는 관찰 가능한 동작이나 타이밍이다.

  • 이는 고유 식별성을 가진다.

    고유 식별자는 일반적으로 사용자 또는 클라이언트 장치에 대해 고유하지만, 식별자가 고유 식별성을 갖기 위해 반드시 엄격하게 고유할 필요는 없다. 예를 들어, 소수의 사용자 사이에서 공유되는 식별자도 여전히 고유 식별성을 가질 수 있다.

  • 그것, 그것에 관한 정보, 또는 그것에서 파생되었거나 그와 관련된 값이 암호화된 형태로라도 클라이언트 외부에 노출된다. 여기에는 애플리케이션 및/또는 라이선스, 개별화, 또는 다른 서버에 이를 제공하는 것이 포함되지만 이에 한정되지 않는다.

  • 이는 다음 속성 중 하나 이상을 가진다.

    • 하나 이상의 고유 영구 식별자에서 파생된다.

    • 그 값을 생성한 생성, 개별화, 프로비저닝 또는 다른 과정이 하나 이상의 고유 영구 식별자 또는 다른 고유 식별자를 관련시키거나, 사용하거나, 제공하거나, 그로부터 파생되었거나, 유사하게 관련시켰다.

    • 이는 삭제 가능하지만 쿠키 및 기타 사이트 데이터와 함께 삭제 가능하지는 않다.

      예를 들어, 운영체제 수준 메커니즘처럼 사용자 에이전트 외부의 어떤 메커니즘을 통하는 경우이다.

    애플리케이션에 노출되는 값에 대해 규범적으로 금지되는 기타 우려 속성에는 다음이 포함된다.

    그러한 규범적으로 금지되는 값의 예에는 다음이 포함되지만 이에 한정되지 않는다.

    • 모든 출처에 사용되는 단일 하드웨어 기반 값.

    • 모든 출처에 사용되는 단일 무작위 기반 값.

    • 모든 출처에 사용되는 개별화 과정에서 얻은 단일 값.

    • 위 값 중 어느 하나의 전부 또는 일부를 포함하는 값.

    • 여러 출처에 사용되지만 모든 출처에는 사용되지 않는 단일 값.

    • 한 도메인의 모든 출처에 사용되는 단일 값. (식별자는 출처별이어야 한다.)

    • 미리 프로비저닝된 출처별 값.

    • 쉽게 되돌릴 수 있는 수단으로 생성되어, 클라이언트에서 생성되었는지 또는 개별화 과정이 관련되었는지와 관계없이 애플리케이션에 의해 연관 가능한 값. 예를 들어, 출처의 일부 또는 전부를 고정 값과 XOR하거나 다른 방식으로 통합하는 경우이다.

고유 식별자는 보통 이를 생성한 엔터티에 의해 연관 가능하지만, 이는 애플리케이션에 의해 연관 불가능해야 MUST 한다. 다시 말해, 그러한 상호 관련 또는 연관은 원래 고유 식별자 값을 생성한 개별화 서버 같은 엔터티에 의해서만 가능하다. 고유 영구 식별자에 접근할 수 있는 엔터티는 이 능력을 애플리케이션에 노출해서는 MUST NOT 된다. 그렇게 하면 결과적인 고유 식별자가 애플리케이션에 의해 연관 가능해지기 때문이다. 또한 그러한 상관관계가 다른 엔터티나 제3자에게 노출되지 않도록 주의해야 SHOULD 한다.

고유 식별자의 예에는 다음이 포함되지만 이에 한정되지 않는다.

  • 키 요청에 포함되고, 다른 클라이언트 장치가 포함하는 바이트열과 다르며, 고유 영구 식별자를 사용해 직접 또는 간접적으로 기반하거나 취득된 바이트열.

  • 키 요청에 포함되고, 다른 클라이언트 장치의 요청에 포함되는 공개 키와 다르며, 고유 영구 식별자를 사용해 직접 또는 간접적으로 기반하거나 취득된 공개 키.

  • 다른 클라이언트 장치가 갖고 있지 않고, 고유 영구 식별자를 사용해 직접 또는 간접적으로 기반하거나 취득된 개인 키의 소유 증명(예: 어떤 데이터에 서명함으로써).

  • 그러한 키에 대한 식별자.

  • 첫 번째 값이 직접 노출되지 않더라도, 노출되는 다른 값을 파생하는 데 사용되는 그러한 값.

  • 다른 고유 식별자에서 파생된 값.

  • 고유 영구 식별자와 함께 (예: 개별화) 서버에 보고되었거나, 고유 영구 식별자를 제공한 후 그러한 서버가 제공한 무작위 값.

  • 공장에서 하드웨어 장치에 프로비저닝된 고유 값에서 파생된 값.

  • 공장에서 하드웨어 장치에 있는 고유 하드웨어 값(예: MAC 주소 또는 일련번호) 또는 소프트웨어 값(예: 운영체제 설치 인스턴스 또는 운영체제 사용자 계정 이름)에서 파생된 값.

  • CDM 바이너리 또는 CDM이 사용하는 다른 파일에 포함된 고유 값에서 파생된 값.

고유 식별자가 아닌 것의 예:

  • 설치 기반이 큰 경우, 주어진 CDM 버전의 모든 사본 사이에서 공유되는 공개 키.

  • 고유하지만 하나의 세션에서만 사용되는 nonce 또는 임시 키.

  • 개별화 또는 이와 유사한 것을 통해서도, 파생되거나 유사한 방식으로도 클라이언트 외부에 노출되지 않는 값.

  • 예를 들어 비디오 파이프라인과 CDM 사이의 증명에 사용되는 장치 고유 키로서, CDM이 이러한 증명이 애플리케이션으로 더 흘러가도록 허용하지 않고, 대신 고유 식별자를 구성하지 않는 키를 사용해 자체적으로 새 증명을 만드는 경우.

  • 쿠키 같은 브라우징 데이터와 함께 완전히 삭제/삭제 가능하며, 이후에는 연관 불가능한 값으로 대체되는 값] (단지 애플리케이션에 의해 연관 불가능한 것이 아니라), 개별화 서버 같은 중앙 서버에 의해서도 연관 불가능하며, 다음 중 하나 이상에 해당하는 경우:

    • 값의 생성에 고유 영구 식별자 또는 고유 식별자가 관여하지 않았다.

    • 시스템의 입력 없이 생성된 무작위 값이다.

    • 다른 고유 식별자의 사용이나 지식 없이 서버가 제공한 값이다.

고유 식별자 및 고유 영구 식별자의 사용

구현, 구성, 인스턴스 또는 객체가 그 수명 동안 또는 관련된 그러한 엔터티의 수명 동안 어느 시점에든, 하나 이상의 고유 식별자, 그에 관한 정보, 또는 그로부터 파생되었거나 그와 관련된 값을 암호화된 형태로라도 클라이언트 외부에 노출하는 경우, 그 구현, 구성, 인스턴스 또는 객체는 고유 식별자를 사용한다고 한다. 여기에는 그러한 값을 애플리케이션 및/또는 라이선스, 개별화, 또는 다른 서버에 제공하는 것이 포함되지만 이에 한정되지 않는다.

구현, 구성, 인스턴스 또는 객체가 그 수명 동안 또는 관련된 그러한 엔터티의 수명 동안 어느 시점에든, 하나 이상의 고유 영구 식별자, 그에 관한 정보, 또는 그로부터 파생되었거나 그와 관련된 값을 암호화된 형태로라도 클라이언트 외부에 노출하는 경우, 그 구현, 구성, 인스턴스 또는 객체는 고유 영구 식별자를 사용한다고 한다. 여기에는 그러한 값을 개별화 서버에 제공하는 것이 포함되지만 이에 한정되지 않는다. 그러한 값은 애플리케이션에 제공되어서는 MUST NOT 된다.

구현, 구성, 인스턴스 또는 객체가 고유 식별자를 사용하거나 및/또는 고유 영구 식별자를 사용하는 경우, 그 구현, 구성, 인스턴스 또는 객체는 고유 식별자 또는 고유 영구 식별자를 사용한다고 한다.

distinctiveIdentifier고유 식별자고유 영구 식별자를 사용할 수 있는지 제어한다. 구체적으로, 그러한 식별자는 distinctiveIdentifier 멤버의 값이, MediaKeySystemAccess를 사용해 생성한 MediaKeys 객체에서 "required"일 때만 사용할 수 있다.

교차 출처 제한

재생 중에, 임베드된 미디어 데이터는 임베딩하는 출처의 스크립트에 노출된다. API가 초기화 데이터encrypted 이벤트에서 제공하려면, 미디어 데이터가 임베딩 페이지와 CORS-same-origin이어야 MUST 한다. 미디어 데이터가 임베딩 문서와 교차 출처인 경우, 작성자는 HTMLMediaElementcrossOrigin 속성과 미디어 데이터 응답의 CORS 헤더를 사용하여 이를 CORS-same-origin으로 만들어야 SHOULD 한다.

혼합 콘텐츠 제한

재생 중에, 임베드된 미디어 데이터는 임베딩하는 출처의 스크립트에 노출된다. API가 초기화 데이터encrypted 이벤트에서 제공하려면, 미디어 데이터혼합 콘텐츠 [MIXED-CONTENT]여서는 MUST NOT 된다.

시간

시간은 ECMAScript 언어 명세에 표현된 것과 동등해야 MUST 한다.

그러한 시간이 존재하지 않거나 시간이 불확정인 경우, 시간은 NaN과 같다. 시간은 결코 Infinity 값을 가져서는 안 된다.

시간은 일반적으로 밀리초 정확도의 한 시점을 나타내지만, 그것만으로는 충분한 정의가 아니다. 정의된 시간 값과 시간 범위 참조는 다른 중요한 요구사항을 추가한다.

만료 시간

그 이후에는 키가 더 이상 복호화에 사용 가능하지 않게 되는 시간.

브라우징 프로필

주어진 머신의 사용자 에이전트는 애플리케이션에 보이는 상태와 데이터와 관련하여 독립적으로 동작할 것으로 기대되는 다양한 서로 다른 컨텍스트나 모드 또는 임시 상태에서의 실행을 지원할 수 있다. 특히, 저장된 모든 데이터는 독립적일 것으로 기대된다. 이 명세에서는 그러한 독립적인 컨텍스트나 모드를 "브라우징 프로필"이라고 한다.

그러한 독립적인 컨텍스트의 예에는, 사용자 에이전트가 서로 다른 운영체제 사용자 계정에서 실행되는 경우 또는 사용자 에이전트가 단일 계정에 대해 여러 독립 프로필을 정의하는 기능을 제공하는 경우가 포함된다.

3. 키 시스템에 대한 접근 얻기

이 절은 키 시스템에 대한 접근을 얻기 위한 메커니즘을 정의한다. 요청에 기능을 포함하는 것은 기능 감지도 가능하게 한다.

알고리즘의 단계는 프로미스를 거부할 때 항상 중단된다.

3.1 Permissions Policy 통합

requestMediaKeySystemAccess()는 문자열 encrypted-media로 식별되는 정책 제어 기능이다. 그 기본 허용 목록'self'이다 [PERMISSIONS-POLICY].

3.3 MediaKeySystemConfiguration 딕셔너리

WebIDLenum MediaKeysRequirement {
  "required",
  "optional",
  "not-allowed"
};

MediaKeysRequirement 열거형은 다음과 같이 정의된다:

열거형 설명
required
requestMediaKeySystemAccess() 호출에서 사용되는 경우
반환된 객체는 이 기능을 지원해야 MUST 한다.
MediaKeySystemAccess 객체가 반환하는 경우
그 객체가 생성한 CDM 인스턴스는 이 기능을 사용할 수 MAY 있다.
optional
requestMediaKeySystemAccess() 호출에서 사용되는 경우
반환된 객체는 이 기능을 지원하고 사용할 수 MAY 있다.
MediaKeySystemAccess 객체가 반환하는 경우
이 값은 그러한 객체 안에 존재할 수 없으며 존재해서는 안 된다 MUST NOT.
not-allowed
requestMediaKeySystemAccess() 호출에서 사용되는 경우
반환된 객체는 이 기능을 사용하지 않고 동작해야 MUST 하며, 언제든 이를 사용해서는 안 된다 MUST NOT.
MediaKeySystemAccess 객체가 반환하는 경우
그 객체가 생성한 CDM 인스턴스는 이 기능을 사용해서는 안 된다 MUST NOT.
WebIDLdictionary MediaKeySystemConfiguration {
  DOMString                               label = "";
  sequence<DOMString>                     initDataTypes = [];
  sequence<MediaKeySystemMediaCapability> audioCapabilities = [];
  sequence<MediaKeySystemMediaCapability> videoCapabilities = [];
  MediaKeysRequirement                    distinctiveIdentifier = "optional";
  MediaKeysRequirement                    persistentState = "optional";
  sequence<DOMString>                     sessionTypes;
};

MediaKeySystemConfiguration 딕셔너리는 다음 멤버를 포함한다:

label 타입은 DOMString이며, 기본값은 ""
MediaKeySystemConfiguration에 보존될 선택적 레이블이며, getConfiguration() 메서드가 MediaKeySystemAccess에서 반환한다.
initDataTypes 타입은 sequence<DOMString>이며, 기본값은 []
지원되는 초기화 데이터 타입 이름의 목록. 이 객체의 초기화 데이터 타입 기능은 목록이 비어 있거나 다른 모든 멤버와 함께 지원되는 값을 하나 이상 포함하는 경우(알고리즘에 의해 결정된 대로) 지원되는 것으로 간주된다. 시퀀스의 값은 빈 문자열이어서는 안 된다 MUST.
audioCapabilities 타입은 sequence<MediaKeySystemMediaCapability>이며, 기본값은 []
지원되는 오디오 타입 및 기능 쌍의 목록. 이 객체의 오디오 기능은 목록이 비어 있거나, 다른 모든 멤버와 함께 지원되는 값을 하나 이상 포함하는 경우(알고리즘에 의해 결정된 대로) 지원되는 것으로 간주된다. 값 사이에 충돌이 있으면, 앞의 값이 선택된다. 빈 목록은 지원되는 오디오 기능이 없음을 나타낸다. 이 경우, videoCapabilities 요소는 비어 있어서는 안 된다.
videoCapabilities 타입은 sequence<MediaKeySystemMediaCapability>이며, 기본값은 []
지원되는 비디오 타입 및 기능 쌍의 목록. 이 객체의 비디오 기능은 목록이 비어 있거나, 다른 모든 멤버와 함께 지원되는 값을 하나 이상 포함하는 경우(알고리즘에 의해 결정된 대로) 지원되는 것으로 간주된다. 값 사이에 충돌이 있으면, 앞의 값이 선택된다. 빈 목록은 지원되는 비디오 기능이 없음을 나타낸다. 이 경우, audioCapabilities 요소는 비어 있어서는 안 된다.
distinctiveIdentifier 타입은 MediaKeysRequirement이며, 기본값은 "optional"
구별 식별자의 사용이 요구되는지 여부.

이 멤버가 "not-allowed"이면, 구현은 이 구성에서 생성된 어떤 객체와 연결된 어떤 작업에 대해서도 구별 식별자 또는 구별 영구 식별자를 사용해서는 안 된다 MUST NOT.

persistentState 타입은 MediaKeysRequirement이며, 기본값은 "optional"
상태를 영속화하는 능력이 요구되는지 여부. 여기에는 세션 데이터 및 기타 모든 유형의 상태가 포함된다.

이 멤버가 "not-allowed"이면, CDM은 이 객체의 Document의 애플리케이션 또는 출처와 관련된 어떤 상태도 영속화해서는 안 된다 MUST NOT.

참고

이 멤버의 목적상, 영속 상태에는 키 시스템 구현이 제어하는 영속 고유 식별자(구별 식별자)가 포함되지 않는다. distinctiveIdentifier는 이 요구사항을 독립적으로 반영한다.

영속 상태가 지원되지 않는 경우에는 "temporary" 세션만 생성할 수 있다.

참고

"temporary" 세션의 경우, 상태를 저장할 필요와 능력은 키 시스템 구현별이며 사용되는 기능에 따라 달라질 수 있다.

참고

"temporary"가 아닌 세션을 생성하려는 애플리케이션은 requestMediaKeySystemAccess()를 호출할 때 이 멤버를 "required"로 설정해야 한다.

sessionTypes 타입은 sequence<DOMString>
지원되어야 하는 MediaKeySessionType의 목록. 모든 값은 지원되어야 한다.

딕셔너리가 requestMediaKeySystemAccess()에 전달될 때 이 멤버가 존재하지 않으면 [Infra], 딕셔너리는 이 멤버가 [ "temporary" ]로 설정된 것처럼 취급된다.

구현은 이 딕셔너리에 멤버를 추가해서는 안 된다 SHOULD NOT. 멤버가 추가되는 경우, 그것들은 MediaKeysRequirement 타입이어야 MUST 하며, 가장 넓은 범위의 애플리케이션 및 클라이언트 조합을 지원하기 위해 기본값을 "optional"로 가지는 것이 권장된다 RECOMMENDED.

참고

사용자 에이전트 구현이 인식하지 않는 딕셔너리 멤버는 [WEBIDL]에 따라 무시되며, requestMediaKeySystemAccess() 알고리즘에서 고려되지 않는다. 애플리케이션이 비표준 딕셔너리 멤버를 사용하는 경우, 그러한 딕셔너리 멤버가 포함된 구성을 사용자 에이전트 구현이 거부할 것이라고 의존해서는 안 된다 MUST NOT.

이 딕셔너리는 상태 또는 데이터를 CDM에 전달하는 데 사용되어서는 안 된다 MUST NOT.

3.4 MediaKeySystemMediaCapability 딕셔너리

WebIDLdictionary MediaKeySystemMediaCapability {
  DOMString contentType = "";
  DOMString? encryptionScheme = null;
  DOMString robustness = "";
};

3.4.1 딕셔너리 MediaKeySystemMediaCapability 멤버

contentType 타입은 DOMString이며, 기본값은 ""

미디어 리소스MIME 타입.

encryptionScheme 타입은 DOMString이며, 기본값은 null

콘텐츠 타입과 연결된 암호화 스킴. null이거나 존재하지 않는 값은 애플리케이션이 특정 암호화 스킴을 요구하지 않으므로 어떤 암호화 스킴도 허용 가능하다는 것을 사용자 에이전트에 나타낸다.

빈 문자열은 null 또는 존재하지 않는 것과 구별되므로, 인식되지 않는 암호화 스킴으로 처리된다.

encryptionScheme의 잘 알려진 값은 다음과 같다.

  • cenc: [CENC] 4.2a절에 정의된 "cenc" 모드. AES-CTR 모드 전체 샘플 및 비디오 NAL 서브샘플 암호화.
  • cbcs: [CENC] 4.2d절에 정의된 "cbcs" 모드. AES-CBC 모드 부분 비디오 NAL 패턴 암호화. 비디오의 경우, 명세는 다양한 암호화 패턴을 허용한다.
  • cbcs-1-9: "cbcs" 모드와 같지만, [CENC] 10.4.2절에서 권장하는 것처럼 비디오에 대해 1:9의 특정 encrypt:skip 패턴을 사용한다.
robustness 타입은 DOMString이며, 기본값은 ""

콘텐츠 타입과 연결된 견고성 수준. 빈 문자열은 콘텐츠 타입을 복호화하고 디코딩할 수 있는 어떤 능력도 허용 가능함을 나타낸다. 구현은 CDM을, MediaKeySystemAccess 객체의 구성에 지정된 견고성 수준을 적어도 지원하도록 구성해야 MUST 하며, 이 객체는 MediaKeys 객체를 생성하는 데 사용된다.

이 객체가 나타내는 기능이 지원되는 것으로 간주되려면, contentType은 빈 문자열이어서는 안 되며 MUST NOT, 모든 코덱을 포함한 전체 값이 robustness와 함께 지원되어야 MUST 한다.

코덱 집합 중 어느 것이든 허용되는 경우, 각 코덱마다 이 딕셔너리의 별도 인스턴스를 사용한다.

모범 사례 3: MediaKeySystemMediaCapabilityrequestMediaKeySystemAccess()에 전달할 때는, 컨테이너가 이를 규범적으로 함의하지 않는 한 MIME 유형 안에 코덱 및 코덱 제약 조건을 지정하고 (예: [RFC6381]에 따름), encryptionScheme을 null이라는 기본값에 의존하지 말고 특정 값으로 설정한다.

서로 다른 암호화 스킴은 일반적으로 서로 호환되지 않는다. null 기본값과 null을 "any"로 해석하는 것은 이를 알지 못하는 애플리케이션에 대한 하위 호환성과 오래된 사용자 에이전트를 위한 polyfill 경로를 제공한다.

4. MediaKeySystemAccess 인터페이스

MediaKeySystemAccess 객체는 키 시스템에 대한 접근을 제공한다.

WebIDL[Exposed=Window, SecureContext] interface MediaKeySystemAccess {
  readonly attribute DOMString keySystem;
  MediaKeySystemConfiguration  getConfiguration ();
  Promise<MediaKeys>           createMediaKeys ();
};

4.1 속성

keySystem 타입은 DOMString이며, 읽기 전용
사용 중인 키 시스템을 식별한다.

4.2 메서드

getConfiguration()

requestMediaKeySystemAccess() 알고리즘이 선택한 지원되는 구성 옵션 조합을 반환한다.

반환되는 객체는 이 객체로 이행된 프로미스를 반환한 requestMediaKeySystemAccess() 호출에 전달된 첫 번째 충족 가능한 MediaKeySystemConfiguration 구성의 비엄격 부분집합(그리고 암시된 기본값)이다. 그 단일 구성에 지정되지 않은 기능에 대한 값은 포함하지 않으므로(암시된 기본값 제외), 키 시스템 구현의 모든 기능을 반영하지 않을 수 있다. 구성 안의 모든 값은 어떤 조합으로도 사용할 수 있다. MediaKeysRequirement 타입의 멤버는 어떤 조합에 대해 기능이 요구되는지를 반영한다. 그 값은 "optional"이 되지 않는다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 configuration 값을 반환한다.

    이로 인해 이 메서드가 호출될 때마다 configuration에서 새 객체가 생성되고 초기화된다.

    encryptionScheme이 애플리케이션에 의해 제공되지 않았더라도, 누적된 configuration은 여전히 값이 nullencryptionScheme 필드를 포함해야 MUST 하므로, polyfill은 특정 값을 지정하지 않고도 해당 필드에 대한 사용자 에이전트의 지원 여부를 감지할 수 있다.

createMediaKeys()

keySystem을 위한 새 MediaKeys 객체를 생성한다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. promise를 새 프로미스로 둔다.

  2. 다음 단계를 병렬로 실행한다:

    1. configuration을 이 객체의 configuration 값의 값으로 둔다.

    2. configurationdistinctiveIdentifier 멤버의 값이 "required"이면 use distinctive identifiertrue로 두고, 그렇지 않으면 false로 둔다.

    3. configurationpersistentState 멤버 값이 "required"이면 persistent state allowedtrue로 두고, 그렇지 않으면 false로 둔다.

    4. 필요한 경우 이 객체의 cdm implementation 값이 나타내는 키 시스템 구현을 로드하고 초기화한다.

    5. instance를 이 객체의 cdm implementation 값이 나타내는 키 시스템 구현의 새 인스턴스로 둔다.

    6. configuration을 사용하여 키 시스템 기능을 활성화, 비활성화 및/또는 선택하도록 instance를 초기화한다.

    7. use distinctive identifierfalse이면, instance구별 식별자 및 구별 영구 식별자를 사용하지 못하게 한다.

    8. persistent state allowedfalse이면, instance가 이 객체의 Document의 애플리케이션 또는 출처와 관련된 어떤 상태도 영속화하지 못하게 한다.

    9. 앞의 단계 중 하나라도 실패하면, 적절한 오류 이름을 이름으로 가지는 새 DOMException으로 promise를 거부한다.

    10. media keys를 새 MediaKeys 객체로 두고, 다음과 같이 초기화한다:

      1. use distinctive identifier 값을 use distinctive identifier로 둔다.

      2. persistent state allowed 값을 persistent state allowed로 둔다.

      3. supported session types 값을 configurationsessionTypes 멤버 값으로 둔다.

      4. cdm implementation 값을 이 객체의 cdm implementation 값으로 둔다.

      5. cdm instance 값을 instance로 둔다.

    11. promisemedia keys로 이행한다.

  3. promise를 반환한다.

5. MediaKeys 인터페이스

MediaKeys 객체는 연결된 HTMLMediaElement가 재생 중 미디어 데이터의 복호화에 사용할 수 있는 키 집합을 나타낸다. 또한 CDM 인스턴스를 나타낸다.

MediaKeys 객체는 더 이상 접근할 수 없을 때 사용자 에이전트에 의해 파괴될 수 있다.

참고

예를 들어, 스크립트 참조가 없고 연결된 미디어 요소도 없는 경우.

프로미스를 반환하는 메서드의 경우, 모든 오류는 반환된 Promise를 거부하여 비동기적으로 보고된다. 여기에는 [WEBIDL] 타입 매핑 오류도 포함된다.

알고리즘의 단계는 프로미스를 거부할 때 항상 중단된다.

WebIDLenum MediaKeySessionType {
  "temporary",
  "persistent-license"
};

MediaKeySessionType 열거형은 다음과 같이 정의된다:

열거형 설명
temporary

라이선스, 키 및 세션의 기록 또는 세션과 관련된 데이터가 영속화되지 않는 세션.

애플리케이션은 그러한 저장소를 관리하는 것을 걱정할 필요가 없다. 이 세션 타입의 지원은 REQUIRED이다.

persistent-license

라이선스(그리고 잠재적으로 세션과 관련된 다른 데이터)가 영속화되는 세션. 라이선스와 그 안에 포함된 키가 파괴될 때 라이선스 파기 기록은 영속화되어야 SHALL 한다. 라이선스 파기 기록은 라이선스와 그 안에 포함된 키가 더 이상 클라이언트에서 사용할 수 없다는 키 시스템별 증명이다. 이 세션 타입의 지원은 OPTIONAL이다.

이 타입의 세션은 이 객체를 생성한 MediaKeySystemAccess 객체와 연결된 구성이 persistentState 값을 "required"로 가질 때만 생성할 수 있다. update()가 성공적으로 호출되면, 세션은 그 세션 ID를 통해 로드 가능해야 MUST 한다. message가 "license-release" 타입으로, 라이선스 파기 기록을 포함하여 생성되며, 이는 remove()가 호출된 때부터 update()에 전달된 응답으로 그 기록이 확인될 때까지 생성된다.

애플리케이션은 그러한 세션에 대해 영속화된 데이터가 더 이상 필요하지 않을 때 제거되도록 보장할 책임이 있다. 세션 저장소 및 영속성을 참고한다.

WebIDL[Exposed=Window, SecureContext] interface MediaKeys {
    MediaKeySession createSession (optional MediaKeySessionType sessionType = "temporary");
    Promise<MediaKeyStatus> getStatusForPolicy (optional MediaKeysPolicy policy = {});
    Promise<boolean> setServerCertificate (BufferSource serverCertificate);
};

5.1 메서드

createSession()

MediaKeySession 객체를 반환한다.

참고

sessionType 매개변수는 반환된 객체의 동작에 영향을 준다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 supported session types 값이 sessionType을 포함하지 않으면, 던진다 [WEBIDL] NotSupportedError.

    참고

    영속 세션 타입인가? 알고리즘이 true를 반환하는 sessionType 값은 이 객체의 persistent state allowed 값이 false이면 실패한다.

  2. 구현이 현재 상태에서 MediaKeySession 작업을 지원하지 않으면, 던진다 [WEBIDL] InvalidStateError.

    참고

    일부 구현은 이 MediaKeys 객체가 setMediaKeys()를 사용하여 미디어 요소와 연결될 때까지 MediaKeySession 알고리즘을 실행할 수 없다. 이 단계는 애플리케이션이 그러한 작업을 수행하려고 시도하기 전에 이 드문 동작을 감지할 수 있게 한다.

  3. session을 새 MediaKeySession 객체로 두고, 다음과 같이 초기화한다:

    1. sessionId 속성을 빈 문자열로 둔다.

    2. expiration 속성을 NaN으로 둔다.

    3. closed 속성을 새 프로미스로 둔다.

    4. key status를 새 빈 MediaKeyStatusMap 객체로 두고, 다음과 같이 초기화한다:

      1. size 속성을 0으로 둔다.

    5. session type 값을 sessionType으로 둔다.

    6. uninitialized 값을 true로 둔다.

    7. callable 값을 false로 둔다.

    8. closing or closed 값을 false로 둔다.

    9. use distinctive identifier 값을 이 객체의 use distinctive identifier 값으로 둔다.

    10. cdm implementation 값을 이 객체의 cdm implementation으로 둔다.

    11. cdm instance 값을 이 객체의 cdm instance로 둔다.

  4. session을 반환한다.

getStatusForPolicy()

주어진 MediaKeysPolicy에 대한 MediaKeyStatus를 반환한다.

WebIDLdictionary MediaKeysPolicy {
    DOMString minHdcpVersion;
};

MediaKeysPolicy 딕셔너리는 선택적 속성만으로 구성된 객체이다. 각 속성은 정책 요구사항을 나타낸다. CDM이 모든 요구사항에 기반하여 복호화된 미디어 데이터의 제시를 허용할 경우, 정책이 충족되었다고 한다.

HDCP 정책은 minHdcpVersion으로 나타낸다. 시스템이 지정된 HDCP 버전 이상을 활성화할 수 있으면, 그 정책은 "usable"의 MediaKeyStatus를 결과로 낳는다. [EME-HDCP-VERSION-REGISTRY]는 minHdcpVersion 값에서 HDCP 명세로의 매핑을 제공한다.

참고

HDCP 상태의 결정은 CDM이 재생 중 그러한 제한을 강제하는 방식과 같은 방식으로 수행되어야 한다. 이렇게 하면 애플리케이션 개발자가 재생을 시작하기 위해 어떤 콘텐츠를 가져올지 최적화할 수 있도록 합리적인 힌트를 얻을 수 있다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. policy존재하는 딕셔너리 멤버가 없으면, 새로 생성된 TypeError로 거부된 프로미스를 반환한다.
  2. promise를 새 프로미스로 둔다.

  3. 다음 단계를 실행하도록 태스크를 큐에 넣는다:

    1. policy의 각 딕셔너리 멤버에 대해, 다음 단계를 실행한다:

      1. 키가 유효한 MediaKeysPolicy 멤버가 아니거나 값의 타입이 올바르지 않으면, TypeErrorpromise를 거부하고 이 단계를 중단한다.

    2. policy의 각 딕셔너리 멤버에 대해, 다음 단계를 실행한다:

      1. CDM딕셔너리 멤버에 대한 MediaKeyStatus를 결정할 수 없으면, NotSupportedErrorpromise를 거부하고 이 단계를 중단한다.

    3. policy의 각 딕셔너리 멤버에 대해, 다음 단계를 실행한다:

      1. CDM딕셔너리 멤버에 대해 복호화된 미디어 데이터의 제시를 차단할 것이라면, promise를 "output-restricted"로 이행하고 이 단계를 중단한다.

    4. promise를 "usable"로 이행한다.

  4. promise를 반환한다.

setServerCertificate()

라이선스 서버로 보내는 메시지를 암호화하는 데 사용할 서버 인증서를 제공한다.

그러한 인증서를 사용하는 키 시스템의 경우, 애플리케이션은 서버 인증서를 명시적으로 설정하기 위해 SHOULD setServerCertificate()를 호출해야 한다. 그렇지 않으면 라이선스 교환이 실패할 수 있다.

참고

일부 키 시스템은 "message" 이벤트 큐에 넣기 알고리즘을 통해 서버에서 인증서를 요청하는 것도 지원한다. 하지만 그러한 인증서를 사용하는 모든 키 시스템이 이를 지원하는 것은 아니다.

서버 인증서 내용은 키 시스템별이다. 이는 실행 가능한 코드를 포함해서는 안 된다 MUST NOT.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 cdm implementation 값이 나타내는 키 시스템 구현이 서버 인증서를 지원하지 않으면, false로 이행된 프로미스를 반환한다.

  2. serverCertificate가 빈 배열이면, 새로 생성된 TypeError로 거부된 프로미스를 반환한다.

  3. certificateserverCertificate 매개변수 내용의 사본으로 둔다.

  4. promise를 새 프로미스로 둔다.

  5. 다음 단계를 병렬로 실행한다:

    1. sanitized certificatecertificate의 검증 및/또는 정제된 버전으로 둔다.

      참고

      사용자 에이전트는 인증서를 CDM에 전달하기 전에 철저히 검증해야 한다. 여기에는 값이 합리적인 한계 안에 있는지 확인하고, 관련 없는 데이터나 필드를 제거하고, 미리 파싱하고, 정제하고, 및/또는 완전히 정제된 버전을 생성하는 것이 포함될 수 있다. 사용자 에이전트는 필드의 길이와 값이 합리적인지 확인해야 한다. 알 수 없는 필드는 거부하거나 제거해야 한다.

    2. 이 객체의 cdm instance를 사용하여 sanitized certificate를 처리한다.

    3. 앞의 단계가 실패하면, 적절한 오류 이름을 이름으로 가지는 새 DOMException으로 promise를 거부한다.

    4. promisetrue로 이행한다.

  6. promise를 반환한다.

5.2 알고리즘

5.2.1 영속 세션 타입인가?

영속 세션 타입인가? 알고리즘은 지정된 세션 타입이 어떤 종류의 영속성을 지원하는지 결정하기 위해 실행된다. 이 알고리즘을 실행하라는 요청에는 MediaKeySessionType 값이 포함된다.

다음 단계가 실행된다:

  1. session type을 지정된 MediaKeySessionType 값으로 둔다.

  2. 다음 목록에서 session type의 값에 해당하는 단계를 따른다:

    "temporary"
    false를 반환한다.
    "persistent-license"
    true를 반환한다.

5.2.2 CDM 사용 불가

CDM 사용 불가 알고리즘은 CDM 인스턴스가 사용할 수 없게 될 때 MediaKeys 객체, media keys와 연결된 모든 MediaKeySession 객체를 닫기 위해 실행된다. 이 알고리즘을 실행하라는 요청에는 MediaKeySessionClosedReason 값이 포함된다.

다음 단계가 실행된다:

  1. reason을 지정된 MediaKeySessionClosedReason 값으로 둔다.

  2. media keys가 생성했으며 닫힌 상태가 아닌 각 MediaKeySession에 대해, 이유 reason과 함께 그 세션에 대해 세션 닫힘 알고리즘을 실행하도록 태스크를 큐에 넣는다.

5.3 저장소 및 영속성

이 절은 저장소 및 영속성과 관련된 일반 요구사항을 설명한다.

MediaKeys 객체의 persistent state allowed 값이 false이면, 그 객체의 cdm instance는 이 객체 또는 이 객체가 생성한 어떤 세션에 대한 작업의 결과로 상태를 영속화하거나 이전에 영속화된 상태에 접근해서는 안 된다 SHALL NOT.

MediaKeys 객체의 persistent state allowed 값이 true이면, 그 객체의 cdm instance는 이 객체 또는 이 객체가 생성한 어떤 세션에 대한 작업의 결과로 상태를 영속화하거나 이전에 영속화된 상태에 접근할 수 있다 MAY.

영속화된 데이터는 항상 이 객체의 Document출처만 접근할 수 있도록 저장되어야 MUST 한다. 또한 데이터는 현재 브라우징 프로필에서만 접근 가능해야 MUST 한다. 다른 브라우징 프로필, 사용자 에이전트 및 애플리케이션은 저장된 데이터에 접근할 수 있어서는 안 된다 MUST NOT. 사용자 기기에 저장되는 정보를 참고한다.

영속 저장소를 지원할 때의 추가 고려사항은 10. 보안11. 개인정보 보호를 참고한다.

6. MediaKeySession 인터페이스

MediaKeySession 객체는 키 세션을 나타낸다.

MediaKeySession 객체는 객체의 closed 속성이 이행된 경우 그리고 오직 그 경우에만 닫힘 상태이다.

사용자 에이전트는 CDM 상태 변경 감시 알고리즘을, 닫힘 상태가 아닌 각 MediaKeySession 객체에 대해 지속적으로 실행해야 SHALL 한다. CDM 상태 변경 감시 알고리즘은 주 이벤트 루프와 병렬로 실행되어야 MUST 하지만, 이 명세에서 병렬로 실행되도록 정의된 다른 절차와는 병렬로 실행되어서는 안 된다.

MediaKeySession 객체는 닫힘 상태가 아니고 이를 생성한 MediaKeys 객체가 계속 접근 가능한 경우, 파괴되어서는 안 되며 SHALL NOT 이벤트를 계속 수신해야 SHALL 한다. 그렇지 않으면, 더 이상 접근할 수 없는 MediaKeySession 객체는 더 이상 이벤트를 수신해서는 안 되며 SHALL NOT 파괴될 수 있다 MAY.

참고

위 규칙은 CDM 인스턴스와 연결된 모든 MediaKeys 객체 및 모든 MediaKeySession 객체가 파괴될 때까지 CDM 인스턴스가 파괴되어서는 안 됨을 의미한다.

MediaKeySession 객체가 페이지에서 접근할 수 없게 될 때 닫힘 상태가 아니면, CDM은 그 객체와 연결된 키 세션을 닫아야 SHALL 한다.

키 세션을 닫으면 명시적으로 저장되지 않은 모든 라이선스와 키가 폐기된다.

모범 사례 4: 다른 작업을 수행하기 전에 키 세션이 확실히 닫혀 있어야 하는 경우, close()를 호출하고 반환된 promise를 기다린다. 자동 세션 닫힘의 타이밍에 의존하지 않는다.

키 세션이 정확히 언제 닫히는지는 구현 세부사항이다.

프로미스를 반환하는 메서드의 경우, 모든 오류는 반환된 Promise를 거부하여 비동기적으로 보고된다. 여기에는 [WEBIDL] 타입 매핑 오류도 포함된다.

알고리즘의 다음 단계는 프로미스를 거부할 때 항상 중단된다.

WebIDLenum MediaKeySessionClosedReason {
  "internal-error",
  "closed-by-application",
  "release-acknowledged",
  "hardware-context-reset",
  "resource-evicted"
};

MediaKeySessionClosedReason 열거형은 다음과 같이 정의된다:

열거형 설명
internal-error 세션은 CDM 안의 복구할 수 없는 오류 때문에 닫혔다. 이 상황이 발생하면, 애플리케이션은 이 MediaKeys 인스턴스에서 새 세션을 생성해서는 안 된다 MUST NOT.
closed-by-application 세션은 애플리케이션이 세션의 close() 메서드를 명시적으로 호출했기 때문에 닫혔다.
release-acknowledged 세션은 CDM라이선스 파기 기록 확인을 받았기 때문에 닫혔다.
hardware-context-reset 세션은 CDM의 원래 하드웨어 컨텍스트가 재설정되었기 때문에 닫혔다. 이 상황이 발생하면, 사용자 에이전트는 애플리케이션이 이 MediaKeys 인스턴스에서 새 세션을 생성할 수 있도록 허용해야 MUST 한다.
참고

이는 장치 최대 절전, 모니터 구성 변경 등 많은 이유로 발생할 수 있다. 하드웨어 컨텍스트 재설정의 정확한 이유는 구현에 따라 다르다.

resource-evicted 세션은 시스템이 다른 세션 생성을 허용하기 위해 리소스를 회수해야 했기 때문에 닫혔다.
참고

이는 애플리케이션이 세션 리소스에 대한 장치별 제한에 도달하고 있음을 의미한다. 닫힌 세션이 어떤 이유로 여전히 필요하다면, 애플리케이션 개발자는 필요한 세션 수를 줄이거나 필요 없는 세션을 선제적으로 닫는 전략을 고려해야 한다.

WebIDL[Exposed=Window, SecureContext] interface MediaKeySession : EventTarget {
  readonly        attribute DOMString                            sessionId;
  readonly        attribute unrestricted double                  expiration;
  readonly        attribute Promise<MediaKeySessionClosedReason> closed;
  readonly        attribute MediaKeyStatusMap                    keyStatuses;
                  attribute EventHandler                         onkeystatuseschange;
                  attribute EventHandler                         onmessage;
  Promise<undefined>    generateRequest (DOMString initDataType, BufferSource initData);
  Promise<boolean> load (DOMString sessionId);
  Promise<undefined>    update (BufferSource response);
  Promise<undefined>    close ();
  Promise<undefined>    remove ();
};

6.1 속성

sessionId 타입은 DOMString이며, 읽기 전용

이 객체와 연결된 키 또는 라이선스에 대한 세션 ID.

expiration 타입은 unrestricted double이며, 읽기 전용

세션의 모든 키에 대한 만료 시간, 또는 그러한 시간이 존재하지 않거나 라이선스가 명시적으로 절대 만료되지 않는 경우 NaN으로, 이는 CDM에 의해 결정된다. 이 값은 세션 수명 동안 변경될 수 있으며, 예를 들어 어떤 동작이 윈도우의 시작을 트리거하는 경우가 이에 해당한다.

closed 타입은 Promise<MediaKeySessionClosedReason>이며, 읽기 전용

세션 닫힘 알고리즘이 실행된 결과로 객체가 닫힘 상태가 될 때 신호를 보낸다. 이 프로미스는 이행될 수만 있으며 절대 거부되지 않는다.

keyStatuses 타입은 MediaKeyStatusMap이며, 읽기 전용

세션에 알려진 키 ID에서 연결된 키의 현재 상태로 가는 읽기 전용 맵에 대한 참조. 각 항목은 고유한 키 ID를 가져야 MUST 한다.

참고

맵 항목과 그 값은 이벤트 루프가 도는 언제든 갱신될 수 있다. 맵은 결코 불일치하거나 부분적으로 갱신되어서는 안 되지만 MUST NOT, 접근 사이에 이벤트 루프가 돌면 접근 사이에 변경될 수 있다. 키 ID는 load() 또는 update() 호출의 결과로 추가될 수 있다. 키 ID는 기존 키에 대한 지식을 제거하는(또는 기존 키 집합을 새 집합으로 대체하는) update() 호출의 결과로 제거될 수 있다. 키 ID는 만료와 같이 사용할 수 없게 되었다는 이유로 제거되어서는 안 된다 MUST NOT. 대신, 그러한 키에는 "expired"와 같은 적절한 상태가 주어져야 MUST 한다.

일부 오래된 플랫폼에는 키 ID를 노출하지 않는 키 시스템 구현이 포함될 수 있으며, 이로 인해 준수하는 사용자 에이전트 구현을 제공하는 것이 불가능해진다. 그러한 경우 상호 운용성을 극대화하기 위해, 비어 있지 않은 목록이 적절할 때마다 이 객체의 집계된 상태에 가장 적절한 MediaKeyStatus와 1바이트 키 ID 0을 포함하는 단일 쌍으로 맵이 채워진다 (예: 이 객체가 나타내는 키 세션를 포함할 수 있는 경우).

onkeystatuseschange 타입은 EventHandler

keystatuseschange 이벤트에 대한 이벤트 핸들러.

onmessage 타입은 EventHandler

message 이벤트에 대한 이벤트 핸들러.

6.2 메서드

generateRequest()

initData에 기반하여 라이선스 요청을 생성한다. 알고리즘이 성공하고 프로미스가 이행되면, 타입이 "license-request" 또는 "individualization-request"인 message가 항상 큐에 들어간다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 closing or closed 값이 true이면, InvalidStateError로 거부된 프로미스를 반환한다.

  2. 이 객체의 uninitialized 값이 false이면, InvalidStateError로 거부된 프로미스를 반환한다.

  3. 이 객체의 uninitialized 값을 false로 둔다.

  4. initDataType이 빈 문자열이면, 새로 생성된 TypeError로 거부된 프로미스를 반환한다.

  5. initData가 빈 배열이면, 새로 생성된 TypeError로 거부된 프로미스를 반환한다.

  6. 이 객체의 cdm implementation 값이 나타내는 키 시스템 구현이 initDataType초기화 데이터 타입으로 지원하지 않으면, NotSupportedError로 거부된 프로미스를 반환한다. 문자열 비교는 대소문자를 구분한다.

  7. init datainitData 매개변수 내용의 사본으로 둔다.

  8. session type을 이 객체의 session type으로 둔다.

  9. promise를 새 프로미스로 둔다.

  10. 다음 단계를 병렬로 실행한다:

    1. init datainitDataType에 대해 유효하지 않으면, 새로 생성된 TypeErrorpromise를 거부한다.

    2. sanitized init datainit data의 검증되고 정제된 버전으로 둔다.

      사용자 에이전트는 초기화 데이터CDM에 전달하기 전에 철저히 검증해야 MUST 한다. 여기에는 필드의 길이와 값이 합리적인지 확인하고, 값이 합리적인 한계 안에 있는지 확인하며, 관련 없거나 지원되지 않거나 알 수 없는 데이터 또는 필드를 제거하는 것이 포함된다. 사용자 에이전트가 초기화 데이터를 미리 파싱하고, 정제하고, 및/또는 완전히 정제된 버전을 생성하는 것이 RECOMMENDED된다. initDataType이 지정한 초기화 데이터 형식이 여러 항목을 지원하는 경우, 사용자 에이전트는 CDM이 필요로 하지 않는 항목을 제거해야 SHOULD 한다. 사용자 에이전트는 초기화 데이터 안의 항목 순서를 다시 정렬해서는 안 된다 MUST NOT.

    3. 앞의 단계가 실패하면, 새로 생성된 TypeErrorpromise를 거부한다.

    4. sanitized init data가 비어 있으면, NotSupportedErrorpromise를 거부한다.

    5. session id를 빈 문자열로 둔다.

    6. message를 null로 둔다.

    7. message type을 null로 둔다.

    8. cdm을 이 객체의 cdm instance 값이 나타내는 CDM 인스턴스로 둔다.

    9. cdm을 사용하여 다음 단계를 실행한다:

      1. sanitized init datacdm에서 지원되지 않으면, NotSupportedErrorpromise를 거부한다.

      2. 다음 목록에서 session type의 값에 해당하는 단계를 따른다:

        "temporary"

        requested license type을 영속화할 수 없는 임시 라이선스로 둔다.

        참고

        반환되는 라이선스는 영속화할 수 없어야 하며, 이와 관련된 정보를 영속화할 것을 요구해서도 안 된다.

        "persistent-license"

        requested license type을 영속화 가능한 라이선스로 둔다.

      3. session id를 고유한 세션 ID 문자열로 둔다.

        session type에 대해 영속 세션 타입인가? 알고리즘을 실행한 결과가 true이면, 그 ID는 이 객체의 Document출처 안에서, Document와 브라우징 세션 전체를 포함하여 시간에 걸쳐 고유해야 MUST 한다.

      4. requested license type에 대한 라이선스 요청을 sanitized init data에 기반하여 생성할 수 있는 경우:
        1. messageinitDataType에 따라 해석된 sanitized init data에 기반하여 생성된, requested license type에 대한 라이선스 요청으로 둔다.

          cdmsanitized init data를 통해 제공되지 않은 미디어 데이터를 포함하여 어떤 스트림별 데이터도 사용해서는 안 된다 MUST NOT.

          cdm은 이 시점에서 세션 ID를 포함한 세션 데이터를 저장해서는 안 된다 SHOULD NOT. 세션 저장소 및 영속성을 참고한다.

        2. message type을 "license-request"로 둔다.

        그 외의 경우:
        1. messagerequested license type에 대한 라이선스 요청을 sanitized init data에 기반하여 생성하기 전에 처리되어야 하는 요청으로 둔다.

          이후 update() 호출에서 CDMinitDataType에 따라 해석되는 sanitized init data에 기반하여 requested license type에 대한 라이선스 요청을 생성해야 MUST 한다.

        2. message typemessage의 타입, 즉 "license-request" 또는 "individualization-request"를 반영하게 한다.

    10. 다음 단계를 실행하도록 태스크를 큐에 넣는다:

      1. 앞의 단계 중 하나라도 리소스 부족 때문에 실패했으면, QuotaExceededErrorpromise를 거부한다.

      2. 앞의 단계 중 하나라도 다른 이유로 실패했으면, 적절한 오류 이름을 이름으로 가지는 새 DOMException으로 promise를 거부한다.

      3. sessionId 속성을 session id로 설정한다.

      4. 이 객체의 callable 값을 true로 설정한다.

      5. promiseundefined로 이행한다.

      6. session에 대해 "message" 이벤트 큐에 넣기 알고리즘을 실행하고, message typemessage를 제공한다.

  11. promise를 반환한다.

load()

지정된 세션에 대해 저장된 데이터를 이 객체로 로드한다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 closing or closed 값이 true이면, InvalidStateError로 거부된 프로미스를 반환한다.

  2. 이 객체의 uninitialized 값이 false이면, InvalidStateError로 거부된 프로미스를 반환한다.

  3. 이 객체의 uninitialized 값을 false로 둔다.

  4. sessionId가 빈 문자열이면, 새로 생성된 TypeError로 거부된 프로미스를 반환한다.

  5. 이 객체의 session type에 대해 영속 세션 타입인가? 알고리즘을 실행한 결과가 false이면, 새로 생성된 TypeError로 거부된 프로미스를 반환한다.

  6. origin을 이 객체의 Document출처로 둔다.

  7. promise를 새 프로미스로 둔다.

  8. 다음 단계를 병렬로 실행한다:

    1. sanitized session IDsessionId의 검증 및/또는 정제된 버전으로 둔다.

      참고

      사용자 에이전트는 sessionId 값을 CDM에 전달하기 전에 철저히 검증해야 한다. 최소한 여기에는 길이와 값이 합리적인지 확인하는 것(예: 수십 문자보다 길지 않고 영숫자인지)이 포함되어야 한다.

    2. 앞의 단계가 실패했거나 sanitized session ID가 비어 있으면, 새로 생성된 TypeErrorpromise를 거부한다.

    3. 이 객체의 Document 안에 닫힘 상태가 아니며, sessionId 속성이 sanitized session IDMediaKeySession 객체가 있으면, QuotaExceededErrorpromise를 거부한다.

      참고

      다시 말해, 이 브라우징 컨텍스트 안에서 이 sanitized session ID에 대해 닫히지 않은 세션이 타입과 관계없이 이미 존재하면 세션을 만들지 않는다.

    4. expiration timeNaN으로 둔다.

    5. message를 null로 둔다.

    6. message type을 null로 둔다.

    7. cdm을 이 객체의 cdm instance 값이 나타내는 CDM 인스턴스로 둔다.

    8. cdm을 사용하여 다음 단계를 실행한다:

      1. origin 안에 sanitized session ID에 대해 저장된 데이터가 없으면, promisefalse로 이행하고 이 알고리즘의 병렬 단계를 중단한다.

      2. 저장된 세션의 session type이 현재 MediaKeySession session type과 같지 않으면, 새로 생성된 TypeErrorpromise를 거부한다.

      3. session dataorigin 안의 sanitized session ID에 대해 저장된 데이터로 둔다. 이는 다른 출처의 데이터나 출처와 연결되지 않은 데이터를 포함해서는 안 된다 MUST NOT.

      4. 어떤 Document 안에든 닫힘 상태가 아니며 session data를 나타내는 MediaKeySession 객체가 있으면, QuotaExceededErrorpromise를 거부한다.

        참고

        다시 말해, 어떤 브라우징 컨텍스트 안에서든 이 sanitized session ID에 대해 닫히지 않은 영속 세션이 이미 존재하면 세션을 만들지 않는다.

      5. session data를 로드한다.

      6. session data가 세션의 만료 시간을 나타내면, expiration time을 그 만료 시간으로 둔다.

      7. 메시지를 보내야 하는 경우, 다음 단계를 실행한다:

        1. messagesession data에 기반하여 생성된 메시지로 둔다.

        2. message type을 그 메시지에 대한 적절한 MediaKeyMessageType으로 둔다.

    9. 다음 단계를 실행하도록 태스크를 큐에 넣는다:

      1. 앞의 단계 중 하나라도 실패했으면, 적절한 오류 이름으로 promise를 거부한다.

      2. sessionId 속성을 sanitized session ID로 설정한다.

      3. 이 객체의 callable 값을 true로 설정한다.

      4. 로드된 세션이 어떤 키에 대한 정보를 포함하면(알려진 키가 있으면), session에 대해 키 상태 갱신 알고리즘을 실행하고, 각 키의 키 ID와 적절한 MediaKeyStatus를 제공한다.

        키의 상태를 확실히 결정하기 위해 추가 처리가 필요하다면 "status-pending"을 사용한다. 하나 이상의 키에 대한 추가 처리가 완료되면, 실제 상태로 키 상태 갱신 알고리즘을 다시 실행한다.

      5. session에 대해 만료 갱신 알고리즘을 실행하고, expiration time을 제공한다.

      6. promisetrue로 이행한다.

      7. message가 null이 아니면, session에 대해 "message" 이벤트 큐에 넣기 알고리즘을 실행하고, message typemessage를 제공한다.

  9. promise를 반환한다.

update()

라이선스를 포함한 메시지를 CDM에 제공한다.

response 매개변수는 CDM에 제공할 메시지를 포함한다. 내용은 키 시스템별이다. 이는 실행 가능한 코드를 포함해서는 안 된다 MUST NOT.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 closing or closed 값이 true이면, InvalidStateError로 거부된 프로미스를 반환한다.

  2. 이 객체의 callable 값이 false이면, InvalidStateError로 거부된 프로미스를 반환한다.

  3. response가 빈 배열이면, 새로 생성된 TypeError로 거부된 프로미스를 반환한다.

  4. response copyresponse 매개변수 내용의 사본으로 둔다.

  5. promise를 새 프로미스로 둔다.

  6. 다음 단계를 병렬로 실행한다:

    1. sanitized responseresponse copy의 검증 및/또는 정제된 버전으로 둔다.

      참고

      사용자 에이전트는 응답을 CDM에 전달하기 전에 철저히 검증해야 한다. 여기에는 값이 합리적인 한계 안에 있는지 확인하고, 관련 없는 데이터나 필드를 제거하고, 미리 파싱하고, 정제하고, 및/또는 완전히 정제된 버전을 생성하는 것이 포함될 수 있다. 사용자 에이전트는 필드의 길이와 값이 합리적인지 확인해야 한다. 알 수 없는 필드는 거부하거나 제거해야 한다.

    2. 앞의 단계가 실패했거나 sanitized response가 비어 있으면, 새로 생성된 TypeErrorpromise를 거부한다.

    3. message를 null로 둔다.

    4. message type을 null로 둔다.

    5. session closed를 false로 둔다.

    6. cdm을 이 객체의 cdm instance 값이 나타내는 CDM 인스턴스로 둔다.

    7. cdm을 사용하여 다음 단계를 실행한다:

      1. sanitized response의 형식이 어떤 방식으로든 유효하지 않으면, 새로 생성된 TypeErrorpromise를 거부한다.

      2. 다음 목록에서 첫 번째로 일치하는 조건에 대한 규정에 따라 sanitized response를 처리한다:

        sanitized response가 라이선스 또는 키를 포함하는 경우
        참고

        여기에는 초기 라이선스, 갱신된 라이선스, 라이선스 갱신 메시지가 포함된다.

        다음 목록에서 첫 번째로 일치하는 조건에 대한 규정에 따라 sanitized response를 처리한다:

        sessionType이 "temporary"이고 sanitized response가 그 안에 포함된 모든 라이선스, 키 또는 유사한 세션 데이터를 포함한 세션 데이터를 저장해야 한다고 지정하지 않는 경우
        어떤 세션 데이터도 저장하지 않고 sanitized response를 처리한다.
        sessionType이 "persistent-license"이고 sanitized response가 영속화 가능한 라이선스를 포함하는 경우
        sanitized response를 처리하고, sanitized response에 포함된 라이선스/키와 관련 세션 데이터를 저장한다. 그러한 데이터는 이 객체의 Document출처만 접근할 수 있도록 저장되어야 MUST 한다.
        그 외의 경우

        새로 생성된 TypeErrorpromise를 거부한다.

        세션 저장소 및 영속성도 참고한다.

        각 세션에 대한 키를 포함한 상태 정보는, 중복되는 키 ID를 포함하더라도 하나의 세션을 닫는 것이 다른 세션의 관찰 가능한 상태에 영향을 주지 않는 방식으로 저장되어야 MUST 한다.

        참고

        sanitized response가 키 및/또는 관련 데이터를 포함하는 경우, cdm은 키 ID로 인덱싱된 키와 관련 데이터를 (메모리에) 저장할 가능성이 높다.

        참고

        세션 안에서의 대체 알고리즘은 키 시스템에 따라 다르다.

        참고

        CDM 구현이 표준적이고 합리적으로 높은 MediaKeySession 객체당 최소 키 수와 표준 대체 알고리즘, 그리고 표준적이고 합리적으로 높은 MediaKeySession 객체 수를 지원하는 것이 RECOMMENDED된다. 이는 합리적인 수의 키 로테이션 알고리즘이 사용자 에이전트 전반에서 구현될 수 있게 하며, 같은 요소의 다양한 스트림 (예: 적응형 스트림, 다양한 오디오 및 비디오 트랙)이 서로 다른 키를 사용하는 사용 사례에서 재생 중단 가능성을 줄일 수 있다.

        sanitized response라이선스 파기 기록 확인을 포함하고 sessionType이 "persistent-license"인 경우

        다음 단계를 실행한다:

        1. 키 세션을 닫고, 이 객체와 연결된 저장된 모든 세션 데이터를 지운다. 여기에는 sessionId라이선스 파기 기록이 포함된다.

          참고

          이후 이 객체의 sessionId 값으로 load()를 호출하면, 해당 세션 ID에 대해 저장된 데이터가 없기 때문에 실패한다.

        2. session closed를 true로 설정한다.

        그 외의 경우
        어떤 세션 데이터도 저장하지 않고 sanitized response를 처리한다.
        참고

        예를 들어, sanitized response는 다른 message 이벤트를 생성하는 데 사용될 정보를 포함할 수 있다. 이 경우, 내용을 sessionType에 대해 검증할 필요가 없다.

      3. 메시지를 보내야 하는 경우, 다음 단계를 실행한다:

        1. message를 그 메시지로 둔다.

        2. message type을 그 메시지에 대한 적절한 MediaKeyMessageType으로 둔다.

    8. 다음 단계를 실행하도록 태스크를 큐에 넣는다:

      1. session closed가 true인 경우:

        이 객체에 대해 이유 "release-acknowledged"와 함께 세션 닫힘 알고리즘을 실행한다.

        그 외의 경우:

        다음 단계를 실행한다:

        1. 이 객체에 대해 CDM알려진 키 집합이 변경되었거나 어떤 키의 상태가 변경되었으면, session에 대해 키 상태 갱신 알고리즘을 실행하고, 각 알려진 키의 키 ID와 적절한 MediaKeyStatus를 제공한다.

          키의 상태를 확실히 결정하기 위해 추가 처리가 필요하다면 "status-pending"을 사용한다. 하나 이상의 키에 대한 추가 처리가 완료되면, 실제 상태로 키 상태 갱신 알고리즘을 다시 실행한다.

        2. 세션의 만료 시간이 변경되었으면, session에 대해 만료 갱신 알고리즘을 실행하고, 새 만료 시간을 제공한다.

        3. 앞의 단계 중 하나라도 실패했으면, 적절한 오류 이름을 이름으로 가지는 새 DOMException으로 promise를 거부한다.

        4. message가 null이 아니면, session에 대해 "message" 이벤트 큐에 넣기 알고리즘을 실행하고, message typemessage를 제공한다.

      2. promiseundefined로 이행한다.

  7. promise를 반환한다.

close()

애플리케이션이 더 이상 세션을 필요로 하지 않으며 CDM이 세션과 연결된 모든 리소스를 해제하고 이를 닫아야 함을 나타낸다. 영속화된 데이터는 해제되거나 지워져서는 안 된다.

참고

반환된 프로미스는 요청이 처리되면 이행되며, closed 속성 프로미스는 세션이 닫힐 때 "closed-by-application"로 이행된다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 closing or closed 값이 true이면, undefined로 이행된 프로미스를 반환한다.

  2. 이 객체의 callable 값이 false이면, InvalidStateError로 거부된 프로미스를 반환한다.

  3. promise를 새 프로미스로 둔다.

  4. 이 객체의 closing or closed 값을 true로 설정한다.

  5. 다음 단계를 병렬로 실행한다:

    1. cdm을 이 객체의 cdm instance 값이 나타내는 CDM 인스턴스로 둔다.

    2. cdm을 사용하여 이 객체와 연결된 키 세션을 닫는다.

      참고

      키 세션을 닫으면 명시적으로 저장되지 않은 모든 라이선스와 키가 파괴된다.

    3. 다음 단계를 실행하도록 태스크를 큐에 넣는다:

      1. promiseundefined로 이행한다.

      2. 이 객체에 대해 이유 "closed-by-application"와 함께 세션 닫힘 알고리즘을 실행한다.

  6. promise를 반환한다.

remove()

세션과 연결된 모든 라이선스와 키를 제거한다. 영속 세션 타입의 경우, 릴리스 메시지 확인이 update()에 의해 처리되면 각 세션 타입에 대해 정의된 대로 다른 세션 데이터가 지워진다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 closing or closed 값이 true이면, InvalidStateError로 거부된 프로미스를 반환한다.

  2. 이 객체의 callable 값이 false이면, InvalidStateError로 거부된 프로미스를 반환한다.

  3. promise를 새 프로미스로 둔다.

  4. 다음 단계를 병렬로 실행한다:

    1. cdm을 이 객체의 cdm instance 값이 나타내는 CDM 인스턴스로 둔다.

    2. message를 null로 둔다.

    3. message type을 null로 둔다.

    4. cdm을 사용하여 다음 단계를 실행한다:

      1. 세션과 연결된 라이선스 및/또는 키가 있으면:

        1. 세션과 연결된 라이선스 및/또는 키를 파괴한다.

          참고

          이는 라이선스 및/또는 키가 메모리, 영속 저장소 또는 둘 다에 있는지와 관계없이 이를 파괴함을 의미한다.

        2. 다음 목록에서 이 객체의 session type 값에 해당하는 단계를 따른다:

          "temporary"

          다음 단계를 계속한다.

          "persistent-license"
          1. record of license destruction를 이 객체가 나타내는 라이선스에 대한 라이선스 파기 기록으로 둔다.

          2. record of license destruction를 저장한다.

          3. messagerecord of license destruction을 포함하거나 반영하는 메시지로 둔다.

    5. 다음 단계를 실행하도록 태스크를 큐에 넣는다:

      1. session에 대해 키 상태 갱신 알고리즘을 실행하고, 세션 안의 모든 키 ID와 각 키에 대한 "released" MediaKeyStatus 값을 제공한다.

      2. session에 대해 만료 갱신 알고리즘을 실행하고, NaN을 제공한다.

      3. 앞의 단계 중 하나라도 실패했으면, 적절한 오류 이름을 이름으로 가지는 새 DOMException으로 promise를 거부한다.

      4. message type을 "license-release"로 둔다.

      5. promiseundefined로 이행한다.

      6. messagenull이 아니면, session에 대해 "message" 이벤트 큐에 넣기 알고리즘을 실행하고, message typemessage를 제공한다.

  5. promise를 반환한다.

6.3 MediaKeyStatusMap 인터페이스

MediaKeyStatusMap 객체는 키 ID에서 연결된 키의 현재 상태로 가는 읽기 전용 맵이다.

키의 상태는 그 키가 현재 사용 중인지 여부 및 미디어 데이터와 독립적이다.

참고

예를 들어, 어떤 키에 현재 충족될 수 없는 출력 요구사항이 있다면, 그 키가 미디어 데이터를 복호화하는 데 필요했는지 또는 현재 필요한지 여부와 관계없이, 키의 상태는 적절하게 "output-downscaled" 또는 "output-restricted"여야 한다.

WebIDL[Exposed=Window, SecureContext] interface MediaKeyStatusMap {
  iterable<BufferSource,MediaKeyStatus>;
  readonly attribute unsigned long size;
  boolean has (BufferSource keyId);
  (MediaKeyStatus or undefined) get (BufferSource keyId);
};

6.3.1 속성

size 타입은 unsigned long이며, 읽기 전용

알려진 키의 수.

6.3.2 메서드

has()

keyId가 식별하는 키의 상태가 알려져 있으면 true를 반환한다.

get()

keyId가 식별하는 키의 MediaKeyStatus를 반환하거나, keyId가 식별하는 키의 상태가 알려져 있지 않으면 undefined를 반환한다.

이 인터페이스는 iterable [WebIDL]에 의해 제공되는 entries, keys, values, forEach@@iterator 메서드를 가진다.

반복할 값 쌍은 모든 알려진 키에 대해 키 ID와 연결된 MediaKeyStatus 값으로 형성된 쌍의 집합을 키 ID로 정렬한 스냅샷이다. 키 ID는 다음과 같이 비교된다: 길이가 m인 키 ID A와 길이가 n인 키 ID B에 대해, m <= n이 되도록 배정하면, Am 옥텟이 B의 처음 m 옥텟보다 사전식 순서로 작거나, 그 옥텟들이 같고 m < n인 경우 그리고 오직 그 경우에만 A < B로 둔다.

WebIDLenum MediaKeyStatus {
  "usable",
  "expired",
  "released",
  "output-restricted",
  "output-downscaled",
  "usable-in-future",
  "status-pending",
  "internal-error"
};

MediaKeyStatus 열거형은 다음과 같이 정의된다:

열거형 설명
usable CDM은 키가 현재 복호화에 사용할 수 있음을 확신한다.
현재 복호화에 사용할 수 없을 수도 있는 키는 이 상태를 가져서는 안 된다 MUST NOT.
expired 키의 만료 시간이 지났기 때문에 키는 더 이상 복호화에 사용할 수 없다.
expiration 속성이 나타내는 시간은 현재 시간보다 이전이어야 MUST 한다. 세션 안의 다른 모든 키도 이 상태를 가져야 MUST 한다.
released 키 자체는 더 이상 CDM에서 사용할 수 없지만, 라이선스 파기 기록과 같은 키에 대한 정보는 사용할 수 있다.
output-restricted 키와 연결된 출력 제한이 있으며, 이는 현재 충족될 수 없다. 이 키로 복호화된 미디어 데이터는 출력 제한에 따라 필요한 경우 제시가 차단될 수 있다. 애플리케이션은 키와 연결된 출력 제한을 트리거할 스트림의 사용을 피해야 한다.
output-downscaled 키와 연결된 출력 제한이 있으며, 이는 현재 충족될 수 없다. 이 키로 복호화된 미디어 데이터는 출력 제한에 따라 필요한 경우 더 낮은 품질(예: 해상도)로 제시될 수 있다. 애플리케이션은 키와 연결된 출력 제한을 트리거할 스트림의 사용을 피해야 한다.
다운스케일링 지원은 OPTIONAL이다. 애플리케이션은 출력 요구사항을 충족할 수 없을 때 중단 없는 재생을 보장하기 위해 다운스케일링에 의존해서는 안 된다 SHOULD NOT.
usable-in-future 시작 시간이 미래이기 때문에 키는 아직 복호화에 사용할 수 없다. 키는 그 시작 시간에 도달하면 사용할 수 있게 된다.
status-pending 키의 상태는 아직 알려져 있지 않으며 결정 중이다. 상태가 결정되면 실제 상태로 갱신된다.
internal-error 다른 값과 무관한 CDM 안의 오류 때문에 키는 현재 복호화에 사용할 수 없다. 이 값은 애플리케이션이 조치할 수 있는 값이 아니다.

MediaKeyMessageEvent 객체는 message 이벤트에 사용된다.

WebIDLenum MediaKeyMessageType {
  "license-request",
  "license-renewal",
  "license-release",
  "individualization-request"
};

MediaKeyMessageType은 다음과 같이 정의된다:

열거형 설명
license-request 메시지는 새 라이선스에 대한 요청을 포함한다.
license-renewal 메시지는 기존 라이선스를 갱신하기 위한 요청을 포함한다.
license-release 메시지는 라이선스 파기 기록을 포함한다.
individualization-request 메시지는 앱 지원 개별화(또는 재개별화)에 대한 요청을 포함한다.
다른 모든 메시지와 마찬가지로, 메시지 안의 모든 식별자는 출처 및 프로필별로 구별되어야 MUST 하며, 구별 영구 식별자여서는 안 된다 MUST NOT.
WebIDL[Exposed=Window, SecureContext]
interface MediaKeyMessageEvent : Event {
  constructor(DOMString type, MediaKeyMessageEventInit eventInitDict);
  readonly attribute MediaKeyMessageType messageType;
  readonly attribute ArrayBuffer         message;
};

6.4.1 속성

messageType 타입은 MediaKeyMessageType이며, 읽기 전용
메시지의 타입.

구현은 애플리케이션이 메시지 타입을 처리하도록 요구해서는 안 된다 MUST NOT. 구현은 메시지를 구별하지 않는 애플리케이션을 지원해야 MUST 하며, 애플리케이션이 메시지 타입을 처리하도록 요구해서는 안 된다 MUST NOT. 구체적으로, 키 시스템은 모든 타입의 메시지를 단일 URL로 전달하는 것을 지원해야 MUST 한다.

참고

이 속성은 애플리케이션이 메시지를 파싱하지 않고 메시지를 구별할 수 있게 한다. 이는 선택적 애플리케이션 및/또는 서버 최적화를 가능하게 하기 위한 것이지만, 애플리케이션이 이를 사용해야 하는 것은 아니다.

message 타입은 ArrayBuffer이며, 읽기 전용
CDM에서 온 메시지. 메시지는 키 시스템별이다.

6.4.2 MediaKeyMessageEventInit

WebIDLdictionary MediaKeyMessageEventInit : EventInit {
  required MediaKeyMessageType messageType;
  required ArrayBuffer         message;
};
6.4.2.1 딕셔너리 MediaKeyMessageEventInit 멤버
messageType 타입은 MediaKeyMessageType
메시지의 타입.
message 타입은 ArrayBuffer
메시지.

6.5 이벤트 요약

이 절은 비규범적이다.

이벤트 이름 인터페이스 디스패치되는 시점...
keystatuseschange Event 세션의 키 또는 그 상태에 변경이 있었다.
message MediaKeyMessageEvent CDM이 세션에 대한 메시지를 생성했다.

6.6 알고리즘

6.6.1 "message" 이벤트 큐에 넣기

"message" 이벤트 큐에 넣기 알고리즘은 메시지 이벤트를 MediaKeySession 객체에 큐에 넣는다. 이 알고리즘을 실행하라는 요청에는 대상 MediaKeySession 객체, message type, 그리고 message가 포함된다.

message는 암호화된 형태라 하더라도 구별 영구 식별자를 포함해서는 안 된다 MUST NOT. messageMediaKeySession 객체의 use distinctive identifier 값이 false인 경우, 암호화된 형태라 하더라도 구별 식별자를 포함해서는 안 된다 MUST NOT.

다음 단계가 실행된다:

  1. session을 지정된 MediaKeySession 객체로 둔다.

  2. 버블링하지 않고 취소할 수 없는 message라는 이름의 이벤트를 생성하고, MediaKeyMessageEvent 인터페이스를 사용하여 그 type 속성을 message로 설정하고 그 isTrusted 속성을 true로 초기화한 뒤, session에 발송하도록 태스크를 큐에 넣는다.

    이벤트 인터페이스 MediaKeyMessageEvent는 다음을 가진다:

6.6.2 키 상태 갱신

키 상태 갱신 알고리즘은 MediaKeySession에 대한 알려진 키 집합 또는 하나 이상의 키 상태를 갱신한다. 이 알고리즘을 실행하라는 요청에는 대상 MediaKeySession 객체와 키 ID 및 연결된 MediaKeyStatus 쌍의 시퀀스가 포함된다.

참고

이 알고리즘은 항상 태스크 안에서 실행된다.

다음 단계가 실행된다:

  1. session을 연결된 MediaKeySession 객체로 둔다.

  2. input statuses를 키 ID 및 연결된 MediaKeyStatus 쌍의 시퀀스로 둔다.

  3. statusessessionkeyStatuses 속성으로 둔다.

  4. statuses의 내용을 대체하기 위해 다음 단계를 실행한다:

    1. statuses를 비운다.

    2. input statuses의 각 쌍에 대해.

      1. pair를 그 쌍으로 둔다.

      2. pair의 키 ID에 대한 항목을 statuses에 삽입하고, 그 값을 pairMediaKeyStatus 값으로 한다.

    참고

    이 단계의 효과는 sessionkeyStatuses 속성에 대한 기존 참조를 무효화하지 않고 그 내용을 대체하는 것이다. 이 대체는 스크립트 관점에서 원자적이다. 즉, 스크립트는 부분적으로 채워진 시퀀스를 결코 보아서는 안 된다 MUST NOT.

  5. session에서 keystatuseschange라는 이름의 이벤트를 발화하도록 태스크를 큐에 넣는다.

  6. session을 생성한 MediaKeys 객체가 mediaKeys 속성인 각 미디어 요소에 대해 필요하면 재생 재개 시도 알고리즘을 실행하도록 태스크를 큐에 넣는다.

6.6.3 만료 갱신

만료 갱신 알고리즘은 MediaKeySession만료 시간을 갱신한다. 이 알고리즘을 실행하라는 요청에는 대상 MediaKeySession 객체와 새 만료 시간이 포함되며, 이는 NaN일 수 있다.

참고

이 알고리즘은 항상 태스크 안에서 실행된다.

다음 단계가 실행된다:

  1. session을 연결된 MediaKeySession 객체로 둔다.

  2. expiration timeNaN으로 둔다.

  3. 새 만료 시간이 NaN이 아니면, expiration time을 그 만료 시간으로 둔다.

  4. sessionexpiration 속성을 시간으로 표현된 expiration time으로 설정한다.

6.6.4 세션 닫힘

세션 닫힘 알고리즘은 CDM에 의해 키 세션이 닫힌 후 MediaKeySession 상태를 갱신한다. 이 알고리즘을 실행하라는 요청에는 대상 MediaKeySession 객체와 MediaKeySessionClosedReason이 포함된다.

참고

이 알고리즘은 항상 태스크 안에서 실행된다.

세션이 닫히면, 그 세션과 연결된 라이선스와 키는 더 이상 미디어 데이터를 복호화하는 데 사용할 수 없다. 이 알고리즘이 실행된 후에는 모든 MediaKeySession 메서드가 실패하고, 이 객체에 대해 더 이상의 이벤트가 큐에 들어가지 않는다.

참고

CDM은 세션이 더 이상 필요하지 않거나 시스템 리소스가 손실된 경우와 같이 언제든 세션을 닫을 수 있다. 이 경우 CDM 상태 변경 감시 알고리즘이 변경을 감지하고 이 알고리즘을 실행한다.

다른 세션의 키는 중복되는 키 ID를 가지더라도 영향을 받아서는 안 된다 MUST.

이 알고리즘이 실행된 후에는 이 알고리즘이 큐에 넣은 이벤트에 대한 이벤트 핸들러가 실행되지만, 더 이상의 이벤트는 큐에 넣을 수 없다. 그 결과 세션을 닫는 것의 결과로 CDM이 메시지를 보낼 수 없다.

다음 단계가 실행된다:

  1. session을 연결된 MediaKeySession 객체로 둔다.

  2. promisesessionclosed 속성으로 둔다.

  3. promise가 이행되었으면, 이 단계를 중단한다.

  4. sessionclosing or closed 값을 true로 설정한다.

  5. session에 대해 키 상태 갱신 알고리즘을 실행하고 빈 시퀀스를 제공한다.

  6. session에 대해 만료 갱신 알고리즘을 실행하고 NaN을 제공한다.

  7. promise를 제공된 이유로 이행한다.

6.6.5 CDM 상태 변경 감시

CDM 상태 변경 감시 알고리즘은 CDM 상태의 다양한 측면이 변경될 때 필요한 단계를 실행한다.

참고

이 알고리즘은 다른 알고리즘이 다루지 않는 CDM 상태 변경에만 적용된다. 예를 들어 update()는 메시지, 키 상태 변경 및/또는 만료 변경을 일으킬 수 있지만, 그것들은 모두 그 알고리즘 안에서 처리된다.

참고

이 알고리즘은 항상 주 이벤트 루프와 병렬로 실행된다.

다음 단계가 실행된다:

  1. sessionMediaKeySession 객체로 둔다.

  2. cdmsessioncdm instance 값이 나타내는 CDM 인스턴스로 둔다.

  3. cdm에 아직 전송되지 않은 나가는 메시지가 있으면, 다음 단계를 실행하도록 태스크를 큐에 넣는다:

    1. message typemessage를 각각 메시지 타입과 메시지로 둔다.

    2. session, message typemessage를 전달하여 "message" 이벤트 큐에 넣기 알고리즘을 실행한다.

  4. cdmsession알려진 키 집합 또는 하나 이상의 키 상태를 변경했으면, 다음 단계를 실행하도록 태스크를 큐에 넣는다:

    1. statusessession알려진 각 키에 대해 하나의 쌍을 포함하는 키 ID 및 MediaKeyStatus 값 쌍의 목록으로 둔다.

    2. sessionstatuses를 전달하여 키 상태 갱신 알고리즘을 실행한다.

  5. cdmsession만료 시간을 변경했으면, 다음 단계를 실행하도록 태스크를 큐에 넣는다:

    1. expiration timesession의 새 만료 시간으로 둔다.

    2. sessionexpiration time을 전달하여 만료 갱신 알고리즘을 실행한다.

  6. cdmsession을 닫았으면, 적절한 MediaKeySessionClosedReason 값과 함께 session에 대해 세션 닫힘 알고리즘을 실행하도록 태스크를 큐에 넣는다.

  7. cdm이 하드웨어 컨텍스트 재설정 때문에 사용할 수 없게 되었으면, 이유 "hardware-context-reset"와 함께 CDM 사용 불가 알고리즘을 실행하도록 태스크를 큐에 넣는다.

  8. cdm이 다른 이유로 사용할 수 없게 되었으면, 이유 "internal-error"와 함께 CDM 사용 불가 알고리즘을 실행하도록 태스크를 큐에 넣는다.

6.7 예외

메서드는 반환된 프로미스를 simple exception [WEBIDL] 또는 DOMException으로 거부하여 오류를 보고한다. 다음의 simple exceptions 및 [WEBIDL]의 DOMException 이름이 알고리즘에서 사용된다. 알고리즘에서 지정된 원인은 각 이름 옆에 나열되어 있지만, 이 이름들은 다른 이유로도 사용될 수 있다 MAY.

이름 가능한 원인(전체 목록 아님)
TypeError 매개변수가 비어 있음.
유효하지 않은 초기화 데이터.
유효하지 않은 응답 형식.
"temporary" 세션에 영속 라이선스가 제공됨.
NotSupportedError 기존 MediaKeys 객체를 제거할 수 없음.
키 시스템이 지원되지 않음.
초기화 데이터 타입이 키 시스템에서 지원되지 않음.
세션 타입이 키 시스템에서 지원되지 않음.
초기화 데이터가 키 시스템에서 지원되지 않음.
작업이 키 시스템에서 지원되지 않음.
InvalidStateError 기존 MediaKeys 객체를 지금 제거할 수 없음.
세션이 이미 사용됨.
세션이 아직 초기화되지 않음.
세션이 닫힘.
QuotaExceededError MediaKeys 객체를 추가 HTMLMediaElement와 함께 사용할 수 없음.
이 sessionId에 대해 닫히지 않은 세션이 이미 존재함.
새 세션 또는 라이선스 요청을 생성할 리소스가 충분하지 않음.

6.8 세션 저장소 및 영속성

이 절은 알고리즘을 보완하는 세션 저장소와 지속성에 대한 개요를 제공한다.

다음 요구사항은 저장소와 지속성의 요구사항에 추가로 적용된다.

이 객체의 session type에 대해 지속 세션 유형인가? 알고리즘을 실행한 결과가 false이면, 사용자 에이전트와 CDM은 어느 시점에도 세션의 기록이나 세션과 관련된 데이터를 지속시켜서는 MUST NOT 된다. 여기에는 라이선스, 키, 라이선스 폐기 기록, 그리고 세션 ID가 포함된다.

이 절의 나머지는 지속 세션 유형인가? 알고리즘이 true를 반환하는 세션 유형에 적용된다.

CDMupdate()가 처음 호출되기 전까지 세션 ID를 포함한 세션 데이터를 저장하지 않는 것이 SHOULD NOT 된다. 구체적으로, CDMgenerateRequest() 알고리즘 동안 세션 데이터를 저장하지 않는 것이 SHOULD NOT 된다. 이는 애플리케이션이 세션을 인식하고 결국 이를 제거해야 함을 알도록 보장한다.

세션이 삭제될 때 세션과 관련된 모든 데이터는 삭제되어야 MUST 하며, 예를 들어 update()에서 라이선스 폐기 기록 확인 응답을 처리할 때가 이에 해당한다. 지속 데이터를 보라.

CDM은 주어진 세션의 데이터가 어떤 Document에서도 닫히지 않은 하나의 MediaKeySession 객체에만 존재하도록 보장해야 MUST 한다. 다시 말해, sessionId 매개변수로 지정된 세션을 나타내는 MediaKeySession이 이미 있는 경우, load()는 실패해야 MUST 한다. 이는 generateRequest()를 통해 이를 생성한 객체가 여전히 활성 상태이거나, load()를 통해 다른 객체에 로드되었기 때문일 수 있다. 세션은 이를 나타낸 적이 있는 모든 객체가 닫힌 경우에만 다시 로드될 MAY 수 있다.

지속 세션 유형인가? 알고리즘이 true를 반환하는 유형을 사용해 세션을 생성하는 애플리케이션은, 나중에 먼저 remove()를 사용하여 제거 프로세스를 시작한 다음, 메시지 교환을 포함할 수 있는 제거 프로세스가 성공적으로 완료되도록 보장함으로써 저장된 데이터를 제거하는 것이 SHOULD 된다. CDM도 적절한 경우 세션을 제거할 MAY 수 있지만, 애플리케이션은 이에 의존하지 않는 것이 SHOULD NOT 된다.

지속 저장소를 지원할 때의 추가 고려사항은 10. 보안11. 개인정보 보호를 보라.

7. HTMLMediaElement 확장

이 절은 Encrypted Media Extensions가 지원될 때 HTMLMediaElement [HTML]에 대한 추가 및 수정을 명시한다.

다음 내부 값들이 HTMLMediaElement에 추가된다:

HTMLMediaElement의 동작에는 다음 수정이 이루어진다:

프로미스를 반환하는 메서드의 경우, 모든 오류는 반환된 Promise를 거부하여 비동기적으로 보고된다. 여기에는 [WEBIDL] 타입 매핑 오류도 포함된다.

알고리즘의 단계는 프로미스를 거부할 때 항상 중단된다.

WebIDL[Exposed=Window] partial interface HTMLMediaElement {
  [SecureContext] readonly        attribute MediaKeys?   mediaKeys;
                                  attribute EventHandler onencrypted;
                                  attribute EventHandler onwaitingforkey;
  [SecureContext] Promise<undefined> setMediaKeys (MediaKeys? mediaKeys);
};

7.1 속성

mediaKeys 타입은 MediaKeys이며, 읽기 전용, nullable

이 미디어 요소에 대한 암호화된 미디어 데이터를 재생 중 복호화할 때 사용되는 MediaKeys.

onencrypted 타입은 EventHandler

encrypted 이벤트에 대한 이벤트 핸들러. 이는 모든 HTMLMediaElement가 콘텐츠 속성과 IDL 속성 모두로 지원해야 MUST 한다.

onwaitingforkey 타입은 EventHandler

waitingforkey 이벤트에 대한 이벤트 핸들러. 이는 모든 HTMLMediaElement가 콘텐츠 속성과 IDL 속성 모두로 지원해야 MUST 한다.

7.2 메서드

setMediaKeys()

재생 중 미디어 데이터를 복호화할 때 사용할 MediaKeys를 제공한다.

참고

재생 중 연결된 MediaKeys 객체를 지우거나 교체하는 것의 지원은 구현 품질 문제이다. 많은 경우 이는 좋지 않은 사용자 경험이나 거부된 프로미스를 초래한다.

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 실행해야 MUST 한다:

  1. 이 객체의 attaching media keys 값이 true이면, InvalidStateError로 거부된 프로미스를 반환한다.

  2. mediaKeysmediaKeys 속성이 같은 객체이면, undefined로 이행된 프로미스를 반환한다.

  3. 이 객체의 attaching media keys 값을 true로 둔다.

  4. promise를 새 프로미스로 둔다.

  5. 다음 단계를 병렬로 실행한다:

    1. 다음 조건이 모두 성립하면:

      • mediaKeys가 null이 아니고,

      • mediaKeys가 나타내는 CDM 인스턴스가 이미 다른 미디어 요소에서 사용 중이며

      • 사용자 에이전트가 이를 이 요소와 함께 사용할 수 없으면

      이 객체의 attaching media keys 값을 false로 두고, QuotaExceededErrorpromise를 거부한다.

    2. mediaKeys 속성이 null이 아니면, 다음 단계를 실행한다:

      1. 사용자 에이전트 또는 CDM이 연결 제거를 지원하지 않으면, 이 객체의 attaching media keys 값을 false로 두고 NotSupportedErrorpromise를 거부한다.

      2. 연결을 현재 제거할 수 없으면, 이 객체의 attaching media keys 값을 false로 두고 InvalidStateErrorpromise를 거부한다.

        참고

        예를 들어, 일부 구현은 재생 중 제거를 허용하지 않을 수 있다.

      3. mediaKeys 속성이 나타내는 CDM 인스턴스를 미디어 데이터 복호화에 사용하는 것을 중지하고, 미디어 요소와의 연결을 제거한다.

      4. 앞의 단계가 실패했으면, 이 객체의 attaching media keys 값을 false로 두고 적절한 오류 이름으로 promise를 거부한다.

    3. mediaKeys가 null이 아니면, 다음 단계를 실행한다:

      1. mediaKeys가 나타내는 CDM 인스턴스를 미디어 데이터 복호화를 위해 미디어 요소와 연결한다.

      2. 앞의 단계가 실패했으면, 다음 단계를 실행한다:

        1. mediaKeys 속성을 null로 설정한다.

        2. 이 객체의 attaching media keys 값을 false로 둔다.

        3. 이름이 적절한 오류 이름인 새 DOMException으로 promise를 거부한다.

      3. 미디어 요소에 대해 필요하면 재생 재개 시도 알고리즘을 실행하도록 태스크를 큐에 넣는다.

    4. mediaKeys 속성을 mediaKeys로 설정한다.

    5. 이 객체의 attaching media keys 값을 false로 둔다.

    6. promiseundefined로 이행한다.

  6. promise를 반환한다.

7.3 MediaEncryptedEvent 인터페이스

MediaEncryptedEvent 객체는 encrypted 이벤트에 사용된다.

WebIDL[Exposed=Window]
interface MediaEncryptedEvent : Event {
    constructor(DOMString type, optional MediaEncryptedEventInit eventInitDict = {});
    readonly        attribute DOMString    initDataType;
    readonly        attribute ArrayBuffer? initData;
};

7.3.1 속성

initDataType 타입은 DOMString이며, 읽기 전용
initData 속성에 포함된 초기화 데이터초기화 데이터 타입을 나타낸다.
initData 타입은 ArrayBuffer이며, 읽기 전용, nullable
이벤트에 대한 초기화 데이터.

7.3.2 MediaEncryptedEventInit

WebIDLdictionary MediaEncryptedEventInit : EventInit {
  DOMString    initDataType = "";
  ArrayBuffer? initData = null;
};
7.3.2.1 딕셔너리 MediaEncryptedEventInit 멤버
initDataType 타입은 DOMString이며, 기본값은 ""
초기화 데이터 타입.
initData 타입은 ArrayBuffer이며, nullable, 기본값은 null
초기화 데이터.

7.4 이벤트 요약

이 절은 비규범적이다.

이벤트 이름 인터페이스 디스패치되는 시점... 전제 조건
encrypted MediaEncryptedEvent 사용자 에이전트가 초기화 데이터미디어 데이터에서 만난다. 요소의 readyStateHAVE_METADATA와 같거나 그보다 크다.

요소가 재생 중이거나 재생된 적이 있을 수 있다.

waitingforkey Event 키를 기다리느라 재생이 차단된다. readyStateHAVE_CURRENT_DATA와 같거나 그보다 작다. 요소의 playback blocked waiting for key 값이 새롭게 true가 된다.

7.5 알고리즘

7.5.1 미디어 데이터가 암호화된 블록을 포함할 수 있음

미디어 데이터가 암호화된 블록을 포함할 수 있음 알고리즘은 사용자 에이전트가 미디어 데이터를 재생하기 전에 MediaKeys 객체의 지정을 요구하는 경우 재생을 일시 중지한다. 이 알고리즘을 실행하라는 요청에는 대상 HTMLMediaElement 객체가 포함된다.

다음 단계가 실행된다:

  1. media element를 지정된 HTMLMediaElement 객체로 둔다.

  2. media elementmediaKeys 속성이 null이고 구현이 잠재적으로 암호화된 미디어 데이터를 디코딩하기 전에 MediaKeys 객체의 지정을 요구하면, 다음 단계를 실행한다:

    참고

    애플리케이션이 setMediaKeys()를 호출하여 MediaKeys 객체를 제공하기 전에 미디어 데이터를 제공하면 이 단계에 도달할 수 있다. CDM 선택은 사용되는 파이프라인 및/또는 디코더에 영향을 줄 수 있으므로, 일부 구현은 MediaKeys 객체를 setMediaKeys()에 전달하여 CDM이 지정될 때까지 암호화된 블록을 포함할 수 있는 미디어 데이터의 재생을 지연시킬 수 있다.

    1. media element에 대해 키 대기 알고리즘을 실행한다.

    2. 재생을 재개하라는 신호를 기다린다.

7.5.2 초기화 데이터 발견

초기화 데이터 발견 알고리즘은 미디어 데이터에서 만난 초기화 데이터에 대한 encrypted 이벤트를 큐에 넣는다. 이 알고리즘을 실행하라는 요청에는 대상 HTMLMediaElement 객체가 포함된다.

다음 단계가 실행된다:

  1. media element를 지정된 HTMLMediaElement 객체로 둔다.

  2. initDataType을 빈 문자열로 둔다.

  3. initData를 null로 둔다.

  4. 미디어 데이터CORS-same-origin이고 혼합 콘텐츠아니면, 다음 단계들을 실행한다.

    1. initDataType을 초기화 데이터의 초기화 데이터 유형을 나타내는 문자열로 둔다.

    2. initData를 초기화 데이터로 둔다.

    미디어 요소가 "Upgradeable Content" [MIXED-CONTENT]의 로드를 허용할 수는 있지만, 사용자 에이전트는 그러한 미디어 데이터의 초기화 데이터를 애플리케이션에 노출해서는 MUST NOT 된다.

  5. 태스크를 큐에 넣어 버블링하지 않고 취소할 수 없는 encrypted라는 이름의 이벤트를 생성한다. 이 이벤트는 MediaEncryptedEvent 인터페이스를 사용하며, 그 type 속성은 encrypted로 설정되고 isTrusted 속성은 true로 초기화되며, 이를 media element에 디스패치한다.

    이벤트 인터페이스 MediaEncryptedEvent는 다음을 가진다.

    readyState는 변경되지 않고 어떤 알고리즘도 중단되지 않는다. 이 이벤트는 단지 정보를 제공할 뿐이다.

    미디어 데이터가 CORS-same-origin아니거나 혼합 콘텐츠인 경우, initData 속성은 null이 된다. 애플리케이션은 다른 소스에서 초기화 데이터를 가져올 수 있다.

7.5.3 암호화된 블록 발견

암호화된 블록 발견 알고리즘은 암호화된 미디어 데이터 블록을 복호화용으로 큐에 넣고, 가능하면 복호화를 시도한다. 이 알고리즘을 실행하라는 요청에는 대상 HTMLMediaElement 객체가 포함된다.

다음 단계가 실행된다:

  1. media element를 지정된 HTMLMediaElement 객체로 둔다.

  2. block을 암호화된 미디어 데이터 블록으로 둔다.

  3. blockmedia elementencrypted block queue 끝에 추가한다.

  4. media elementdecryption blocked waiting for key 값이 false이면, 복호화 시도 알고리즘을 실행한다.

7.5.4 복호화 시도

복호화 시도 알고리즘은 복호화용으로 큐에 들어간 미디어 데이터를 복호화하려고 시도한다. 이 알고리즘을 실행하라는 요청에는 대상 HTMLMediaElement 객체가 포함된다.

다음 단계가 실행된다:

  1. media element를 지정된 HTMLMediaElement 객체로 둔다.

  2. media elementencrypted block queue가 비어 있으면, 이 단계를 중단한다.

  3. media elementmediaKeys 속성이 null이 아니면, 다음 단계를 실행한다:

    1. media keys를 그 속성이 참조하는 MediaKeys 객체로 둔다.

    2. cdmmedia keyscdm instance 값이 나타내는 CDM 인스턴스로 둔다.

    3. cdm을 어떤 이유로든 더 이상 사용할 수 없으면, 다음 단계를 실행한다:

      1. 리소스 가져오기 알고리즘미디어 데이터가 손상됨 단계를 실행한다.

      2. media keys에 대해 CDM 사용 불가 알고리즘을 실행하며, 이유로 하드웨어 컨텍스트 재설정의 경우 "hardware-context-reset", 그렇지 않으면 "internal-error"를 사용한다.

      3. 이 단계를 중단한다.

    4. media keys가 생성한 MediaKeySession닫힌 상태가 아닌 것이 적어도 하나 있으면, 다음 단계를 실행한다:

      참고

      이 검사는 cdm의 로드가 완료되었음을 보장하며, 일치하는 키가 사용 가능하기 위한 전제조건이다.

      1. blockmedia elementencrypted block queue 안의 첫 번째 항목으로 둔다.

      2. block key IDblock의 키 ID로 둔다.

        참고

        키 ID는 일반적으로 컨테이너가 지정한다.

      3. cdm을 사용하여 다음 단계를 실행한다:

        1. available keysmedia keys가 생성한 세션 안의 키들의 합집합으로 둔다.

        2. block key를 null로 둔다.

        3. available keys 중 하나라도 block key ID에 대응하고 복호화에 사용할 수 있으면, session을 그 키를 포함하는 MediaKeySession 객체로 두고, block key를 그 키로 둔다.

          참고

          여러 세션이 block key ID에 대해 복호화에 사용할 수 있는 키를 포함하는 경우, 사용할 세션과 키는 키 시스템에 따라 다르다.

        4. 앞의 단계를 실행한 결과 available keys 중 하나의 상태가 변경되었으면, 영향을 받은 각 session에 대해 태스크를 큐에 넣어 키 상태 갱신 알고리즘을 실행하고, 세션 안의 모든 키 ID와 각 키에 대한 적절한 MediaKeyStatus 값을 제공한다.

        5. block key가 null이 아니면, 다음 단계를 실행한다:

          1. cdm을 사용하여 block keyblock을 복호화한다.

          2. 다음 목록에서 첫 번째로 일치하는 조건에 대한 단계를 따른다:

            복호화가 실패한 경우
            1. 미디어 데이터가 손상됨 단계를 리소스 가져오기 알고리즘에서 실행한다.

            2. cdm을 더 이상 사용할 수 없으면, media keys에 대해 CDM 사용 불가 알고리즘을 실행하며, 이유로 하드웨어 컨텍스트 재설정의 경우 "hardware-context-reset", 그렇지 않으면 "internal-error"를 사용한다.

            3. 이 단계를 중단한다.

            그 외의 경우
            1. media elementencrypted block queue 앞에서 block을 제거한다.

            2. 복호화된 블록을 정상적으로 처리한다.

              참고

              다시 말해, 블록을 디코딩한다.

            3. 이 알고리즘의 처음으로 돌아간다.

            참고

            모든 복호화 문제(예: 잘못된 키 사용)가 복호화 실패를 초래하는 것은 아니다. 그런 경우 여기에서는 오류가 발생하지 않지만, 디코딩 중에 발생할 수 있다.

          참고

          그렇지 않으면, 어떤 세션에도 block key ID에 대한 키가 없으므로 계속한다.

  4. media elementdecryption blocked waiting for key 값을 true로 설정한다.

    참고

    이 단계에는 block에 대해 복호화에 사용할 수 있는 키가 없을 때 도달한다.

    참고

    사용자 에이전트가 복호화할 수 없는 블록보다 앞에 있는 블록들을 렌더링한 뒤 (예를 들어 모든 완전한 비디오 프레임처럼 가능한 만큼), 키 대기 알고리즘을 실행한다.

    그 알고리즘은 현재 재생 위치보다 앞선 미디어 데이터를 구현이 복호화하고 디코딩할 수 있게 하면서도 보이는 동작에 영향을 주지 않도록 하기 위해 여기에서 직접 실행되지 않는다.

참고

프레임 기반 암호화의 경우, 미디어 요소가 리소스 가져오기 알고리즘의 일부로 프레임을 디코딩하려고 시도할 때 다음과 같이 구현될 수 있다:

  1. encrypted를 false로 둔다.

  2. 프레임이 암호화되었는지 감지한다.

    프레임이 암호화된 경우
    위 단계를 실행한다.
    그 외의 경우
    계속한다.
  3. 프레임을 디코딩한다.

  4. 렌더링을 위해 프레임을 제공한다.

7.5.5 키 대기

키 대기 알고리즘은 waitingforkey 이벤트를 큐에 넣고 readyState를 갱신한다. 이 알고리즘은 HTMLMediaElement 객체가 잠재적으로 재생 중이고 그 readyStateHAVE_FUTURE_DATA와 같거나 그보다 클 때에만 호출되어야 한다. 이 알고리즘을 실행하라는 요청에는 대상 HTMLMediaElement 객체가 포함된다.

다음 단계가 실행된다:

  1. media element를 지정된 HTMLMediaElement 객체로 둔다.

  2. media elementplayback blocked waiting for key 값이 true이면, 이 단계를 중단한다.

  3. media elementplayback blocked waiting for key 값을 true로 설정한다.

    참고

    위 단계의 결과로, 미디어 요소가 아직 차단된 미디어 요소가 아니었다면 그렇게 된다. 그 경우, 미디어 요소는 재생을 중지한다.

  4. 다음 목록에서 첫 번째로 일치하는 조건에 대한 단계를 따른다:

    즉시 현재 재생 위치에 대한 데이터를 사용할 수 있는 경우

    media elementreadyStateHAVE_CURRENT_DATA로 설정한다.

    그 외의 경우

    media elementreadyStateHAVE_METADATA로 설정한다.

    참고

    다시 말해, 현재 재생 위치에 대한 비디오 프레임과 오디오 데이터가 암호화되지 않았거나 성공적으로 복호화되었기 때문에 디코딩되었다면, readyStateHAVE_CURRENT_DATA로 설정한다. 그렇지 않으면, 이전에 그러한 상태였지만 데이터를 더 이상 사용할 수 없는 경우를 포함하여, readyStateHAVE_METADATA로 설정한다.

  5. media element에서 waitingforkey라는 이름의 이벤트를 발화하도록 태스크를 큐에 넣는다.

  6. 재생을 일시 중지한다.

7.5.6 필요하면 재생 재개 시도

필요하면 재생 재개 시도 알고리즘은 미디어 요소가 키를 기다리느라 차단되어 있고 필요한 키를 현재 복호화에 사용할 수 있으면 재생을 재개한다. 이 알고리즘을 실행하라는 요청에는 대상 HTMLMediaElement 객체가 포함된다.

다음 단계가 실행된다:

  1. media element를 지정된 HTMLMediaElement 객체로 둔다.

  2. media elementplayback blocked waiting for keyfalse이면, 이 단계를 중단한다.

  3. media element에 대해 복호화 시도 알고리즘을 실행한다.

  4. 사용자 에이전트가 현재 재생 위치재생 방향으로 진행시킬 수 있으면:

    1. media elementdecryption blocked waiting for key 값을 false로 설정한다.

    2. media elementplayback blocked waiting for key 값을 false로 설정한다.

      참고

      위 단계의 결과로, 미디어 요소는 더 이상 차단된 미디어 요소가 아닐 수 있으며, 따라서 재생이 재개될 수 있다.

    3. media elementreadyState 값을 적절한 대로 HAVE_CURRENT_DATA, HAVE_FUTURE_DATA 또는 HAVE_ENOUGH_DATA로 설정한다.

      참고

      HAVE_CURRENT_DATA를 넘는 상태와 canplaythrough 이벤트는 현재 키를 넘어선 키 사용 가능성을 고려하지 않는다(또는 그럴 가능성이 낮다).

      준비 상태의 변경은 또한 HTMLMediaElement 이벤트가 여기에 설명된 대로 발화되도록 할 수 있다.

7.6 미디어 요소 제한

이 절은 비규범적이다.

CDM이 처리한 미디어 데이터는 일반적인 방식으로 웹 플랫폼 API를 통해 사용할 수 없을 수 있다 MAY (예를 들어 CanvasRenderingContext2D drawImage() 메서드와 AudioContext MediaElementAudioSourceNode를 사용하는 경우). 이 명세는 그러한 미디어 데이터의 비가용성에 대한 조건을 정의하지 않는다. 그러나 그러한 API를 통해 미디어 데이터를 사용할 수 없다면, 해당 API는 미디어 데이터가 전혀 없는 것처럼 동작할 수 있다 MAY.

미디어 렌더링이 UA에 의해 수행되지 않는 경우, 예를 들어 하드웨어 기반 미디어 파이프라인의 경우에는, CSS Transforms와 같은 HTML 렌더링 기능 전체 집합을 사용할 수 없을 수 있다 MAY. 한 가지 가능한 제한은 비디오 미디어가 창의 가장자리와 평행한 변을 가진 직사각형 영역 안에 정상 방향으로만 나타나도록 제한될 수 있다는 것이다 MAY.

8. 구현 요구사항

이 절은 사용자 에이전트와 키 시스템 모두에 대한 구현 요구사항을 정의한다. 여기에는 CDM 및 서버가 포함되며, 이러한 요구사항은 알고리즘에서 명시적으로 다루지 않을 수 있다. 여기 및 명세 전반의 요구사항은 CDM이 사용자 에이전트와 분리되어 있는지 또는 사용자 에이전트의 일부인지와 관계없이 모든 구현에 적용된다.

8.1 CDM 제약

사용자 에이전트 구현자는 CDM이 이 명세의 기능을 사용하여 보호된 미디어를 재생하는 데 합리적으로 필요하지 않은 정보, 저장소 또는 시스템 기능에 접근하지 않도록 보장해야 MUST 한다. 구체적으로, CDM은 다음을 해서는 SHALL NOT 안 된다.

사용자 에이전트 구현자는 위 요구사항을 충족하기 위해 다양한 기법을 사용할 수 있다. 예를 들어, 자체 CDM도 구현하는 사용자 에이전트 구현자는 위 내용을 해당 구성요소의 설계 요구사항으로 포함할 수 있다. 제3자 CDM을 사용하는 사용자 에이전트 구현자는 금지된 정보와 구성요소에 접근할 수 없는 제한된 환경(예: "sandbox")에서 실행되도록 보장할 수 있다.

8.2 메시지 및 통신

CDM과 주고받는 모든 메시지와 통신, 예를 들어 CDM과 라이선스 서버 사이의 통신은 사용자 에이전트를 통해 전달되어야 MUST 한다. CDM은 직접적인 대역 외 네트워크 요청을 해서는 MUST NOT 된다. 직접 개별화에 설명된 것 이외의 모든 메시지와 통신은 이 명세에 정의된 API를 통해 애플리케이션을 거쳐 전달되어야 MUST 한다. 구체적으로, 애플리케이션별, 출처별, 또는 콘텐츠별 정보를 포함하거나 애플리케이션이 지정한 URL 또는 그 출처에 기반한 URL로 전송되는 모든 통신은 API를 거쳐야 MUST 한다. 여기에는 모든 라이선스 교환 메시지가 포함된다.

8.3 영속 데이터

지속 데이터에는 CDM이 저장하거나, CDM을 대신하여 사용자 에이전트가 저장한 모든 데이터 중 MediaKeys 객체의 폐기 후에도 존재하는 데이터가 포함된다. 구체적으로, 여기에는 CDM이 저장하거나 CDM을 대신하여 사용자 에이전트가 저장한 모든 식별자(고유 식별자 포함), 라이선스, 키, 키 ID, 또는 라이선스 폐기 기록이 포함된다.

8.3.1 출처별 및 브라우징 프로필별 키 시스템 저장소 사용

애플리케이션 또는 라이선스 서버에서 볼 수 있는 방식으로 메시지나 동작에 영향을 줄 수 있는 영속 데이터는 출처별 및 브라우징 프로필별 방식으로 저장되어야 MUST 하며, 비공개 브라우징 세션으로 유출되거나 거기에서 유출되어서는 안 된다 MUST NOT. 구체적으로 그러나 이것에 국한되지 않고, 세션 데이터, 라이선스, 키 및 출처별 식별자는 출처별 및 브라우징 프로필별로 저장되어야 MUST 한다.

세션 저장소 및 영속성을 참고한다.

8.3.2 영속 데이터를 지울 수 있도록 허용

영속 데이터를 사용하는 구현은 이 명세에 정의된 API와 같은 외부와 클라이언트 장치 양쪽에서 해당 데이터를 더 이상 가져올 수 없도록 사용자가 그 데이터를 지울 수 있게 해야 MUST 한다.

사용자 에이전트는 다음을 하는 것이 좋다 SHOULD:

  • 영속 데이터를 쿠키 [COOKIES] 같은 다른 사이트 데이터처럼 취급한다. 구체적으로:

    • 사용자가 쿠키 [COOKIES] 및 다른 사이트 데이터와 함께 영속 데이터를 지울 수 있도록 허용한다.

    • 사용자가 브라우징 기록을 지우는 사용자 에이전트 기능의 일부로 영속 데이터를 지울 수 있도록 허용한다.

    • "모든 데이터 제거" 기능에 영속 데이터를 포함한다.

    • 영속 데이터를 다른 사이트 데이터와 같은 UI 위치에 표시한다.

  • 사용자가 출처별 및 브라우징 프로필별 기준으로 영속 데이터를 지울 수 있도록 허용한다. 특히 특정 사이트와 연결된 쿠키 [COOKIES], 데이터베이스 등을 잊는 "이 사이트 잊기" 기능의 일부로 허용한다.

  • 영속 데이터를 지우는 작업이, 동시에 지워지지 않은 다른 종류의 로컬 저장 데이터를 이용하여 새 식별자를 이전 식별자와 다시 상관시키는 "쿠키 부활" 유형의 재상관을 방지할 만큼 충분히 원자적이도록 보장한다. 데이터의 불완전한 삭제를 참고한다.

  • 사용자가 데이터의 불완전한 삭제 가능성을 이해하는 데 도움이 되고, 쿠키 [COOKIES] 및 웹 저장소를 포함하여 데이터를 영속화하는 모든 기능과 연결된 데이터를 동시에 삭제할 수 있도록 하는 방식으로 이러한 인터페이스를 제시한다.

  • 키 시스템을 비활성화하고 다시 활성화하는 인터페이스를, 사용자가 데이터의 불완전한 삭제 가능성을 이해하는 데 도움이 되고 모든 영속 저장 기능에서 그러한 모든 데이터를 동시에 삭제할 수 있도록 하는 방식으로 제시한다.

  • 사용자가 출처별 및/또는 모든 출처에 대해 영속 데이터를 구체적으로 삭제할 수 있도록 허용한다.

8.3.3 영속 데이터 암호화 또는 난독화

사용자 에이전트는 영속 데이터를 잠재적으로 민감한 것으로 취급하는 것이 좋다 SHOULD. 이 정보의 공개로 인해 사용자 개인정보가 침해될 가능성은 충분히 있다. 이를 위해 사용자 에이전트는 영속 데이터가 안전하게 저장되도록 보장하고, 데이터를 삭제할 때에는 기반 저장소에서 즉시 삭제되도록 보장하는 것이 좋다 SHOULD.

8.4 애플리케이션에 노출되는 값

애플리케이션에 노출되거나, 예를 들어 CDM의 사용을 통해 추론 가능한 값은 식별자로 설계되었는지 여부와 관계없이 클라이언트 또는 사용자를 식별하는 데 사용될 수 있다. 이 절은 그러한 우려를 피하거나 적어도 완화하기 위한 요구사항을 정의한다. 식별자에 대해서는 추가 요구사항이 있다.

8.4.1 출처별 프로필별 값 사용

애플리케이션에 노출되거나 추론 가능한 모든 구별 값출처브라우징 프로필마다 고유해야 MUST 한다. 즉, 이 명세에 정의된 API를 사용하는 한 출처에 대해 사용되는 값은 API를 사용하는 다른 어떤 출처에 대해 사용되는 값과도 달라야 MUST 하며, 한 브라우징 프로필에서 사용되는 값은 출처와 관계없이 다른 어떤 프로필에서 사용되는 값과도 달라야 MUST 한다. 그러한 값은 비공개 브라우징 세션으로 유출되거나 거기에서 유출되어서는 안 된다 MUST NOT.

출처와 프로필 간의 값은 애플리케이션에 의해 연관될 수 없어야 MUST 한다. 이는 같은 클라이언트 또는 사용자에서 왔음을 판단하는 등 여러 출처 또는 프로필의 값을 상관시킬 수 없어야 MUST NOT 함을 의미한다. 구체적으로, 출처별 값을 출처 독립적 및/또는 프로필 독립적 값에서 도출하는 구현은 적절한 비가역 속성을 가진 도출 함수를 사용하는 등, 위의 비연관성 속성을 보장하는 방식으로 그렇게 해야 MUST 한다.

8.4.2 값을 지울 수 있도록 허용

영속 데이터를 지울 수 있도록 허용의 요구사항의 결과로, 애플리케이션에 노출되는 모든 영속화된 값은 이 명세에 정의된 API와 같은 외부와 클라이언트 장치 양쪽에서 더 이상 가져오거나, 관찰하거나, 추론할 수 없도록 지울 수 있어야 MUST 한다.

일단 지워지면, 이후 값이 필요할 때 새 애플리케이션에 의해 연관될 수 없는 값이 생성되어야 MUST 한다.

8.5 식별자

구현에서 식별자, 특히 구별 식별자 또는 구별 영구 식별자를 사용하는 것은 개인정보 보호 문제를 제기한다. 이 절은 그러한 우려를 피하거나 적어도 완화하기 위한 요구사항을 정의한다. 애플리케이션에 노출되는 값에 대한 요구사항도 애플리케이션에 노출되는 식별자에 적용된다.

8.5.1 구별 식별자 및 영구 식별자의 사용 제한 또는 회피

  • 구현은 구별 식별자 또는 구별 영구 식별자의 사용을 피하는 것이 좋다 SHOULD.

    참고

    예를 들어, 개별 클라이언트가 아니라 클라이언트 또는 장치 그룹에 적용되는 식별자나 다른 값을 사용한다.

  • 구현은 특정 CDM 인스턴스 및 세션과 관련된 정책을 적용하는 데 필요한 경우에만 구별 식별자 또는 구별 영구 식별자를 사용하는 것이 좋다 SHOULD.

    참고

    예를 들어, "temporary" 및 "persistent-license" 세션은 서로 다른 요구사항을 가질 수 있다.

  • 구별 식별자 또는 구별 영구 식별자를 사용하는 구현은 이를 사용하지 않는 옵션을 지원하는 것이 좋다 SHOULD. 그러한 지원을 가진 구현은 사용자가 이 옵션을 선택할 수 있는 기능을 노출하는 것이 좋다 SHOULD.

    참고

    지원되는 경우, 애플리케이션은 distinctiveIdentifier = "not-allowed"를 사용하여 이 모드를 선택할 수 있다. 이러한 옵션을 선택하면 requestMediaKeySystemAccess() 호출의 결과 및/또는 이후 생성된 세션에서 생성되는 라이선스 요청에 영향을 줄 수 있다.

    사용자가 이 구현 기능을 선택하거나 고를 수 있게 하면, 사용자는 더 높은 수준의 개인정보 보호를 유지하면서 콘텐츠에 접근할 수 있을 수 있다.

8.5.2 식별자 암호화

고유 식별자고유 영구 식별자는 클라이언트 외부에 노출될 때 메시지 교환 수준에서 암호화되어야 MUST 한다. 다른 모든 식별자는 클라이언트 외부에 노출될 때 메시지 교환 수준에서 암호화되는 것이 SHOULD 된다. 암호화는 식별자 암호문의 임의의 두 인스턴스가 복호화 키를 소유한 엔터티에 의해서만 연관 가능하도록 보장해야 MUST 한다.

식별자는 다음과 같은 방식으로 노출될 수 있다.

  • message 이벤트를 통해 애플리케이션에 노출.

  • update()에 전달되는 것과 같은 서버의 메시지 안에서 노출.

  • 개별화의 일부로 노출.

CDM은 암호화 키가 해당 키 시스템의 유효한 서버에 속하는지 검증해야 MUST 한다. 애플리케이션에 노출되는 식별자의 경우, 이는 서버 인증서를 사용하여 구현될 MAY 있다.

서버는 고유 식별자를 이를 보낸 CDM 이외의 어떤 엔터티에도 노출해서는 MUST NOT 된다.

구체적으로, 이를 애플리케이션에 제공하거나 CDM에 보내는 메시지에 암호화되지 않은 상태로 포함해서는 안 된다. 이는 식별자 또는 식별자를 포함한 메시지를 암호화하여 특정 CDM만 복호화할 수 있도록 함으로써 달성할 수 있다.

8.5.3 출처별 프로필별 식별자 사용

구별 영구 식별자를 제외한 모든 식별자는 출처브라우징 프로필마다 고유해야 MUST 한다. 8.4.1 출처별 프로필별 값 사용을 참고한다.

8.5.4 연관될 수 없는 식별자 사용

구현이 애플리케이션에 노출하는 모든 식별자, 암호화된 형태의 식별자까지 포함하여 구별 식별자출처, 브라우징 프로필식별자 삭제 전후에 걸쳐 애플리케이션에 의해 연관될 수 없어야 MUST 한다.

8.5.5 식별자를 지울 수 있도록 허용

지속 데이터를 삭제할 수 있도록 허용의 요구사항의 결과로, 고유 영구 식별자를 제외한 모든 잠재적 식별자 또는 고유 식별성 값은 이 명세에 정의된 API를 통해서와 같은 외부와 클라이언트 장치 양쪽 모두에서 해당 값을 더 이상 검색, 관찰 또는 추론할 수 없도록 삭제 가능해야 MUST 한다.

고유 식별자를 사용하는 구현은 사용자가 고유 식별자를 삭제할 수 있도록 해야 MUST 한다. 고유 영구 식별자를 사용하는 구현은 사용자가 고유 영구 식별자와 연결된 값을 삭제할 수 있도록 해야 MUST 한다.

삭제된 후에는 이후에 고유 식별자와 같은 값이 필요할 때 새로운 애플리케이션에 의해 연관 불가능한 값을 생성해야 MUST 한다.

8.6 개별화

식별자, 특히 고유 식별자는 때때로 개별화 또는 프로비저닝이라고 하는 프로세스를 통해 생성되거나 얻어진다. 그 결과로 생성된 식별자는 애플리케이션에 의해 연관 불가능해야 MUST 하며, 그 사용단일 프로필의 단일 출처에만 노출되어야 MUST 한다. 이 프로세스는 식별자가 삭제된 뒤와 같이 여러 번 수행될 MAY 수 있다.

이 프로세스는 사용자 에이전트가 직접 또는 애플리케이션을 통해 수행되어야 MUST 한다. 두 유형의 개별화에 대한 메커니즘, 흐름 및 제한은 다음 절에 설명된 것처럼 서로 다르다. 어떤 방법이 사용되는지는 CDM 구현 및 이 명세의 요구사항, 특히 아래 요구사항의 적용에 따라 달라진다.

distinctiveIdentifier고유 식별자고유 영구 식별자가 개별화를 포함하여 사용될 수 있는지를 제어한다. 구체적으로, 그러한 식별자는 distinctiveIdentifier 멤버의 값이, MediaKeySystemAccess를 사용해 생성한 MediaKeys 객체에서 "required"일 때만 사용될 수 있다.

8.6.1 직접 개별화

직접 개별화는 CDM과 출처 및 애플리케이션에 독립적인 서버 사이에서 수행된다. 서버는 출처에 독립적이지만, 개별화의 결과를 통해 CDM은 이 명세의 다른 요구사항에 따라 출처별 식별자를 제공할 수 있다. 이 프로세스는 사용자 에이전트가 수행해야 MUST 하며, 이 명세에 정의된 API를 사용해서는 MUST NOT 된다.

예를 들어, 그러한 프로세스는 사용자 에이전트 또는 CDM 공급업체가 호스팅하는 미리 정해진 서버와 통신하여 클라이언트 장치를 초기화하거나 및/또는 단일 브라우징 프로필에 대해 출처별 삭제 가능한 식별자를 얻을 수 있으며, 이때 클라이언트 장치의 고유 영구 식별자 사용 또는 기타 영구 식별자를 사용할 수도 있다.

그러한 개별화의 경우, 모든 메시지 교환은:

  • 사용자 에이전트가 처리하고 사용자 에이전트의 네트워크 스택을 통해 사용자 에이전트가 수행해야 MUST 한다.

  • CDM이 직접 수행해서는 MUST NOT 된다.

  • 이 명세에 정의된 API를 통해 애플리케이션으로 전달되거나 애플리케이션을 거쳐 전달되어서는 MUST NOT 된다.

  • 어떤 출처와 애플리케이션에도 독립적으로 선택된 URL로 전송되어야 MUST 한다.

  • 모든 고유 식별자고유 영구 식별자를 암호화해야 MUST 한다.

  • TLS를 사용해야 MUST 한다.

구현은 암호화된 형태로라도 출처, 출처 또는 애플리케이션별 정보, 또는 출처와 연관 가능한 값을 중앙 서버에 노출해서는 MUST NOT 된다. 이는 사용자 또는 장치가 방문한 모든 출처의 중앙 기록을 생성할 수 있기 때문이다.

8.6.2 앱 지원 개별화

애플리케이션 보조 개별화는 CDM과 애플리케이션, 애플리케이션이 선택한 서버를 포함한 대상 사이에서 수행되며, 출처별 식별자를 생성한다. 이 프로세스는 이 명세에 정의된 API를 통해 수행되어야 MUST 하며, 다른 통신 방법을 포함해서는 MUST NOT 된다. API의 다른 모든 사용과 마찬가지로, 이 프로세스는 하나 이상의 고유 식별자를 사용할 MAY 수 있지만, 암호화된 형태로라도 고유 영구 식별자를 사용하거나 출처별이 아닌 값을 사용해서는 MUST NOT 된다. 이 프로세스가 하나 이상의 고유 식별자를 사용하는 경우, 결과 식별자도 정의상 고유 식별자이다.

그러한 개별화의 경우, 모든 메시지 교환은:

  • 이 명세에 정의된 API를 통해 애플리케이션으로 전달되거나 애플리케이션을 거쳐 전달되어야 MUST 한다.

  • 관련된 모든 message 이벤트에 대해 메시지 유형 "individualization-request"를 사용해야 SHALL 한다.

  • 사용자 에이전트가 수행해서는 MUST NOT 된다.

  • CDM이 직접 수행해서는 MUST NOT 된다.

  • 고유 영구 식별자를 사용하거나 포함해서는 MUST NOT 된다.

  • 출처별이 아닌 클라이언트별 정보를 포함해서는 MUST NOT 된다.

  • 식별자 요구사항을 준수해야 MUST 한다.

    여기에는 출처 및 프로필별로 고유하고 삭제 가능한 값만 사용하며, 요구되는 대로 이를 암호화하는 것이 포함된다.

  • CDM에 실행 가능한 코드를 제공해서는 MUST NOT 된다.

고유 식별자를 포함한 연관 가능한 값이 이 프로세스에서 사용되는 경우, 구현은 암호화된 형태로라도 출처, 출처 또는 애플리케이션별 정보, 또는 출처와 연관 가능한 값을 중앙 서버에 노출해서는 MUST NOT 된다. 이는 사용자 또는 장치가 방문한 모든 출처의 중앙 기록을 생성할 수 있기 때문이다.

적절한 예방 조치를 취하면, 그러한 개별화는 직접 개별화보다 더 나은 개인정보 보호를 제공할 수 있지만, 고유 식별자를 사용하지 않는 모델만큼 좋지는 않다. 그러한 설계의 이점을 보존하고 다른 개인정보 보호 우려를 도입하지 않기 위해, 그러한 구현 및 이를 지원하는 애플리케이션은 개별화 메시지를 중앙 서버 또는 애플리케이션 작성자가 제어하지 않는 다른 서버로 연기하거나 전달하는 것을 피하는 것이 SHOULD 된다.

8.7 여러 키 지원

구현은 각 MediaKeySession 객체 안에서 여러 키를 지원해야 MUST 한다.

참고

여러 키가 지원되는 방식의 메커니즘은 구현 세부사항이지만, 애플리케이션과 이 명세에 정의된 API에는 투명해야 MUST 한다.

구현은 재생 중 키 간의 끊김 없는 전환을 지원해야 MUST 한다. 여기에는 같은 MediaKeySession 안의 키와 별도의 MediaKeySession 객체 안의 키 모두가 포함된다.

8.8 초기화 데이터 타입 지원

8.8.1 생성된 라이선스는 콘텐츠 타입과 독립적임

구현은 지원하는 어떤 초기화 데이터 타입으로 생성된 라이선스든 어떤 콘텐츠 타입과도 함께 사용할 수 있도록 허용하는 것이 좋다 SHOULD.

참고

그렇지 않으면, 예를 들어 requestMediaKeySystemAccess() 알고리즘은 MediaKeySystemConfiguration을 거부할 수 있다. 그 이유는 initDataTypes 중 하나가 videoCapabilities 중 하나와 함께 지원되지 않기 때문일 수 있다.

8.8.2 미디어 데이터에서 추출 지원

지원되는 컨테이너에 나타날 수 있는 지원되는 초기화 데이터 타입에 대해, 사용자 에이전트는 그러한 각 지원 컨테이너에서 그 타입의 초기화 데이터추출하는 것을 지원해야 MUST 한다.

참고

다시 말해, 초기화 데이터 타입 지원을 나타내는 것은 라이선스 요청 생성을 위한 CDM 지원과, 컨테이너별 타입의 경우 이를 컨테이너에서 추출하기 위한 사용자 에이전트 지원을 모두 의미한다. 이는 구현이 임의의 지원되는 초기화 데이터임의의 지원되는 콘텐츠 타입에서 파싱할 수 있어야 함을 의미하지는 않는다.

8.9 지원되는 미디어

이 절은 이 명세의 구현에서 지원되는 콘텐츠(미디어 리소스)의 속성을 정의한다.

8.9.1 암호화되지 않은 컨테이너

미디어 컨테이너는 암호화되어서는 안 된다 MUST NOT. 이 명세는 사용자 에이전트가 미디어 데이터의 어느 것도 복호화하지 않고 미디어 컨테이너를 파싱할 수 있는 능력에 의존한다. 여기에는 암호화된 블록 발견초기화 데이터 발견 알고리즘뿐 아니라 HTMLMediaElement [HTML]의 표준 기능, 예를 들어 탐색 지원도 포함된다.

8.9.2 상호운용 가능하게 암호화됨

모든 트랙을 포함한 미디어 리소스는 컨테이너별 "common encryption" 명세에 따라 암호화되고 패키징되어야 MUST 하며, 해당 명세는 하나 이상의 키가 제공될 때 콘텐츠가 완전히 명시되고 호환 가능한 방식으로 복호화될 수 있도록 해야 한다.

암호화된 미디어 확장 스트림 형식 레지스트리는 그러한 스트림 형식에 대한 참조를 제공한다.

8.9.3 암호화되지 않은 인밴드 지원 콘텐츠

캡션, 해설 오디오, 대본과 같은 인밴드 지원 콘텐츠는 암호화하지 않는 것이 좋다 SHOULD NOT.

참고

그러한 트랙의 복호화, 특히 이를 사용자 에이전트에 다시 제공할 수 있게 하는 복호화는 일반적으로 구현에서 지원되지 않는다. 따라서 그러한 트랙을 암호화하면 사용자 에이전트 구현의 접근성 기능에서 널리 사용할 수 없게 된다.

접근성 정보가 사용 가능한 형태로 제공되도록 보장하기 위해, 암호화된 인밴드 지원 콘텐츠를 지원하기로 선택한 구현의 경우: a) CDM은 복호화된 데이터를 사용자 에이전트에 제공해야 MUST 하고, b) 사용자 에이전트는 이를 예를 들어 timed text tracks [HTML]로 노출하기 위해, 동등한 암호화되지 않은 지원 콘텐츠와 같은 방식으로 처리해야 MUST 한다.

9. 공통 키 시스템

모든 사용자 에이전트는 이 절에서 설명하는 공통 키 시스템을 지원해야 MUST 한다.

참고

이는 완전히 오픈 소스인 사용자 에이전트를 포함하여 모든 사용자 에이전트에서 지원이 보장되는 공통 기준 수준의 기능이 존재하도록 보장한다. 따라서 기본 복호화만 필요한 콘텐츠 제공자는 어떤 콘텐츠 보호 제공자와도 협력할 필요 없이 모든 플랫폼에서 동작하는 단순한 애플리케이션을 만들 수 있다.

9.1 Clear Key

"org.w3.clearkey" 키 시스템은 소스를 복호화하기 위해 평문 clear(암호화되지 않은) 키를 사용한다. 추가적인 클라이언트 측 콘텐츠 보호는 요구되지 않는다. 이 키 시스템은 아래에 설명되어 있다.

9.1.1 기능

다음은 Clear Key키 시스템별 기능을 지원하는 방식을 설명한다:

9.1.2 동작

다음은 Clear Key키 시스템별 동작을 구현하는 방식을 설명한다:

  • generateRequest() 알고리즘에서:

    • 생성된 message라이선스 요청 형식에 설명된 대로 UTF-8로 인코딩된 JSON 객체이다.

    • 요청은 sanitized init data에서 키 ID를 추출하여 생성된다.

    • "type" 멤버 값은 sessionType 매개변수의 값이다.

  • sessionId 속성은 32비트 정수로 표현 가능한 수치 값이다.

  • expiration 속성은 항상 NaN이다.

  • update() 알고리즘에서:

    • response 매개변수는 라이선스 형식에 설명된 JWK Set이거나, 라이선스 릴리스 확인 형식에 설명된 UTF-8로 인코딩된 JSON 객체이다.

    • 첫 번째 경우, sanitized response는 오디오/비디오 타입에 대해 유효한 길이의 유효한 JWK 키를 하나 이상 가진 유효한 JWK Set이 아니면 유효하지 않은 것으로 간주된다. 두 번째 경우 sanitized response는 유효한 JSON 객체가 아니면 유효하지 않은 것으로 간주된다.

  • "persistent-license" 타입의 세션의 경우, remove() 알고리즘에서, record of license destruction을 반영하는 message라이선스 릴리스 형식에 설명된 대로 UTF-8로 인코딩된 JSON 객체이다.

  • keyStatuses 속성 메서드는 처음에는 update()를 통해 제공된 모든 키 ID를 포함하며, 상태는 "usable"이다. remove() 알고리즘이 실행되면, keyStatuses 속성은 빈 목록으로 설정된다.

  • 초기화 데이터: 구현은 등록된 초기화 데이터 타입 [EME-INITDATA-REGISTRY]의 어떤 조합이든 지원할 수 있다 MAY. 구현은 "keyids" 타입 [EME-INITDATA-KEYIDS]과 사용자 에이전트가 지원하는 콘텐츠 타입에 적합한 다른 타입을 지원하는 것이 좋다 SHOULD.

9.1.3 라이선스 요청 형식

이 절은 message 이벤트의 message 속성을 통해 애플리케이션에 제공되는 라이선스 요청의 형식을 설명한다.

이 형식은 다음 멤버를 포함하는 JSON 객체이다:

"kids"
키 ID의 배열. 배열의 각 요소는 키 ID 값을 포함하는 옥텟 시퀀스의 base64url 인코딩이다.
"type"
요청된 MediaKeySessionType.

MediaKeyMessageEvent 객체의 ArrayBuffer message 속성에 포함될 때, JSON 문자열은 Encoding 명세 [ENCODING]에 명시된 대로 UTF-8로 인코딩된다. 애플리케이션은 TextDecoder 인터페이스 [ENCODING]를 사용하여 ArrayBuffer의 내용을 JSON 문자열로 디코딩할 수 있다 MAY.

9.1.3.1 예제

이 절은 비규범적이다.

다음 예제는 두 개의 키 ID에 대한 임시 라이선스의 라이선스 요청이다. (줄바꿈은 읽기 쉽도록 하기 위한 것일 뿐이다.)

{
  "kids": [
    "LwVHf8JLtPrv2GUXFW2v_A",
    "0DdtU9od-Bh5L3xbv0Xf_A"
  ],
  "type": "temporary"
}

9.1.4 라이선스 형식

이 절은 update() 메서드의 response 매개변수를 통해 제공될 라이선스의 형식을 설명한다.

이 형식은 JSON Web Key (JWK) 명세 [RFC7517]에 정의된 대로 복호화에 사용할 대칭 키의 표현을 포함하는 JSON Web Key (JWK) Set이다.

집합의 각 JWK에 대해, 매개변수 값은 다음과 같다:

"kty" (key type)
"oct" (옥텟 시퀀스).
"k" (key value)
대칭 값을 포함하는 옥텟 시퀀스의 base64url 인코딩.
"kid" (key ID)
키 ID 값을 포함하는 옥텟 시퀀스의 base64url 인코딩.

JSON 객체는 선택적인 "type" 멤버 값을 가질 수 있으며 MAY, 이는 MediaKeySessionType 값 중 하나여야 MUST 한다. 지정되지 않으면 기본값 "temporary"가 사용된다. update() 알고리즘은 이 값을 sessionType과 비교한다.

update() 메서드에 ArrayBuffer response 매개변수로 전달될 때, JSON 문자열은 Encoding 명세 [ENCODING]에 명시된 대로 UTF-8로 인코딩되어야 MUST 한다. 애플리케이션은 TextEncoder 인터페이스 [ENCODING]를 사용하여 JSON 문자열을 인코딩할 수 있다 MAY.

9.1.4.1 예제

이 절은 비규범적이다.

다음 예제는 하나의 대칭 키를 포함하는 JWK Set이다. (줄바꿈은 읽기 쉽도록 하기 위한 것일 뿐이다.)

{
  "keys": [{
    "kty": "oct",
    "k": "tQ0bJVWb6b0KPL6KtZIy_A",
    "kid": "LwVHf8JLtPrv2GUXFW2v_A"
  }],
  "type": "temporary"
}

9.1.5 라이선스 릴리스 형식

이 절은 message 이벤트의 message 속성을 통해 제공될 라이선스 릴리스 메시지의 형식을 설명한다.

이 형식은 JSON 객체이다. "persistent-license" 타입의 세션에 대해, 객체는 다음 멤버를 포함해야 한다:

"kids"
키 ID의 배열. 배열의 각 요소는 키 ID 값을 포함하는 옥텟 시퀀스의 base64url 인코딩이다.

MediaKeyMessageEvent 객체의 ArrayBuffer message 속성에 포함될 때, JSON 문자열은 Encoding 명세 [ENCODING]에 명시된 대로 UTF-8로 인코딩된다. 애플리케이션은 TextDecoder 인터페이스 [ENCODING]를 사용하여 ArrayBuffer의 내용을 JSON 문자열로 디코딩할 수 있다 MAY.

9.1.5.1 라이선스 파기 기록을 반영하는 예제 메시지

이 절은 비규범적이다.

다음 예제는 두 개의 키를 포함했던 "persistent-license" 세션의 라이선스 릴리스이다. (줄바꿈은 읽기 쉽도록 하기 위한 것일 뿐이다.)

{
  "kids": [ "LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A" ]
}

9.1.6 라이선스 릴리스 확인 형식

이 절은 update() 메서드의 response 매개변수를 통해 제공되는 라이선스 릴리스 확인의 형식을 설명한다.

이 형식은 다음 멤버를 포함하는 JSON 객체이다:

"kids"
키 ID의 배열. 배열의 각 요소는 키 ID 값을 포함하는 옥텟 시퀀스의 base64url 인코딩이다.

update() 메서드에 ArrayBuffer response 매개변수로 전달될 때, JSON 문자열은 Encoding 명세 [ENCODING]에 명시된 대로 UTF-8로 인코딩되어야 MUST 한다. 애플리케이션은 TextEncoder 인터페이스 [ENCODING]를 사용하여 JSON 문자열을 인코딩할 수 있다 MAY.

9.1.6.1 예제

이 절은 비규범적이다.

다음 예제는 두 개의 키 ID에 대한 임시 라이선스의 라이선스 요청이다. (줄바꿈은 읽기 쉽도록 하기 위한 것일 뿐이다.)

{
  "kids": [
    "LwVHf8JLtPrv2GUXFW2v_A",
    "0DdtU9od-Bh5L3xbv0Xf_A"
  ]
}

9.1.7 base64url 사용

이 절은 비규범적이다.

base64url 및 그 사용에 대한 자세한 내용은 [RFC7515]의 "Base64url Encoding" 용어 정의와 "Notes on implementing base64url encoding without padding"을 참고한다. 구체적으로 '=' 패딩은 없으며, 문자 '-'와 '_'가 각각 '+'와 '/' 대신 사용되어야 MUST 한다.

10. 보안

10.1 입력 데이터 공격 및 취약점

사용자 에이전트 및 키 시스템 구현은 MUST 미디어 데이터, 초기화 데이터, update()에 전달되는 데이터, 라이선스, 키 데이터, 그리고 애플리케이션이 제공하는 기타 모든 데이터를 신뢰할 수 없는 콘텐츠 및 잠재적 공격 벡터로 간주해야 한다. 이들은 관련 위협을 완화하기 위해 적절한 보호 조치를 사용해야 MUST 하며, 그러한 데이터를 안전하게 파싱하고 복호화하는 등의 주의를 기울여야 한다. 사용자 에이전트는 데이터를 CDM에 전달하기 전에 검증하는 것이 좋다 SHOULD.

참고

그러한 검증은 CDM이 예를 들어 DOM과 같은 (샌드박스화된) 컨텍스트에서 실행되지 않는 경우 특히 중요하다.

구현은 프로그램 제어 흐름에 영향을 주는 능동 콘텐츠 또는 수동 콘텐츠를 애플리케이션에 반환해서는 안 된다 MUST NOT.

참고

예를 들어, generateRequest()에 전달되는 초기화 데이터의 경우처럼, 미디어 데이터에서 온 것일 수 있는 URL이나 기타 정보를 노출하는 것은 안전하지 않다. 애플리케이션은 사용할 URL을 결정해야 한다. messageType 속성은 해당되는 경우 애플리케이션이 URL 집합 중에서 선택하는 데 사용할 수 있다. message 이벤트의 속성이다.

10.2 CDM 공격 및 취약점

사용자 에이전트는 사용자에게 웹을 안전하게 탐색할 수 있는 방법을 제공할 책임이 있다. 이 책임은 제3자의 기능을 포함하여 사용자 에이전트가 사용하는 모든 기능에 적용된다. 사용자 에이전트 구현자는 키 시스템 구현자로부터 충분한 정보를 얻어 키 시스템과의 통합이 갖는 보안 영향을 적절히 평가할 수 있도록 해야 MUST 한다. 사용자 에이전트 구현자는 CDM 구현이 사용자 에이전트가 사용자에게 보안을 제공하는 데 충분한 제어를 제공하거나 및/또는 지원하도록 보장해야 MUST 한다. 사용자 에이전트 구현자는 CDM 구현이 보안 취약점이 발생한 경우 신속하고 사전 예방적으로 업데이트될 수 있고 그렇게 되도록 보장해야 MUST 한다.

완전히 샌드박스화되지 않았거나 및/또는 플랫폼 기능을 사용하는 CDM 구현을 악용하면, 공격자가 OS 또는 플랫폼 기능에 접근하거나 권한을 상승시키거나(예: system 또는 root로 실행), 드라이버, 커널, 펌웨어, 하드웨어 등에 접근할 수 있다. 그러한 기능, 소프트웨어, 하드웨어는 적대적 소프트웨어나 웹 기반 공격에 견고하도록 작성되지 않았을 수 있으며, 특히 사용자 에이전트와 비교할 때 보안 수정으로 업데이트되지 않을 수 있다. CDM 구현의 보안 취약점 수정 업데이트가 없거나, 드물거나, 느리면 위험이 증가한다. 그러한 CDM 구현과 이를 노출하는 UA는 모든 데이터의 구문 분석을 포함하여 보안의 모든 영역에서 특히 주의해야 MUST 한다.

사용자 에이전트는 클라이언트 OS, 플랫폼 및/또는 하드웨어의 일부이거나 그것들이 제공하는 CDM 또는 기반 메커니즘을 사용할 때 특히 주의를 기울여야 한다.

사용자 에이전트가 충분히 샌드박스화하거나 다른 방식으로 보안할 수 없는 키 시스템 구현을 지원하기로 선택한 경우, 사용자 에이전트는 이를 로드하거나 호출하기 전에 사용자가 충분히 정보를 제공받고 및/또는 명시적으로 동의하도록 보장하는 것이 SHOULD 된다.

인증되지 않은 출처에 권한을 부여하는 것은 네트워크 공격자가 있는 상황에서 임의의 출처에 권한을 부여하는 것과 같다. 지속된 동의의 남용을 보라.

10.3 네트워크 공격

10.3.1 잠재적 공격

이 절은 비규범적이다.

잠재적 네트워크 공격과 그 영향은 다음을 포함한다:

  • DNS 스푸핑 공격: 특정 도메인(출처)에 속한다고 주장하는 호스트가 실제로 그 도메인에서 왔다고 보장할 수 없다.

  • 수동 네트워크 공격: 클라이언트와 서버 사이에서 전송되는 데이터, 예를 들어 구별 식별자구별 영구 식별자를 포함한 데이터가 다른 엔터티에 의해 보이지 않는다고 보장할 수 없다. 사용자 추적을 참고한다.

  • 능동 네트워크 공격: 추가 스크립트나 iframe이 페이지에 삽입되지 않는다고 보장할 수 없다(이 명세에 정의된 API를 정당한 목적으로 사용하는 페이지와 그렇지 않은 페이지 모두). 그 결과는 다음과 같다:

    • 이 명세에 정의된 API 호출이 임의의 페이지에 삽입될 수 있다.

    • 정당한 이유로 이 API를 사용하는 페이지에서 이 명세에 정의된 API 호출이, 요청된 기능을 수정하거나, 호출을 수정 또는 추가하거나, 데이터를 수정 또는 삽입하는 것을 포함하여 조작될 수 있다. 입력 데이터 공격 및 취약점도 참고한다

    • 클라이언트와 서버 사이에서 전송되는 데이터, 예를 들어 구별 식별자구별 영구 식별자를 포함한 데이터가 다른 엔터티에 의해 보이거나 수정될 수 있다. 사용자 추적을 참고한다.

  • 영속 동의의 남용: 이 명세에 정의된 API 사용을 요청하는 호스트가 사용자가 이전에 동의한 호스트라고 보장할 수 없다. 그 결과 인증되지 않은 출처에 권한을 부여하는 것은 네트워크 공격자가 있는 상황에서 모든 출처에 권한을 부여하는 것과 같다.

10.3.2 완화책

다음 기법은 위험을 완화할 수 있다:

TLS 사용

TLS를 사용하는 애플리케이션은 사용자, 사용자를 대신해 동작하는 소프트웨어, 그리고 같은 도메인에서 왔음을 식별하는 인증서를 가진 TLS 사용 다른 페이지만이 해당 애플리케이션과 상호작용할 수 있음을 확신할 수 있다. 더 나아가, 보안 출처와 결합된 출처별 권한은 애플리케이션에 부여된 권한이 네트워크 공격자에 의해 남용될 수 없도록 보장한다.

이 명세에 정의된 API는 보안 컨텍스트에서만 노출된다. 보안 출처 및 전송도 참고한다.

혼합 콘텐츠 차단

사용자 에이전트는 안전하지 않은 콘텐츠에 노출될 가능성을 피하기 위해 "차단 가능 콘텐츠" [MIXED-CONTENT]를 차단하는 것을 포함하여, 혼합 콘텐츠 [MIXED-CONTENT]를 적절히 처리해야 MUST 한다. 그러한 노출은 TLS 사용과 같은 다른 완화책을 손상시킬 수 있다.

사용자 에이전트는 신뢰할 수 없는 미디어 데이터CDM에 전달되는 것을 방지하여 보안을 더 강화하기 위해 "선택적으로 차단 가능한 콘텐츠" [MIXED-CONTENT]를 포함한 모든 혼합 콘텐츠를 차단하도록 선택할 수 있다 MAY (CDM 공격 및 취약점 참고).

사용자 에이전트는 다른 사용자 에이전트 기능(예: DOM 콘텐츠)보다 더 큰 보안 우려를 제시하는 키 시스템출처에 의해 접근될 수 있기 전에, 사용자가 충분히 알도록 하고/하거나 명시적 동의를 제공하도록 보장하는 것이 좋다 SHOULD.

그러한 메커니즘은 유효한 사용이 이후의 악성 접근을 가능하게 하지 않도록 출처별이어야 MUST 하며, 브라우징 프로필별이어야 MUST 한다.

참고

이 명세에 정의된 API가 보안 컨텍스트로 제한되므로 네트워크 공격자는 인증되지 않은 출처에 부여된 권한을 악용할 수 없다. 영속 동의의 남용을 참고한다.

10.4 iframe 공격

10.4.1 잠재적 공격

이 절은 비규범적이다.

악성 페이지는 공격을 숨기거나, 사용이 정당한 콘텐츠 제공자로부터 온 것처럼 보이게 하는 등 사용자에게 출처를 속이려는 시도로, 정당한 애플리케이션을 iframe 안에 호스팅할 수 있다. 이는 보안 및/또는 개인정보 보호 이유사용자에게 알리거나 동의를 요구하는 구현에 특히 관련된다. 네트워크 공격에 더해, 공격자는 이 명세에 정의된 API의 정당한 사용을 iframe 안에 호스팅함으로써 악용하려고 시도할 수 있다. 정당한 애플리케이션이 작업을 수행하게 함으로써, 공격자는 기존에 부여된 권한(또는 허용 목록)을 재사용하고/하거나 정당한 요청 또는 사용처럼 보일 수 있다.

10.4.2 완화책

보안 및/또는 개인정보 보호 이유를 포함하여 사용자에게 알리거나 동의를 요구하는 사용자 에이전트는, 동의의 UI와 영속성을 최상위 Document출처와 이 명세에 정의된 API를 사용하는 출처의 조합에 기반하게 하는 것이 좋다 SHOULD. 이는 사용자가 요청을 하는 주 문서를 알 수 있도록 하고, 하나의 (정당한) 조합에 대한 권한 영속화가 악성 사용을 부주의하게 탐지되지 않도록 허용하지 않도록 보장한다.

작성자는 다른 엔터티가 자신의 애플리케이션을 iframe 안에 호스팅하지 못하도록 방지하는 것이 좋다 SHOULD. 정당한 애플리케이션 설계 이유로 호스팅 지원이 필요한 애플리케이션은, 호스팅 문서가 이 명세에 정의된 API를 통해서든 미디어 데이터로서든 CDM에 전달될 어떠한 데이터도 제공하지 못하게 하는 것이 좋으며 SHOULD NOT, 호스팅 프레임이 이 명세에 정의된 API를 호출하지 못하게 하는 것이 좋다 SHOULD NOT.

10.5 교차 디렉터리 공격

이 절은 비규범적이다.

예를 들어 geocities.com에서 콘텐츠를 호스팅하는 사용자처럼 하나의 호스트 이름을 공유하는 서로 다른 작성자는 모두 하나의 출처를 공유한다. 사용자 에이전트는 경로명으로 API 접근을 제한하는 기능을 제공하지 않는다.

공유 호스트에서 이 명세에 정의된 API를 사용하면 사용자 에이전트가 구현한 출처 기반 보안 및 개인정보 보호 완화책이 손상된다. 예를 들어, 출처별 구별 식별자는 하나의 호스트 이름에 있는 모든 작성자가 공유하며, 영속 데이터는 그 호스트의 어떤 작성자에 의해서든 접근되고 조작될 수 있다. 후자는 예를 들어 그러한 데이터의 수정 또는 삭제가 특정 콘텐츠에 대한 사용자의 권리를 지울 수 있는 경우 특히 중요하다.

참고

경로 제한 기능이 사용자 에이전트에 의해 제공되더라도, 일반적인 DOM 스크립팅 보안 모델은 이 보호를 우회하고 임의의 경로에서 데이터에 접근하는 것을 사소하게 만들 것이다.

따라서 공유 호스트의 작성자는 이 명세에 정의된 API 사용을 피하는 것이 권장된다 RECOMMENDED. 그렇게 하면 사용자 에이전트의 출처 기반 보안 및 개인정보 보호 완화책이 손상되기 때문이다.

11. 개인정보 보호

사용자의 기기에 키 시스템이 존재하거나 사용되는 것은 여러 개인정보 보호 문제를 일으키며, 이는 두 범주로 나뉜다: (a) EME 인터페이스 자체 또는 키 시스템 메시지 안에서 공개될 수 있는 사용자별 정보, 그리고 (b) 사용자의 기기에 영속적으로 저장될 수 있는 사용자별 정보.

사용자 에이전트는 사용자가 자신의 개인정보 보호를 적절히 제어할 수 있도록 제공할 책임을 져야 MUST 한다. 사용자 에이전트는 서드파티 CDM 구현과 통합될 수 있으므로, CDM 구현자는 아래에 설명된 기법을 포함하되 이에 국한되지 않는 적절한 기법을 사용자 에이전트 구현자가 구현하여 사용자가 개인정보 보호를 제어할 수 있도록, 충분한 정보와 제어를 제공해야 MUST 한다.

11.1 EME 및 키 시스템에 의해 공개되는 정보

EME 및 키 시스템에 의해 공개되는 정보에 관한 우려는 두 범주로 나뉜다: (a) 특정적이지는 않지만 사용자 에이전트 또는 기기의 핑거프린팅 가능성에 기여할 수 있는 정보에 대한 우려, 그리고 (b) 사용자 추적에 직접 사용될 수 있는 사용자별 정보.

11.2 핑거프린팅

악성 애플리케이션은 지원되는 키 시스템 목록과 관련 정보를 감지하거나 열거함으로써 사용자나 사용자 에이전트를 핑거프린팅할 수 있을 수 있다. 적절한 출처 보호가 제공되지 않으면, 여기에는 방문한 사이트와 해당 사이트에 저장된 정보의 감지가 포함될 수 있다. 특히 키 시스템출처 간에 키 또는 기타 데이터를 공유해서는 안 된다 MUST.

이 명세의 여러 기능은 핑거프린팅에 약간 기여할 수 있는 기능 정보를 노출한다:

11.3 정보 유출

11.3.1 우려사항

이 절은 비규범적이다.

CDM, 특히 사용자 에이전트 밖에서 구현된 CDM은 웹 플랫폼과 같은 기본 격리를 갖지 않을 수 있다. 정보 유출, 특히 출처 간 정보 유출을 피하기 위한 조치를 취하는 것이 중요하다. 여기에는 메모리 내 데이터와 저장된 데이터가 모두 포함된다. 이를 수행하지 않으면 비공개 브라우징 세션으로부터/세션으로, 브라우징 프로필 간(운영 체제 사용자 계정 간 포함), 심지어 서로 다른 브라우저나 애플리케이션 간에도 정보 유출이 발생할 수 있다.

11.3.2 완화책

그러한 문제를 피하기 위해, 사용자 에이전트와 CDM 구현은 다음을 보장해야 MUST 한다.

  • CDMCDM 인스턴스라는 개념을 가지며, 이는 MediaKeys 객체와 일대일로 연결된다.

  • 키, 라이선스, 기타 세션 데이터 및 세션의 존재는 그 세션을 생성한 MediaKeys 객체와 연결된 CDM 인스턴스로 제한된다.

  • 세션 데이터는 MediaKeys 객체 또는 CDM 인스턴스 간에 공유되지 않는다.

  • 세션 데이터는 그 세션을 생성한 MediaKeys 객체와 연결되지 않은 미디어 요소와 공유되지 않는다. 무엇보다도 이는 세션의 키가 mediaKeys 속성이 그 MediaKeys 객체가 아닌 미디어 요소가 로드한 콘텐츠를 복호화하는 데 사용되어서는 MUST 안 됨을 의미한다.

  • MediaKeys 객체와 그 기반 구현은 출처 밖으로 정보를 노출하지 않는다.

  • 해당되는 경우, 지속된 세션 데이터는 출처별로 저장된다.

  • 요청하는 출처가 저장한 데이터만 로드될 수 있다.

  • 이 명세에 명시적으로 설명되어 있거나 사용자 권한 없이 다른 웹 플랫폼 API를 통해 페이지에서 사용할 수 있는 정보가 아닌 정보는 CDM에서 추출, 파생 또는 추론할 수 없어야 한다. 이는 예를 들어 CDM 메시지 안에서처럼, 클라이언트 장치 외부 또는 애플리케이션에 노출되는 모든 정보에 적용된다.

    이 요구사항이 다루는 정보의 유형에는 다음이 포함되지만 이에 한정되지 않는다.

    • 지리 위치를 포함한 위치

    • 고유 식별자 이외의 자격 증명 또는 식별자

    • OS 계정 이름 및 기타 잠재적 PII

    • 유사한 정보를 포함할 수 있는 로컬 디렉터리 경로.

    • 로컬 네트워크 세부정보(예: 장치의 로컬 IP 주소)

    • Bluetooth, USB 및 사용자 미디어를 포함하되 이에 한정되지 않는 로컬 장치.

    • 이 명세에 정의된 API와 관련되어 있지 않거나 그 결과로 저장되지 않은 사용자 상태.

11.4 사용자 추적

11.4.1 우려사항

이 절은 비규범적이다.

제3자 호스트(또는 광고주처럼 콘텐츠를 여러 사이트에 배포할 수 있는 어떤 엔터티)는 고유 식별자 또는 라이선스, 키, 키 ID, 또는 라이선스 폐기 기록을 포함하여 CDM이 저장하거나 이를 대신해 저장된 지속 데이터를 사용하여 여러 세션에 걸쳐 사용자를 추적할 수 있다(출처브라우징 프로필 전반을 포함함). 이를 통해 사용자의 활동이나 관심사에 대한 프로필을 만들 수 있다. 그러한 추적은 웹 플랫폼의 나머지 부분이 제공하는 개인정보 보호를 약화시키며, 예를 들어 다른 방식으로는 불가능한 고도로 표적화된 광고를 가능하게 할 수 있다. 사용자의 실제 신원을 알고 있는 사이트(예를 들어 인증된 자격 증명을 요구하는 콘텐츠 제공자 또는 전자상거래 사이트)와 결합하면, 순수하게 익명적인 웹 사용만 있는 세계보다 억압적인 집단이 개인을 더 높은 정확도로 표적으로 삼을 수 있다.

이 명세의 API 구현을 통해 얻을 수 있는 사용자 또는 클라이언트별 정보에는 다음이 포함된다.

이 명세는 그러한 정보가 일반적으로 사용자 에이전트(및 관련 브라우징 프로필 저장소) 외부에, 흔히 CDM에 저장되기 때문에 특별한 우려를 제기한다.

라이선스와 라이선스 폐기 기록의 내용은 키 시스템별이며, 키 ID는 어떤 값이든 포함할 수 있으므로, 이러한 데이터 항목은 사용자를 식별하는 정보를 저장하는 데 악용될 수 있다.

키 시스템은 장치 또는 장치 사용자를 위한 지속 또는 반지속 식별자에 접근하거나 이를 생성할 수 있다. 어떤 경우에는 이러한 식별자가 특정 장치에 안전한 방식으로 바인딩될 수 있다. 이러한 식별자가 키 시스템 메시지에 존재하면, 장치 및/또는 사용자가 추적될 수 있다. 아래 완화 조치가 적용되지 않으면, 여기에는 시간에 따른 사용자/장치 추적과 주어진 장치의 여러 사용자를 연관시키는 것이 모두 포함될 수 있다.

그러한 식별자, 특히 삭제 불가능하거나 출처별이 아니거나 영구적인 식별자는 쿠키 [COOKIES] 또는 URL에 삽입된 세션 식별자 같은 기존 기법보다 추적 영향이 크다는 점에 유의하는 것이 중요하다.

완화되지 않으면, 그러한 추적은 키 시스템의 설계에 따라 세 가지 형태를 취할 수 있다.

  • 모든 경우에, 그러한 식별자는 키 시스템을 완전히 지원하는 사이트 및/또는 서버에서 사용할 수 있을 것으로 예상된다(따라서 키 시스템 메시지를 해석할 수 있음). 이로 인해 그러한 사이트에 의한 추적이 가능해진다.

  • 키 시스템이 노출하는 식별자가 출처별이 아니면, 키 시스템을 완전히 지원하는 두 사이트 및/또는 서버가 공모하여 사용자를 추적할 수 있다.

  • 키 시스템 메시지가 사용자 식별자에서 일관된 방식으로 파생된 정보를 포함하는 경우, 예를 들어 특정 콘텐츠 항목에 대한 초기 키 시스템 메시지의 일부가 시간이 지나도 변하지 않고 사용자 식별자에 의존하는 경우, 이 정보는 어떤 애플리케이션에 의해서도 장치 또는 사용자를 시간에 따라 추적하는 데 사용될 수 있다.

또한 키 시스템이 키 또는 다른 데이터를 저장하고 출처 간에 재사용하도록 허용하면, 두 출처가 공모하여 공통 키에 접근할 수 있는 능력을 기록함으로써 고유 사용자를 추적하는 것이 가능할 수 있다.

마지막으로, 키 시스템에 대한 사용자 제어용 사용자 인터페이스가 HTTP 세션 쿠키 [COOKIES] 또는 지속 저장소의 데이터와 별도로 데이터를 표시하면, 사용자는 사이트 권한을 변경하거나 데이터를 삭제할 때 어느 하나만 수정하고 나머지는 수정하지 않을 가능성이 크다. 그러면 사이트가 여러 기능을 서로의 중복 백업으로 사용할 수 있어, 개인정보를 보호하려는 사용자의 시도를 무력화할 수 있다.

사이트와 다른 제3자가 사용자를 추적할 가능성에 더해, 사용자 에이전트 구현자, CDM 공급업체 또는 장치 공급업체도 이 명세에 정의된 API를 사용하는 방문 사이트와 같은 사용자의 활동이나 관심사에 대한 프로필을 만들 수 있다. 그러한 추적은 웹 플랫폼의 나머지 부분, 특히 출처 격리와 관련된 개인정보 보호를 약화시킨다.

고유 식별자와 같은 식별자는 CDM 공급업체가 운영하거나 제공하는 서버에서, 예를 들어 개별화 프로세스를 통해 얻어질 수 있다. 이 프로세스에는 고유 영구 식별자를 포함한 클라이언트 식별자를 서버에 제공하는 것이 포함될 수 있다. 출처별 식별자를 생성하기 위해, 출처를 나타내는 값도 제공될 수 있다.

그러한 구현에서, CDM 공급업체는 사용자가 방문한 출처 수 또는 새 식별자가 필요한 횟수 같은 사용자의 활동을 추적할 수 있다. 출처 또는 출처와 연관 가능한 값이 식별자 요청에 제공되면, CDM 공급업체는 사용자 또는 장치 사용자가 방문한 사이트를 추적할 수 있다.

다음 절은 사용자 동의 없는 추적의 위험을 완화할 수 있는 기법을 설명한다.

11.4.2 완화책

고유 식별자 또는 고유 영구 식별자를 사용하지 말 것

키 시스템 구현은 가능한 한 고유 식별자와 고유 영구 식별자의 사용을 피하는 것이 SHOULD 되며, 구현의 견고성에 의미 있게 기여하는 경우에만 사용해야 한다. 고유 식별자와 영구 식별자의 사용 제한 또는 회피를 보라.

고유 영구 식별자를 애플리케이션에 노출하지 말 것

구현은 고유 영구 식별자를 애플리케이션 또는 출처에 노출해서는 MUST NOT 된다.

고유 식별자 암호화

고유 식별자키 시스템 메시지 안에서 타임스탬프 또는 nonce와 함께 암호화되어야 MUST 하며, 그 결과 키 시스템 메시지는 항상 서로 달라야 한다. 이는 키 시스템을 완전히 지원하는 서버를 제외하고는 키 시스템 메시지가 추적에 사용되는 것을 방지한다. 식별자 암호화를 보라.

고유 식별자와 키 시스템 저장 데이터를 쿠키 / 웹 저장소처럼 취급할 것

사용자 에이전트는 고유 식별자키 시스템이 저장한 데이터의 존재를 HTTP 세션 쿠키 [COOKIES]와 강하게 연관되도록 사용자에게 표시하는 것이 SHOULD 되며, "모든 데이터 제거"에 이를 포함하고 같은 UI 위치에 표시해야 한다. 이는 사용자가 그러한 식별자를 건전한 의심을 가지고 보도록 장려할 수 있다. 사용자 에이전트는 사용자가 불완전한 데이터 삭제를 피하도록 도와야 SHOULD 한다.

출처별 정보를 관련 없는 엔터티에 노출하지 말 것

출처 또는 출처와 연관 가능한 값을 개별화 서버 또는 출처와 관련 없는 다른 엔터티에 제공하지 말 것. 구현이 그러한 프로세스를 사용하는 경우 개별화 절의 요구사항과 권장사항을 따른다.

연관 불가능한 출처별·프로필별 값과 식별자를 사용할 것

애플리케이션에 노출되는 모든 고유 식별성 값에 대해, 구현은 각 출처브라우징 프로필마다 서로 다른 애플리케이션에 의해 연관 불가능한 값을 사용해야 MUST 한다. 8.4.1 출처별·프로필별 값 사용을 보라.

이는 고유 식별자를 사용하는 구현에 특히 중요하다. 8.5.3 출처별·프로필별 식별자 사용을 보라.

출처별 및 브라우징 프로필별 키 시스템 저장소 사용

CDM이 사용하는 데이터 중 애플리케이션 또는 라이선스 서버에 보이는 방식으로 메시지나 동작에 영향을 줄 수 있는 모든 데이터는 출처브라우징 프로필별로 분할되어야 MUST 하며, 비공개 브라우징 세션으로 누출되거나 그로부터 누출되어서는 MUST NOT 된다. 여기에는 메모리 내 데이터와 지속 데이터가 모두 포함된다. 구체적으로 그러나 빠짐없이 열거하는 것은 아니며, 세션 데이터, 라이선스, 키 및 출처별 식별자는 출처별 및 브라우징 프로필별로 분할되어야 MUST 한다. 8.3.1 출처별 및 브라우징 프로필별 키 시스템 저장소 사용8.4.1 출처별·프로필별 값 사용을 보라.

고유 식별자를 포함한 지속 데이터의 사용자 삭제 제공

사용자 에이전트는 키 시스템이 유지하는 고유 식별자를 포함한 모든 지속 데이터를 사용자가 삭제할 수 있는 기능을 제공해야 MUST 한다. 지속 데이터를 삭제할 수 있도록 허용을 보라.

저장된 데이터 만료시키기

사용자 에이전트는, 사용자가 구성한 방식일 수도 있는 방식으로, 일정 시간이 지난 후 고유 식별자 및/또는 기타 키 시스템 데이터를 자동으로 삭제할 MAY 수 있다.

예를 들어, 사용자 에이전트는 그러한 데이터를 세션 전용 저장소로 저장하도록 구성되어, 사용자가 이에 접근할 수 있는 모든 브라우징 컨텍스트를 닫으면 데이터를 삭제할 수 있다.

이는 사이트가 사용자를 추적하는 능력을 제한할 수 있다. 그러면 사이트는 사용자가 그 사이트 자체에서 인증하는 경우(예: 구매하거나 서비스에 로그인함) 여러 세션에 걸쳐서만 사용자를 추적할 수 있기 때문이다.

그러나 사용자가 그러한 만료의 의미를 완전히 이해하지 못하면, 이는 사용자의 콘텐츠, 특히 구매하거나 대여한 콘텐츠에 대한 접근을 위험에 빠뜨릴 수도 있다.

제3자 접근 차단

사용자 에이전트는 키 시스템 및/또는 기능에 대한 접근을 브라우징 컨텍스트의 최상위 Document출처에서 기원한 스크립트로 제한할 MAY 수 있다. 예를 들어, requestMediaKeySystemAccess()iframe에서 실행 중인 다른 출처의 페이지에 대해 특정 구성 요청을 거부할 수 있다.

사용자 에이전트는 고유 식별자 또는 고유 영구 식별자를 사용하기 전에 사용자가 충분히 정보를 제공받고 및/또는 명시적으로 동의하도록 보장해야 MUST 한다.

그러한 메커니즘은 유효한 사용이 이후의 악의적 접근을 가능하게 하는 것을 피하기 위해 출처별이어야 MUST 하며, 브라우징 프로필별이어야 MUST 한다.

이 명세에 정의된 API를 보안 컨텍스트로 제한하면 네트워크 공격자가 인증되지 않은 출처에 부여된 권한을 악용할 수 없도록 보장된다. 지속된 동의의 남용을 보라.

키 시스템 또는 키 시스템의 식별자 사용을 비활성화하는 사용자 제어 제공

사용자 에이전트는 키 시스템이 활성화되는지 및/또는 키 시스템고유 식별자 또는 고유 영구 식별자 사용이 활성화되는지에 대한 전역 제어를 사용자에게 제공하는 것이 SHOULD 된다(키 시스템이 지원하는 경우). 사용자 에이전트는 사용자가 불완전한 데이터 삭제를 피하도록 도와야 SHOULD 한다.

키 시스템에 대한 접근의 사이트별 허용 목록 요구

사용자 에이전트는 사이트가 각 키 시스템 및/또는 특정 기능을 사용하기 전에 사용자가 그 접근을 명시적으로 승인하도록 요구할 MAY 수 있다. 사용자 에이전트는 사용자가 이 승인을 일시적으로 또는 영구적으로 철회할 수 있게 해야 SHOULD 한다.

공유 차단 목록 사용

사용자 에이전트는 사용자가 출처 및/또는 키 시스템의 차단 목록을 공유할 수 있게 할 MAY 수 있다. 이는 공동체가 함께 행동하여 개인정보를 보호할 수 있게 한다.

이러한 제안은 이 명세에 정의된 API가 사용자 추적에 사소하게 사용되는 것을 방지하지만, 이를 완전히 차단하지는 않는다. 단일 출처 내에서 사이트는 세션 동안 사용자를 계속 추적할 수 있으며, 사이트가 얻은 식별 정보(이름, 신용카드 번호, 주소)와 함께 이 모든 정보를 제3자에게 전달할 수 있다. 제3자가 여러 사이트와 협력하여 그러한 정보를 얻고, 식별자가 출처 및 프로필별로 고유하지 않다면, 여전히 프로필이 생성될 수 있다.

11.5 사용자 기기에 저장되는 정보

11.5.1 우려사항

이 절은 비규범적이다.

키 시스템은 사용자의 기기에 정보를 저장할 수 있고, 또는 사용자 에이전트가 키 시스템을 대신하여 정보를 저장할 수 있다. 잠재적으로 이는 같은 기기의 다른 사용자에게 사용자에 관한 정보를 드러낼 수 있으며, 여기에는 특정 키 시스템을 사용한 출처(즉, 방문한 사이트)나 심지어 키 시스템을 사용하여 복호화된 콘텐츠까지 포함될 수 있다.

한 출처가 저장한 정보가 다른 출처에 대한 키 시스템의 동작에 영향을 주면, 한 사이트에서 사용자가 방문한 사이트나 본 콘텐츠가 다른, 잠재적으로 악성인 사이트에 드러날 수 있다.

클라이언트 기기에서 한 브라우징 프로필을 위해 저장된 정보가 다른 브라우징 프로필 또는 브라우저에 대한 키 시스템의 동작에 영향을 주면, 한쪽에서 방문한 사이트나 본 콘텐츠가 다른 브라우징 프로필에 의해 드러나거나 그것과 상관될 수 있으며, 여기에는 서로 다른 운영 체제 사용자 계정이나 브라우저까지 포함될 수 있다.

11.5.2 완화책

이러한 우려를 완화하는 요구사항은 8.3 영속 데이터에 정의되어 있다.

11.6 데이터의 불완전한 삭제

11.6.1 우려사항

이 절은 비규범적이다.

사용자가 고유 식별자와 저장된 데이터를 삭제하거나 및/또는 키 시스템을 비활성화하여 개인정보를 보호하려는 시도는, 그러한 모든 데이터와 기능뿐만 아니라 쿠키 [COOKIES] 및 기타 사이트 데이터가 동시에 삭제되거나 및/또는 비활성화되지 않으면 무력화될 수 있다. 예:

  • 사용자가 쿠키 또는 기타 지속 저장소를 삭제하면서 고유 식별자와 키 시스템이 저장한 데이터를 함께 삭제하지 않으면, 사이트는 여러 기능을 서로의 중복 백업으로 사용하여 그러한 시도를 무력화할 수 있다.

  • 사용자가 고유 식별자를 삭제하면서 지속 세션을 포함하여 키 시스템이 저장한 데이터와 쿠키 및 기타 지속 저장소를 함께 삭제하지 않으면, 사이트는 남아 있는 데이터를 사용하여 이전 식별자와 새 식별자를 연관시킴으로써 그러한 시도를 무력화할 수 있다.

  • 사용자가 키 시스템을, 특히 특정 출처에 대해 비활성화하면서 쿠키 또는 기타 지속 저장소를 함께 삭제하지 않으면, 사이트는 남아 있는 기능을 사용하여 그러한 시도를 무력화할 수 있다.

  • 사용자가 키 시스템을 비활성화한 뒤, 나중에 키 시스템을 다시 활성화하기로 결정하면서 쿠키 또는 기타 지속 저장소, 고유 식별자, 그리고 키 시스템이 저장한 데이터를 함께 삭제하지 않으면, 사이트는 비활성화 이전의 데이터를 키 시스템이 다시 활성화된 이후의 데이터 및 동작과 연관시킬 수 있다.

11.6.2 완화책

이러한 우려를 완화하는 권고는 8.3 영속 데이터에 정의되어 있다.

11.7 비공개 브라우징 모드

사용자 에이전트는 사용자 익명성을 보존하고/하거나 브라우징 활동 기록이 클라이언트에 영속화되지 않도록 하기 위한 동작 모드(예: 비공개 브라우징)를 지원할 수 있다. 이전 절에서 논의한 개인정보 보호 우려는 그러한 모드를 사용하는 사용자에게 특히 우려될 수 있다.

그러한 모드를 지원하는 사용자 에이전트 구현자는 이러한 모드에서 키 시스템에 대한 접근을 비활성화해야 하는지 신중히 고려하는 것이 좋다 SHOULD. 예를 들어, 그러한 모드는 MediaKeySystemAccess 객체 중 persistentState 또는 distinctiveIdentifier를 지원하거나 사용하는 객체의 생성을 금지할 수 있다 MAY (이는 CDM 구현의 일부로서일 수도 있고, 애플리케이션이 그것들을 "required"라고 표시했기 때문일 수도 있다). 구현이 그러한 생성을 금지하지 않는다면, 이를 허용하기 전에 그러한 모드의 예상되는 개인정보 보호 속성에 대한 의미와 잠재적 결과를 사용자에게 알리는 것이 좋다 SHOULD.

11.8 보안 출처 및 전송

이 명세에 정의된 API는 보안 출처에서만 지원되며, 이전 절에서 논의한 정보를 보호한다. 식별자는 식별자 암호화에 명시된 대로 추가로 암호화된다.

애플리케이션은, 사용하는 서버를 포함하여, CDM으로부터의 데이터나 메시지를 포함하거나 관련된 모든 트래픽에 보안 전송을 사용하는 것이 좋다 SHOULD. 여기에는 message 이벤트에서 전달되는 모든 데이터와 update()에 전달되는 모든 데이터가 포함되지만 이에 국한되지 않는다.

모든 사용자 에이전트는 사용자 에이전트 또는 애플리케이션이 보안 출처와 전송을 강제하려는 경우 안전하지 않은 콘텐츠나 전송에 노출되지 않도록 혼합 콘텐츠 [MIXED-CONTENT]를 적절히 처리해야 MUST 한다.

12. 적합성

비규범적으로 표시된 절뿐 아니라, 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고는 비규범적이다. 이 명세의 그 밖의 모든 것은 규범적이다.

이 문서의 핵심 단어 MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHALL, SHALL NOT, SHOULD, 및 SHOULD NOT는 여기에 보인 것처럼 모두 대문자로 나타날 때, 그리고 오직 그때에만, BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석된다.

13. 예제

이 절은 비규범적이다.

이 절은 제안된 확장을 사용하여 다양한 사용 사례에 대한 예제 해결책을 포함한다. 이것들이 이러한 사용 사례에 대한 유일한 해결책은 아니다. 예제에서는 video 요소를 사용하지만, 모든 미디어 요소에도 동일하게 적용된다. 동기 XHR 사용과 같은 일부 경우에는 확장에 초점을 맞추기 위해 예제를 단순화했다.

13.1 페이지 로드 시 소스와 키가 알려져 있음(Clear Key)

이 간단한 예제에서는 소스 파일과 평문 라이선스가 페이지에 하드코딩되어 있다. 세션은 언제나 하나만 생성된다.

<script>
  function onLoad() {
    var video = document.getElementById('video');

    if (!video.mediaKeys) {
      navigator.requestMediaKeySystemAccess('org.w3.clearkey', [
        { initDataTypes: ['webm'],
          videoCapabilities: [{ contentType: 'video/webm; codecs="vp8"' }] }
      ]).then(
        function(keySystemAccess) {
          var promise = keySystemAccess.createMediaKeys();
          promise.catch(
            console.error.bind(console, 'Unable to create MediaKeys')
          );
          promise.then(
            function(createdMediaKeys) {
              return video.setMediaKeys(createdMediaKeys);
            }
          ).catch(
            console.error.bind(console, 'Unable to set MediaKeys')
          );
          promise.then(
            function(createdMediaKeys) {
              var te = new TextEncoder();
              var initData = te.encode( '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}');
              var keySession = createdMediaKeys.createSession();
              keySession.addEventListener("message", handleMessage, false);
              return keySession.generateRequest('keyids', initData);
            }
          ).catch(
            console.error.bind(console, 'Unable to create or initialize key session')
          );
        }
      );
    }
  }

  function handleMessage(event) {
    var keySession = event.target;
    var te = new TextEncoder();
    var license = te.encode('{"keys":[{"kty":"oct","k":"tQ0bJVWb6b0KPL6KtZIy_A","kid":"LwVHf8JLtPrv2GUXFW2v_A"}],"type":"temporary"}');
    keySession.update(license).catch(
      console.error.bind(console, 'update() failed')
    );
  }
</script>

<body onload='onLoad()'>
  <video src='foo.webm' autoplay id='video'></video>
</body>

13.2 지원되는 키 시스템 선택 및 "encrypted" 이벤트의 초기화 데이터 사용

이 예제는 requestMediaKeySystemAccess() 메서드를 사용하여 지원되는 키 시스템을 선택한 다음, 라이선스 요청을 생성하고 적절한 라이선스 서버로 보내기 위해 미디어 데이터초기화 데이터를 사용한다. 지원되는 키 시스템 중 하나는 serverCertificate를 사용하며, 이는 사전에 제공된다.

<script>
  var licenseUrl;
  var serverCertificate;

  // Returns a Promise<MediaKeys>.
  function createSupportedKeySystem() {
    someSystemOptions = [
     { initDataTypes: ['keyids', 'webm'],
       audioCapabilities: [
         { contentType: 'audio/webm; codecs="opus"' },
         { contentType: 'audio/webm; codecs="vorbis"' }
       ],
       videoCapabilities: [
         { contentType: 'video/webm; codecs="vp9"' },
         { contentType: 'video/webm; codecs="vp8"' }
       ]
     }
    ];
    clearKeyOptions = [
     { initDataTypes: ['keyids', 'webm'],
       audioCapabilities: [
         { contentType: 'audio/webm; codecs="opus"' },
         { contentType: 'audio/webm; codecs="vorbis"' }
       ],
       videoCapabilities: [
         { contentType: 'video/webm; codecs="vp9"',
           robustness: 'foo' },
         { contentType: 'video/webm; codecs="vp9"',
           robustness: 'bar' },
         { contentType: 'video/webm; codecs="vp8"',
           robustness: 'bar' },
       ]
     }
    ];

    return navigator.requestMediaKeySystemAccess('com.example.somesystem', someSystemOptions).then(
      function(keySystemAccess) {
        // Not shown:
        // 1. Use both attributes of keySystemAccess.getConfiguration().audioCapabilities[0]
        //    and both attributes of keySystemAccess.getConfiguration().videoCapabilities[0]
        //    to retrieve appropriate stream(s).
        // 2. Set video.src.

        licenseUrl = 'https://license.example.com/getkey';
        serverCertificate = new Uint8Array([ ... ]);
        return keySystemAccess.createMediaKeys();
      }
    ).catch(
      function(error) {
        // Try the next key system.
        navigator.requestMediaKeySystemAccess('org.w3.clearkey', clearKeyOptions).then(
          function(keySystemAccess) {
            // Not shown:
            // 1. Use keySystemAccess.getConfiguration().audioCapabilities[0].contentType
            //    and keySystemAccess.getConfiguration().videoCapabilities[0].contentType
            //    to retrieve appropriate stream(s).
            // 2. Set video.src.

            licenseUrl = 'https://license.example.com/clearkey/request';
            return keySystemAccess.createMediaKeys();
          }
        );
      }
    ).catch(
      console.error.bind(console, 'Unable to instantiate a key system supporting the required combinations')
    );
  }

  function handleInitData(event) {
    var video = event.target;
    if (video.mediaKeysObject === undefined) {
      video.mediaKeysObject = null; // Prevent entering this path again.
      video.pendingSessionData = []; // Will store all initData until the MediaKeys is ready.
      createSupportedKeySystem().then(
        function(createdMediaKeys) {
          video.mediaKeysObject = createdMediaKeys;

          if (serverCertificate)
            createdMediaKeys.setServerCertificate(serverCertificate);

          for (var i = 0; i < video.pendingSessionData.length; i++) {
            var data = video.pendingSessionData[i];
            makeNewRequest(video.mediaKeysObject, data.initDataType, data.initData);
          }
          video.pendingSessionData = [];

          return video.setMediaKeys(createdMediaKeys);
        }
      ).catch(
        console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
      );
    }
    addSession(video, event.initDataType, event.initData);
  }

  function addSession(video, initDataType, initData) {
    if (video.mediaKeysObject) {
      makeNewRequest(video.mediaKeysObject, initDataType, initData);
    } else {
      video.pendingSessionData.push({initDataType: initDataType, initData: initData});
    }
  }

  function makeNewRequest(mediaKeys, initDataType, initData) {
    var keySession = mediaKeys.createSession();
    keySession.addEventListener("message", licenseRequestReady, false);
    keySession.generateRequest(initDataType, initData).catch(
      console.error.bind(console, 'Unable to create or initialize key session')
    );
  }

  function licenseRequestReady(event) {
    var request = event.message;

    var xmlhttp = new XMLHttpRequest();
    xmlhttp.keySession = event.target;
    xmlhttp.open("POST", licenseUrl);
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4) {
        var license = new Uint8Array(xmlhttp.response);
        xmlhttp.keySession.update(license).catch(
          console.error.bind(console, 'update() failed')
        );
      }
    }
    xmlhttp.send(request);
  }
</script>

<video autoplay onencrypted='handleInitData(event)'></video>

13.3 미디어 로드 전에 MediaKeys 생성

MediaKeys 초기화 중에 encrypted 이벤트를 처리할 필요가 없다면 초기화는 훨씬 단순하다. 이는 초기화 데이터를 다른 방식으로 제공하거나, MediaKeys 객체가 생성된 후 소스를 설정하여 달성할 수 있다. 이 예제는 후자를 수행한다.

<script>
  var licenseUrl;
  var serverCertificate;
  var mediaKeys;

  // See the previous example for implementations of these functions.
  function createSupportedKeySystem() { ... }
  function makeNewRequest(mediaKeys, initDataType, initData) { ... }
  function licenseRequestReady(event) { ... }

  function handleInitData(event) {
    makeNewRequest(mediaKeys, event.initDataType, event.initData);
  }

  createSupportedKeySystem().then(
    function(createdMediaKeys) {
      mediaKeys = createdMediaKeys;
      var video = document.getElementById("v");
      video.src = 'foo.webm';
      if (serverCertificate)
        mediaKeys.setServerCertificate(serverCertificate);
      return video.setMediaKeys(mediaKeys);
    }
  ).catch(
    console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
  );
</script>

<video id="v" autoplay onencrypted='handleInitData(event)'></video>

13.4 모든 이벤트 사용

이것은 모든 이벤트가 사용되는 모습을 보여 주는 더 완전한 예제이다.

handleMessage()는 여러 번 호출될 수 있음에 유의한다. 여기에는 여러 번의 왕복이 필요한 경우 update() 호출에 대한 응답으로 호출되는 경우와, 키 시스템이 메시지를 보내야 할 수 있는 기타 모든 이유가 포함된다.

<script>
  var licenseUrl;
  var serverCertificate;
  var mediaKeys;

  // See previous examples for implementations of these functions.
  // createSupportedKeySystem() additionally sets renewalUrl.
  function createSupportedKeySystem() { ... }
  function handleInitData(event) { ... }

  // This replaces the implementation in the previous example.
  function makeNewRequest(mediaKeys, initDataType, initData) {
    var keySession = mediaKeys.createSession();
    keySession.addEventListener('message', handleMessage, false);
    keySession.addEventListener('keystatuseschange', handlekeyStatusesChange, false);
    keySession.closed.then(
      function(reason) {
        console.log('Session', this.sessionId, 'closed, reason', reason);
      }.bind(keySession)
    );
    keySession.generateRequest(initDataType, initData).catch(
      console.error.bind(console, 'Unable to create or initialize key session')
    );
  }

  function handleMessageResponse(keySession, response) {
    var license = new Uint8Array(response);
    keySession.update(license).catch(
      function(err) {
        console.error('update() failed: ' + err);
      }
    );
  }

  function sendMessage(type, message, keySession) {
    var url = licenseUrl;
    if (type == "license-renewal")
      url = renewalUrl;
    xmlhttp = new XMLHttpRequest();
    xmlhttp.keySession = keySession;
    xmlhttp.open('POST', url);
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4)
        handleMessageResponse(xmlhttp.keySession, xmlhttp.response);
    }
    xmlhttp.send(message);
  }

  function handleMessage(event) {
    sendMessage(event.messageType, event.message, event.target);
  }

  function handlekeyStatusesChange(event) {
    // Evaluate the current state using one of the map-like methods exposed by
    // event.target.keyStatuses.
    // For example:
    event.target.keyStatuses.forEach(function(status, keyId) {
      switch (status) {
        case "usable":
          break;
        case "expired":
          // Report an expired key.
          break;
        case "status-pending":
          // The status is not yet known. Consider the key unusable until the status is updated.
          break;
        default:
          // Do something with |keyId| and |status|.
      }
    })
  }

  createSupportedKeySystem().then(
    function(createdMediaKeys) {
      mediaKeys = createdMediaKeys;
      var video = document.getElementById("v");
      video.src = 'foo.webm';
      if (serverCertificate)
        mediaKeys.setServerCertificate(serverCertificate);
      return video.setMediaKeys(mediaKeys);
    }
  ).catch(
    console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
  );
</script>

<video id="v" autoplay onencrypted='handleInitData(event)'></video>

13.5 저장된 라이선스

이 예제는 나중에 사용하기 위한 영속 라이선스를 요청하고 저장한다. 또한 나중에 라이선스를 가져오는 함수와 이를 파기하는 함수를 제공한다.

<script>
  var licenseUrl;
  var serverCertificate;
  var mediaKeys;

  // See the previous examples for implementations of these functions.
  // createSupportedKeySystem() additionally sets persistentState: "required" in each options dictionary.
  function createSupportedKeySystem() { ... }
  function sendMessage(message, keySession) { ... }
  function handleMessage(event) { ... }

  // Called if the application does not have a stored sessionId for the media resource.
  function makeNewRequest(mediaKeys, initDataType, initData) {
    var keySession = mediaKeys.createSession("persistent-license");
    keySession.addEventListener('message', handleMessage, false);
    keySession.closed.then(
      function(reason) {
        console.log('Session', this.sessionId, 'closed, reason', reason);
      }.bind(keySession)
    );
    keySession.generateRequest(initDataType, initData).then(
      function() {
        // Store this.sessionId in the application.
      }.bind(keySession)
    ).catch(
      console.error.bind(console, 'Unable to request a persistent license')
    );
  }

  // Called if the application has a stored sessionId for the media resource.
  function loadStoredSession(mediaKeys, sessionId) {
    var keySession = mediaKeys.createSession("persistent-license");
    keySession.addEventListener('message', handleMessage, false);
    keySession.closed.then(
      function(reason) {
        console.log('Session', this.sessionId, 'closed, reason', reason);
      }.bind(keySession)
    );
    keySession.load(sessionId).then(
      function(loaded) {
        if (!loaded) {
          console.error('No stored session with the ID ' + sessionId + ' was found.');
          // The application should remove its record of |sessionId|.
          return;
        }
      }
    ).catch(
      console.error.bind(console, 'Unable to load or initialize the stored session with the ID ' + sessionId)
    );
  }

  // Called when the application wants to stop using the session without removing the stored license.
  function closeSession(keySession) {
    keySession.close();
  }

  // Called when the application wants to remove the stored license.
  // The stored session data has not been completely removed until the promise returned by remove() is fulfilled.
  // The remove() call may initiate a series of messages to/from the server that must be completed before this occurs.
  function removeStoredSession(keySession) {
    keySession.remove().then(
      function() {
        console.log('Session ' + this.sessionId + ' removed');
        // The application should remove its record of this.sessionId.
      }.bind(keySession)
    ).catch(
      console.error.bind(console, 'Failed to remove the session')
    );
  }

  // This replaces the implementation in the previous example.
  function handleMessageResponse(keySession, response) {
    var license = new Uint8Array(response);
    keySession.update(license).then(
      function() {
        // If this was the last required message from the server, the license is
        // now stored. Update the application state as appropriate.
      }
    ).catch(
      console.error.bind(console, 'update() failed')
    );
  }

  createSupportedKeySystem().then(
    function(createdMediaKeys) {
      mediaKeys = createdMediaKeys;
      var video = document.getElementById("v");
      if (serverCertificate)
        mediaKeys.setServerCertificate(serverCertificate);
      return video.setMediaKeys(mediaKeys);
    }
  ).catch(
    console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
  );
</script>

<video id='v' src='foo.webm' autoplay></video>

13.6 HDCP 정책으로 미디어 사전 가져오기

일부 미디어가 라이선스 안에 HDCP 정책을 갖게 될 경우, 애플리케이션은 사전 가져오기 전에 해당 버전을 확인할 수 있다.

const status = await video.mediaKeys.getStatusForPolicy({
  minHdcpVersion: '1.4'
});

if (status === 'usable') {
  // Pre-fetch HD content.
} else {  // 'output-restricted'
  // Pre-fetch SD content.
}

14. 감사의 말

편집자들은 이 명세에 기여해 준 Aaron Colwell, Alex Russell, Anne van Kesteren, Bob Lund, Boris Zbarsky, Chris Needham, Chris Pearce, David Singer, Domenic Denicola, Frank Galligan, Glenn Adams, Henri Sivonen, Jer Noble, Joe Steele, Joey Parrish, John Simmons, Mark Vickers, Pavel Pergamenshchik, Philip Jägenstedt, Pierre Lemieux, Robert O'Callahan, Ryan Sleevi, Steve Heffernan, Steven Robertson Theresa O'Connor, Thomás Inskip, Travis Leithead, 그리고 Xiaohan Wang에게 감사한다. 메일링 리스트와 이슈 참여를 포함하여 명세에 기여해 준 많은 다른 분들께도 감사드린다.

A. 참고문헌

A.1 규범적 참고문헌

[COOKIES]
HTTP State Management Mechanism. A. Barth. IETF. 2011년 4월. 제안 표준. URL: https://httpwg.org/specs/rfc6265.html
[dom]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMA-262]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[EME-INITDATA-KEYIDS]
"keyids" Initialization Data Format. Joey Parrish; Greg Freedman. W3C. 2024년 8월 20일. W3C Working Group Note. URL: https://www.w3.org/TR/eme-initdata-keyids/
[EME-INITDATA-REGISTRY]
Encrypted Media Extensions Initialization Data Format Registry. Joey Parrish; Greg Freedman. W3C. 2026년 5월 7일. DRY. URL: https://www.w3.org/TR/eme-initdata-registry/
[ENCODING]
Encoding Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://encoding.spec.whatwg.org/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[Infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[mimesniff]
MIME Sniffing Standard. Gordon P. Hemsley. WHATWG. Living Standard. URL: https://mimesniff.spec.whatwg.org/
[MIXED-CONTENT]
Mixed Content. Emily Stark; Mike West; Carlos IbarraLopez. W3C. 2023년 2월 23일. CRD. URL: https://www.w3.org/TR/mixed-content/
[PERMISSIONS-POLICY]
Permissions Policy. Ian Clelland. W3C. 2025년 10월 6일. W3C Working Draft. URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997년 3월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC6381]
The 'Codecs' and 'Profiles' Parameters for "Bucket" Media Types. R. Gellens; D. Singer; P. Frojdh. IETF. 2011년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6381
[RFC7517]
JSON Web Key (JWK). M. Jones. IETF. 2015년 5월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7517
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. 2017년 5월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

A.2 정보성 참고문헌

[CENC]
ISO/IEC 23001-7:2016, Information technology — MPEG systems technologies — Part 7: Common encryption in ISO Base Media File Format files. ISO/IEC. International Standard. URL: https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1
[EME-HDCP-VERSION-REGISTRY]
Encrypted Media Extensions HDCP Version Registry. Joey Parrish; Greg Freedman. W3C. 2026년 5월 7일. DRY. URL: https://www.w3.org/TR/eme-hdcp-version-registry/
[EME-STREAM-REGISTRY]
Encrypted Media Extensions Stream Format Registry. Joey Parrish; Greg Freedman. W3C. 2026년 5월 7일. DRY. URL: https://www.w3.org/TR/eme-stream-registry/
[MEDIA-SOURCE]
Media Source Extensions™. Jean-Yves Avenard; Mark Watson. W3C. 2025년 11월 4일. W3C Working Draft. URL: https://www.w3.org/TR/media-source-2/
[RFC6838]
Media Type Specifications and Registration Procedures. N. Freed; J. Klensin; T. Hansen. IETF. 2013년 1월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc6838
[RFC7515]
JSON Web Signature (JWS). M. Jones; J. Bradley; N. Sakimura. IETF. 2015년 5월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7515
[webaudio]
Web Audio API 1.1. Paul Adenot; Hongchan Choi. W3C. 2024년 11월 5일. FPWD. URL: https://www.w3.org/TR/webaudio-1.1/