100% found this document useful (1 vote)
2K views

Widevine DRM Encryption API

This document specifies an interface for requesting encryption keys from Google's Widevine DRM system. The interface allows an encryption process to send a request containing a content ID to the key server. The key server will respond with Widevine header data and encryption keys associated with that content ID.

Uploaded by

pooper
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
2K views

Widevine DRM Encryption API

This document specifies an interface for requesting encryption keys from Google's Widevine DRM system. The interface allows an encryption process to send a request containing a content ID to the key server. The key server will respond with Widevine header data and encryption keys associated with that content ID.

Uploaded by

pooper
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Common Encryption API for Widevine DRM

Version1.5

History

Date Changes

10/08/2014 Updatedtestplayerandcontenturls.

07/30/2013 UpdatedKeyId(tracks.key_id).Typeis128bitbinaryreturnedasBase64
encodedstring.
UpdatedContentId.TypeisbinaryspecifiedasaBase64encodedstring.
Sizecannotexceed1024bytes.

08/02/2013 ChangesingleWidevinePSSHtoanarraycontainingWidevineand
PlayReady.Newfieldinresponseiscalledcontent_protection.

03/21/2014 Addnewfieldstosupportlivestreamingwithkeyrotation.
first_crypto_period_index
crypto_period_count

01/13/2015 AddedsectiondescribinginsertingaPSSHintoaMPD
UpdateddemoplayersectionwithWidevineShakaPlayerlinks

04/21/2015 Updatedsignaturerequirements

01/22/2016 Addeddrm_typesarraytotheencryptionrequesttosupportPlayReady.

02/29/2016 Addcrypto_period_seconds.

06/28/2016 UpdatedWidevine
proto
.

2016Google,Inc.AllRightsReserved.Noexpressorimpliedwarrantiesareprovidedforherein.Allspecificationsaresubjectto
changeandanyexpectedfutureproducts,featuresorfunctionalitywillbeprovidedonanifandwhenavailablebasis.Notethatthe
descriptionsofGooglespatentsandotherintellectualpropertyhereinareintendedtoprovideillustrative,nonexhaustiveexamples
ofsomeoftheareastowhichthepatentsandapplicationsarecurrentlybelievedtopertain,andisnotintendedforuseinalegal
proceedingtointerpretorlimitthescopeormeaningofthepatentsortheirclaims,orindicatethataGooglepatentclaim(s)is
materiallyrequiredtoperformorimplementanyofthelisteditems.


GoogleConfidential Page2of14
Introduction
ThisdocumentspecifiesaninterfaceforaddingsupportforGooglesWidevineencryptiontoa
videoprocessingsystem.Theinterfaceallowstheencryptionprocesstorequestandreceive
theWidevineheaderandencryptionkey.

Description
TheencryptionprocesssendsanHTTP(s)requesttotheKeyserver.Therequestcontainsthe
uniquecontentidentifier(ContentId).TheContentIdisownedbytheencryptionprocess.The
KeyserverwillrespondwithProtectionSystemSpecificHeader(PSSH)dataforWidevineand
ContentKey(s)thatareassociatedwiththeContentId.
AllBase64encodedstringsusethestandardencodingspecifiedinRFC4648.
WidevineSystemIDforthePSSH
edef8ba979d64acea3c827dcd51d21ed
DASHMPDContentProtectiontype: widevine

Details
Authentication
Theprotocoldescribedinthisdocumentssupportstheabilityfortheclientandserverto
optionally
signthemessage.Themethoddescribedhereistheclientwillsigntherequestby
usingtheclientsAESkeyandWidevinewillsigntheresponseusingWidevinesRSAkey.

Request
TherequestisanHTTPPOSTrequesttotheKeyServerURL.
TheposteddataisaJSONformatted( optionallysigned
)requestwiththefollowingsyntax:

{
request:<message>,
signature:<signature>,
signer:<signername>
}

Name Value Description

request Base64encodedstring. Requiredfield.


Theactualmessage.Thisisaserialized
JSONmessagecontainingtherequestor
theresponse.Themessageisintheclear.

signature Base64encodedstring. Optionalfield.


RFC4648 RequiredforaccesstoWidevineCloud


GoogleConfidential Page3of14
LicenseService.

AESCBCencryptionoftheSHA1hashof
<message>.

signer string Required.


Identifiestheentitysendingthemessage.

Theclear<message>isaJSONformattedstringcontainingthecontentidandthetracktypes.
Acontentmayhaveoneormoretracktypes,forexample,theaudiotrackmaybeencrypted
withadifferentkeythanthevideotrack.OrthecontentmayhaveanSDvideotrackandanHD
videotrackencryptedwithdifferentkeys.

{
"content_id":"vid0000001",
policy:test_policy,
"tracks":[
{
type:HD
},
{
type:SD
},
{
type:AUDIO,
}
],
drm_types:[
{
WIDEVINE,
},
],
}

Name Value Description

type Oneof: Required.


HD,SD,AUDIO Labeltoidentifythetracktype.ItsOKfor
(maynotbelimitedto multiplerequeststospecifythesametracktype.
thissetoftypes) Inthiscase,thesamekeyidandkeyisreturned
foreachtrackofthesametype.

policy string Optional.


GoogleConfidential Page4of14
Ascii,maxsize=1024 Nameofapreviouslystoredpolicytouseforthis
bytes. content.Thepolicycontainsplaybackduration
informationandoutputprotectioninformationfor
SD,HDandAUDIO.If<policy>isnotspecified,
thecontentprovidermustprovideallpolicy
attributesatthetimeoflicenseacquisition.

content_id Base64encodedstring Required.


Uniqueidentifierofthecontent.Thecontent_id
Binary,maxsize=1024 willbeavailableinthelicenserequest.
bytes.

token Optionalbase64 Ifpresent,the72bytetokenfromaWidevine


encodedstring. keybox.Contentkeysintheresponsewillbe
AESor3DESencryptedusingthedevicekey
associatedwiththistoken,andthustheresponse
willonlyusablebyadevicewiththatkeybox.

rsa_public_key OptionalRSApublic Ifpresent,arandomsession_keyencryptedwith


keyinBase64 thispublickeywillbeincludedintheresponse.
DERencodedPKCS#1 ContentkeysintheresponsewillbeAESECB
format. encryptedwiththesessionkey.

first_crypto_period_index 32bitunsignedint Usedforkeyrotationonly.


Thetimevalueforthefirstkeyperiodforwhich
keysarerequested,dividedbytheperiod
duration.Perhapsepochormediatime.

crypto_period_count 32bitunsignedint Usedforkeyrotationonly.


Numberofkeysrequested.

crypto_period_seconds 32bitunsignedint Usedforkeyrotationonly.


Numberofsecondsineachcryptoperiod.

drm_types Optionalenumerated Usedtorequestpsshdataconformingto


drmtypeidentifier. nonwidevinedrm.

Signing the request


GeneratetheJSONstring.
Json::StyledWriterwriter
std::stringclear_message=writer.write(root)

Signthemessage.
GenerateSHA1hashofthemessage.Resultis20bytesstring.
Encryptthe20bytehash.
ForAES:CBC,PKCS5padding
ForRSA:RSAPSS,PKCS1.5padding,Saltlength=20.


GoogleConfidential Page5of14
Multiple requests using the same Content Id with different track types.
ItispossiblefortheclienttosendmultiplerequestsforcontentkeyswiththesamecontentId
(c_id))butwithdifferenttracktypes.Forexample,
request#1:contentId=CID,tracktype=SD.
request#2:contentId=CID,tracktype=AUDIO.

Inthiscase,theKeyServerwillreturnaresponseforeachrequestasfollows:
response#1:status=OK,contentId=CID,keyId=KID_1,contentkey=CKey_1,
tracktype=SD
response#2:status=OK,contentId=CID,keyId=KID_2,contentkey=CKey_2,
tracktype=AUDIO.

Multiple requests using the same Content Id with same track types.
IfmultiplerequestsaresentwiththesamecontentIdandsametracktype,thefirstresponse
willcontainthesamekeyIdandcontentkey.Thesecondresponsewillalsosucceedandfield
indicatingalreadyused.
request#1:contentId=CID,tracktype=SD.
request#2:contentId=CID,tracktype=SD.

Inthiscase,theKeyServerwillreturnaresponseforeachrequestasfollows:
response#1:status=OK,contentId=CID,keyId=KID_1,contentkey=CKey_1,
tracktype=SD.
response#2:status=OK,contentId=CID,keyId=KID_1,contentkey=CKey_1,
tracktype=SD,already_used=true.

Response
Ifsigned,theresponseisaJSONformattedstring.
{
response:<message>,
signature:<signature>
}

Where<message>isaJSONformattedstring.Foreachtracktypeintherequest,thereisa
keyandkey_idintheresponse..

{
"status":"OK",
"content_id":"vid0000001",
"session_key":"MTIzNDU2Nzg5MDEyMzQ1",
"drm":[
{
"type":"widevine",
"system_id":"edef8ba979d64acea3c827dcd51d21ed"
},


GoogleConfidential Page6of14
{
"type":"playready",
"system_id":"79f0049a40988642ab92e65be0885f95"
}
],
"tracks":[
{
pssh:[
{
drm_type:widevine,
"pssh_data":"aDM0aDM0MjNrMDAyODVubm5uZ2dnZzMyNDM0MmRmYWRm"
},
{
drm_type:playready,
pssh_data:TODO:AddXMLdata
}
]
"key_id":"MTIzNDU2Nzg5MDExMTExMQ==",
"type":"HD",
"key":"MTIzNDU2Nzg5MDAwMDAwMQ=="
},
{
pssh:[
{
drm_type:widevine,
"pssh_data":"aDM0aDM0MjNrMDAyODVtbW1tZ2dnZzMyNDM0MmRmYWRm"
},
{
drm_type:playready,
pssh_data:TODO:AddXMLdata
}
]
"key_id":"MTIzNDU2Nzg5MDIyMjIyMg==",
"type":"SD",
"key":"MTIzNDU4Nzg5MDAwMDAwMg==",
"iv":"MTIzNDU2Nzg5MDEyMzQ1"
},
{
pssh:[
{
drm_type:widevine,
"pssh_data":"aDM0aDM0MjNrMDAyODVtbW1tZ2dnZzMyNDM0MmRmYWRm"
},
{
drm_type:playready,
pssh_data:TODO:AddXMLdata
}
]

GoogleConfidential Page7of14
"key_id":"MTIzNDU2Nzg5MDMzMzMzMw==",
"type":"AUDIO",
"key":"MTIzNDU6Nzg5MDAwMDAwMg=="
}
]
}

Name Value Description

status string Ifsuccessful,OKisreturned.Otherwiseanerror


codeisreturnedtoindicatefailure.
SeeStatusCodes
tablebelow.

session_key Base64encodedbinarystring OptionalAES128bitrandomkeyusedtoencrypt


thecontentkeys.Thesession_keyisencrypted
withtheclientsRSAkeyspecifiedintherequest.

drm arrayofJSONstruct. AlistofDRMsystems.

drm.type String. TheDRMsystem.



oneof:
WIDEVINE
PLAYREADY

drm.system_id string RegisteredsystemIdfortheDRMsystem.

tracks.pssh arrayofJSONstruct AlistofPSSH,oneperDRMsystem.

tracks.pssh.drm_ string TheDRMsystemforaspecificpieceofPSSH


type

tracks.pssh.data Base64encodedstring PSSH(protectionsystemspecificheader)data.


ThePSSHdataisuniquepertrack.

tracks.key_id Base64encodedstring Uniqueidentifierforthekey.



Binary,16bytes

tracks.type Oneof: Identifiesthetracktypeencryptedwiththiskey.


HD Thesevaluesareextractedfromtherequest.
SD
AUDIO

tracks.key Base64encodedstring Contentkey.Ifthesession_keyisspecified,the


contentkeyisAESECBencryptedwiththe
Binary,16bytes sessionkey.Thesessionkeyisgeneratedbythe
DRMserverandencryptedwiththecontent
providerspublickeyusingRSAOAEP(sha1,
mgf1sha1).TheencryptedkeyisBase64encoded.


GoogleConfidential Page8of14
already_used Boolean Settotrueifthekey_idwaspreviouslyissued.
Thiscanhappenifapreviouskeyrequestfromthe
samesignerwiththesamecontent_idand
track_typewassent.

Signing the response


GeneratetheJSONstring.
Json::StyledWriterwriter
std::stringclear_message=writer.write(root)

Signthemessage.
RSAPSS

Status codes

Code Description

OK Success.

SIGNATURE_FAILED Theserverwasunabletoauthenticatethemessage.Perhaps:
Thespecified<signer>isunknown
The<signature>wasnotspecified,butisrequiredinthis
case.

CONTENT_ID_MISSING <content_id>fieldismissingintherequest.

POLICY_UNKNOWN Thespecified<policy>wasnotfoundforthis<signer>.

TRACK_TYPE_MISSING <tracks.type>ismissingintherequest.

TRACK_TYPE_UNKNOWN Thespecified<tracks.type>isnotoneoftheallowedvalues.

MALFORMED_REQUEST Therequestisnotformattedcorrectly.

ACCESS_DENIED


GoogleConfidential Page9of14

PSSH
BelowistheWidevinePSSHformatforcontentproviderswhowishtosynthesisthePSSH
ratherthanusingtheonesreturnedbytheAPI.Thestructurebelowisaprotocolbuffer(see
https://developers.google.com/protocolbuffers/
).Theprocessis:
1)Buildtheprotocolbuffermessagebelow.
2)Serializethemessagetobytes.
3)Base64encodethebytes.


message
WidevineCencHeader{

enum
Algorithm{
UNENCRYPTED=
0

AESCTR=
1

}

optional
Algorithmalgorithm=
1


repeated
byteskey_id=
2



//Contentprovidername.

optional

string
provider=
3



//Acontentidentifier,specifiedbycontentprovider.

optional
bytescontent_id=
4



//Tracktype.AcceptablevaluesareSD,HDandAUDIO.Usedto
//differentiate

contentkeysusedbyanasset.

optional

string
track_type_deprecated=
5



//Thenameofaregisteredpolicytobeusedforthisasset.

optional

string
policy=
6



//
Cryptoperiodindex,formediausingkeyrotation.

optionaluint32
crypto_period_index=
7


//Optionalprotectedcontextforgroupcontent.Thegrouped_licenseisa
//serializedSignedMessage.

optionalbytes
grouped_license=
8



//Protectionschemeidentifyingtheencryptionalgorithm.
//Representedasoneofthefollowing4CCvalues:
//'cenc'(AESCTR),'cbc1'(AESCBC),
//'cens'(AESCTRsubsample),'cbcs'(AESCBCsubsample).
optionaluint32
protection_scheme=
9



//Optional.Formediausingkeyrotation,thisrepresentstheduration
//ofeachcryptoperiodinseconds.
optionaluint32
crypto_period_seconds=
10

}


GoogleConfidential Page10of14
PSSH in the MPD

Incompliancewith
DASHIFInteroperabilityPoints
,WidevinesupportsinsertionofthePSSHin
theDASHMPDfile.

ThePSSHbox,includingitsheader,mustbebase64encodedandplacedinthe<cenc:pssh>
elementnestedunderthe<ContentProtection>element.Seetheexamplebelow:

<AdaptationSetmimeType="audio/mp4">
<ContentProtection
schemeIdUri=
urn:uuid:edef8ba979d64acea3c827dcd51d21ed
">
<cenc:pssh>AAAANHBzc2gAAAAA7e+</cenc:pssh>
</ContentProtection>


GoogleConfidential Page11of14
Test Player
Tohelpintegrationandverification,thefollowingcanbeusedtoplaybackWidevineCENC
content:

Demo URLs for players


http://shakaplayerdemo.appspot.com/

Content URL
http://storage.googleapis.com/wvmedia/cenc/tears.mpd

WidevinehaspublishedanopensourceHTML5DASHplayer,availableat:

githubsite:
https://github.com/google/shakaplayer
changelog: https://github.com/google/shakaplayer/blob/master/CHANGELOG.md
hosteddemo: http://shakaplayerdemo.appspot.com/
hostedcopyofdocumentation: http://shakaplayerdemo.appspot.com/docs/index.html
hostedcopyofthefinaltutorialfromthedocs:
http://turtletube.appspot.com/


GoogleConfidential Page12of14
Appendix
Sample Request
Provider:widevine_test
ContentID:fkj3ljaSdfalkr3j
Policy:emptystring

Hereisthecommandtoobtainkeysforthissampleasset:

wgetO/tmp/keypostdata'{"request":
"ewogICJjb250ZW50X2lkIjogIlptdHFNMnhxWVZOa1ptRnNhM0l6YWc9PSIsCiAgInRyYWNrcyI6I
FsKICAgIHsgInR5cGUiOiAiU0QiIH0sCiAgICB7ICJ0eXBlIjogIkhEIiB9LAogICAgeyAidHlwZSI
6ICJBVURJTyIgfQogIF0sCiAgImRybV90eXBlcyI6IFsgIldJREVWSU5FIiBdLAogICJwb2xpY3kiO
iAiIgp9Cg==","signature":"kwVLL4xVh9mnlZlPqiEWN0E+FsvG0y+/oy451XXeIMo=",
"signer":"widevine_test"}'
http://license.uat.widevine.com/cenc/getcontentkey/widevine_test

Theexpectedresponseshouldbe:

{"response":"eyJzdGF0dXMiOiJPSyIsImRybSI6W3sidHlwZSI6IldJREVWSU5FIiwic3lzdGVtX
2lkIjoiZWRlZjhiYTk3OWQ2NGFjZWEzYzgyN2RjZDUxZDIxZWQifV0sInR
yYWNrcyI6W3sidHlwZSI6IlNEIiwia2V5X2lkIjoiQXBTNVdaMTFYZUs3OFAzS1A2WHF0dz09Iiwia
2V5IjoiTzlvdlFEUk1mZTloUWllNXdQQStKZz09IiwicHNzaCI6W3siZHJ
tX3R5cGUiOiJXSURFVklORSIsImRhdGEiOiJDQUVTRUFLVXVWbWRkVjNpdS9EOXlqK2w2cmNhRFhkc
FpHVjJhVzVsWDNSbGMzUWlFR1pyYWpOc2FtRlRaR1poYkd0eU0yb3FBbE5
FTWdBPSJ9XX0seyJ0eXBlIjoiSEQiLCJrZXlfaWQiOiI2MmRxdThzMFhwYTd6MkZtTVBHajJnPT0iL
CJrZXkiOiJFQXRzSUpRUGQ1cEZpUlVyVjlMYXl3PT0iLCJwc3NoIjpbeyJ
kcm1fdHlwZSI6IldJREVWSU5FIiwiZGF0YSI6IkNBRVNFT3RuYXJ2TE5GNld1ODloWmpEeG85b2FEW
GRwWkdWMmFXNWxYM1JsYzNRaUVHWnJhak5zYW1GVFpHWmhiR3R5TTJvcUF
raEVNZ0E9In1dfSx7InR5cGUiOiJBVURJTyIsImtleV9pZCI6Ilk1Mm9EUEk3VmZPNHlyUDJUUHBkO
Wc9PSIsImtleSI6IklwOWZLYlpENGdNQVN6REU2dk5JOUE9PSIsInBzc2g
iOlt7ImRybV90eXBlIjoiV0lERVZJTkUiLCJkYXRhIjoiQ0FFU0VHT2RxQXp5TzFYenVNcXo5a3o2W
GZZYURYZHBaR1YyYVc1bFgzUmxjM1FpRUdacmFqTnNhbUZUWkdaaGJHdHl
NMm9xQlVGVlJFbFBNZ0E9In1dfV0sImFscmVhZHlfdXNlZCI6dHJ1ZX0="}

Decodetheresponse
cutd:f2/tmp/key|base64di

{"status":"OK","drm":[{"type":"WIDEVINE","system_id":"edef8ba979d64acea3c827dc
d51d21ed"}],"tracks":[{"type":"SD","key_id":"ApS5WZ11XeK78P3KP6Xqtw==","key":"
O9ovQDRMfe9hQie5wPA+Jg==","pssh":[{"drm_type":"WIDEVINE","data":"CAESEAKUuVmdd
V3iu/D9yj+l6rcaDXdpZGV2aW5lX3Rlc3QiEGZrajNsamFTZGZhbGtyM2oqAlNEMgA="}]},{"type
":"HD","key_id":"62dqu8s0Xpa7z2FmMPGj2g==","key":"EAtsIJQPd5pFiRUrV9Layw==","p
ssh":[{"drm_type":"WIDEVINE","data":"CAESEOtnarvLNF6Wu89hZjDxo9oaDXdpZGV2aW5lX
3Rlc3QiEGZrajNsamFTZGZhbGtyM2oqAkhEMgA="}]},{"type":"AUDIO","key_id":"Y52oDPI7
VfO4yrP2TPpd9g==","key":"Ip9fKbZD4gMASzDE6vNI9A==","pssh":[{"drm_type":"WIDEVI

GoogleConfidential Page13of14
NE","data":"CAESEGOdqAzyO1XzuMqz9kz6XfYaDXdpZGV2aW5lX3Rlc3QiEGZrajNsamFTZGZhbG
tyM2oqBUFVRElPMgA="}]}],"already_used":true}

Signing
Thesignatureisgeneratedasfollows.
1. Taketherawvalueoftherequestfield(notinbase64encoding).
{"policy":"test_policy","tracks":[{"type":"SD"},{"type":"HD"},
{"type":"AUDIO"}],"content_id":"dGVzdF9pZF9GOUZQQzBOTw=="}

2. ComputeitsSHA1hash(thisexampleuseswidevine_testkeys).
306814a9_12abd779_de5dd373_89ca45d9_7328e89c

3. EncryptthehashwithAESCBC.Theresultisthesignature:
46f1ee6e3660acb081106c78e45e190464d87e5f8f7c79143c34da0308ec4bfc

4. Base64encodethesignature:
RvHubjZgrLCBEGx45F4ZBGTYfl+PfHkUPDTaAwjsS/w=

5. Addsignaturetotherequest:
{"request":
"eyJwb2xpY3kiOiAidGVzdF9wb2xpY3kiLCAidHJhY2tzIjogW3sidHlwZSI6ICJTRCJ9LCB
7InR5cGUiOiAiSEQifSwgeyJ0eXBlIjogIkFVRElPIn1dLCAiY29udGVudF9pZCI6ICJkR1Z
6ZEY5cFpGOUdPVVpRUXpCT1R3PT0ifQ==",
"signer":"widevine_test",
"signature":"RvHubjZgrLCBEGx45F4ZBGTYfl+PfHkUPDTaAwjsS/w="}

Forintegrationtests,youcanusewidevine_testasthesigner.ItsAESkeyis
0x1a,0xe8,0xcc,0xd0,0xe7,0x98,0x5c,0xc0,
0xb6,0x20,0x3a,0x55,0x85,0x5a,0x10,0x34,
0xaf,0xc2,0x52,0x98,0x0e,0x97,0x0c,0xa9,
0x0e,0x52,0x02,0x68,0x9f,0x94,0x7a,0xb9
TheIVis
0xd5,0x8c,0xe9,0x54,0x20,0x3b,0x7c,0x9a,
0x9a,0x9d,0x46,0x7f,0x59,0x83,0x92,0x49


GoogleConfidential Page14of14

You might also like