shaka-project / shaka-packager

A media packaging and development framework for VOD and Live DASH and HLS applications, supporting Common Encryption for Widevine and other DRM Systems.
https://shaka-project.github.io/shaka-packager/
Other
2k stars 510 forks source link

What is the exact algorithm behind the AES signature used when getting Widevine KID/KEY? #1295

Closed sh9351 closed 1 year ago

sh9351 commented 1 year ago

System info

Operating System: Windows 11 22H2 (Build 22621.2428) Shaka Packager Version: v2.6.1-634af65-release (latest)

Question

Hi. I'm interested in requesting the Widevine server for the KID/KEY, and then providing those values to Shaka Packager through the command line. However, when I make the request, the "signature" is required, but I can find absolutely no documentation about the exact algorithm behind it. (I'm currently trying to use Node.js to communicate with the Widevine server.) I also tried looking through the source, but no luck there too. The exact credentials I'm looking for are below: (they're the test credentials from the official documentation)

aes_signing_key: 1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f947ab9' aes_signing_iv: d58ce954203b7c9a9a9d467f59839249 key_server_url: https://license.uat.widevine.com/cenc/getcontentkey/widevine_test

It seems that in packager\media\base\widevine_key_source.cc:388 the GenerateSignature function generates the signature, but that function just SHA1 hashes the message, which is signed_request.request(). And I wasn't able to find any references on that. So, is there any open documentation on how the message is signed, or is there someone who can reverse the source code? (I'm a coding newbie, and I've only used Node.js in my whole life đŸ˜­)

Links

packager\media\base\widevine_key_source.cc:388 packager\media\base/request_signer.cc:39 Using Widevine Key Server

sh9351 commented 1 year ago

Here's the Node.js code I'm currently using:

const axios = require('axios')
const crypto = require('crypto')

const provider = 'widevine_test'
    , content_id = '1239'
    , aes_signing_key = '1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f947ab9'
    , aes_signing_iv = 'd58ce954203b7c9a9a9d467f59839249'

async function main() {
    const request = Buffer.from(JSON.stringify({
        content_id: Buffer.from(content_id).toString('base64'),
        drm_types: ['WIDEVINE'],
        tracks: [
            { type: 'AUDIO' },
            { type: 'SD' },
            { type: 'HD' },
            { type: 'UHD1' },
            { type: 'UHD2' }
        ]
    })).toString('base64')
    // Do the magic here
    const signature = signMessage(request, aes_signing_key, aes_signing_iv)
    const { data } = await axios.post(`https://license.uat.widevine.com/cenc/getcontentkey/${provider}`, {
        request,
        signature,
        signer: 'widevine_test'
    })
    console.log(JSON.parse(Buffer.from(data.response, 'base64')))
    // Extract KID/KEY
}

main()
cosmin commented 1 year ago

Please contact Widevine support for questions about how to interact with the Widevine license server https://support.google.com/widevine/troubleshooter/6027072