VideoHelp Forum
+ Reply to Thread
Results 1 to 7 of 7
Thread
  1. I'm a newbie,Currently trying to analyze onlyfans
    Based on my attempts and github project(of-drm:https://github.com/sim0n00ps/OF-DRM/blob/089b7402dc1f6240993255b0492795bcd1114be8/OF%2...elper.cs#L1199)

    Code:
                    var resp1 = PostData(licenceURL, drmHeaders, new byte[] { 0x08, 0x04 });
                    var certDataB64 = Convert.ToBase64String(resp1);
                    var cdm = new CDMApi();
                    var challenge = cdm.GetChallenge(pssh, certDataB64, false, false);
                    var resp2 = PostData(licenceURL, drmHeaders, challenge);
                    var licenseB64 = Convert.ToBase64String(resp2);
                    cdm.ProvideLicense(licenseB64);
                    List<ContentKey> keys = cdm.GetKeys();
    His drm logic is:
    There are two pssh in mpd
    The shorter pssh will generate fixed 0804 data through the generateRequest function
    Obtain the certificate by submitting 0804, and then submit the longer pssh to obtain the decryption key

    According to my learning in the forum, long pssh can be solved by pywidevine

    But using short pssh generate 0804 how to generate by code?

    I didn't find the relevant function in pywidevine

    hope to get help


    The simplest html code generated by 0804 is as follows

    HTML Code:
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
    </body>
    <script>
    
    
        const config = [{
            initDataTypes: ['cenc'],
            videoCapabilities: [{
                contentType: 'video/mp4;codecs=\"avc1.42E01E\"',
                robustness: "SW_SECURE_CRYPTO"
            }]
        }];
    
    
        navigator.requestMediaKeySystemAccess("com.widevine.alpha",
            config).then(
                function (keySystemAccess) {
                    var promise = keySystemAccess.createMediaKeys();
                    promise.then(
                        function (createdMediaKeys) {
                            m = function e(t) {
                                return atob(t)
                            }
                            function p(e) {
                                for (var t = m(e), n = new Uint8Array(t.length), i = 0; i < t.length; i++)
                                    n[i] = t.charCodeAt(i);
                                return n
                            }
                            var initData = p("AAAAUnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADIIARIQ8ZV53WEBxiMaR+Ox/cyuaxoMaW5rYWVudHdvcmtzIgozMzc5OTQ4ODA3KgJIRA==")
                            
                            var keySession = createdMediaKeys.createSession();
                            keySession.addEventListener('message', (message)=>{
                                console.log(message.message)
                            },
                                false);
                            return keySession.generateRequest('cenc', initData);
                        }
                    ).catch(
                        console.error.bind(console,
                            'Unable to create or initialize key session')
                    );
                }
            );
    
    
    </script>
    
    </html>
    -------------------------------------------------------------------------------------------------------

    Thanks to everyone for their generosity and selflessness, this is a very friendly and informative forum! I learned a lot of knowledge
    Quote Quote  
  2. Education Student (Grad.) CrymanChen's Avatar
    Join Date
    Apr 2022
    Location
    Mainland China
    Search Comp PM
    Url?
    twitter @Cryman_Chen
    email crymanchen@gmail.com
    Quote Quote  
  3. Originally Posted by CrymanChen View Post
    Url?
    Since it is a paid video, I have not found an address to test it.

    My goal is not to download the video, I am interested in the knowledge related to drm

    So my current question is about simulating the code [keySession.generateRequest('cenc', initData)] in other languages

    Give an example of the generation of 0804 in the html above

    HTML Code:
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
    
    </body>
    <script>
    
    
        const config = [{
            initDataTypes: ['cenc'],
            videoCapabilities: [{
                contentType: 'video/mp4;codecs=\"avc1.42E01E\"',
                robustness: "SW_SECURE_CRYPTO"
            }]
        }];
    
    
        navigator.requestMediaKeySystemAccess("com.widevine.alpha",
            config).then(
                function (keySystemAccess) {
                    var promise = keySystemAccess.createMediaKeys();
                    promise.then(
                        function (createdMediaKeys) {
                            m = function e(t) {
                                return atob(t)
                            }
                            function p(e) {
                                for (var t = m(e), n = new Uint8Array(t.length), i = 0; i < t.length; i++)
                                    n[i] = t.charCodeAt(i);
                                return n
                            }
                            var initData = p("AAAAUnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADIIARIQ8ZV53WEBxiMaR+Ox/cyuaxoMaW5rYWVudHdvcmtzIgozMzc5OTQ4ODA3KgJIRA==")
                            
                            var keySession = createdMediaKeys.createSession();
                            keySession.addEventListener('message', (message)=>{
                                console.log(message.message)   //0804
                            },
                                false);
                            return keySession.generateRequest('cenc', initData);
                        }
                    ).catch(
                        console.error.bind(console,
                            'Unable to create or initialize key session')
                    );
                }
            );
    
    
    </script>
    
    </html>
    This code calls keySession.generateRequest('cenc', initData), which will get 0804 in message.message
    Quote Quote  
  4. The long PSSH is used for Microsoft's PlayReady and then short one is for Google's Widevine (that's what you're going to want to use).

    The '08 04' (or CAQ= is base64) (or '\x08\x04' in python) is a fixed data value that can be sent to the same server (even same URL and 99% of the time even the same headers) from which you will receive your license.

    If you have a CDM, you can use pywidevine to retrieve the keys from the license returned by the server.
    Take this pywidevine example from their GitHub:
    Code:
    # prepare pssh
    pssh = PSSH("<Your PSSH>")
    
    # load device
    device = Device.load("<Your Widevine Device File>")
    
    # load cdm
    cdm = Cdm.from_device(device)
    
    # open cdm session
    session_id = cdm.open()
    
    # you could set the requested certificate here, which isn't normally needed as it's static most of the time.
    cdm.set_service_certificate(session_id, "<bytes>")
    
    # get license challenge
    challenge = cdm.get_license_challenge(session_id, pssh)
    
    # send license challenge (without license wrapping)
    licence = requests.post("https://...", data=challenge)
    licence.raise_for_status()
    
    # parse license challenge
    cdm.parse_license(session_id, licence.content)
    
    # print keys
    for key in cdm.get_keys(session_id):
        print(f"[{key.type}] {key.kid.hex}:{key.key.hex()}")
    
    # close session, disposes of session data
    cdm.close(session_id)
    If your license server (always a POST request) is not responding to your challenge in raw bytes or even denies your request, then you have to look at the server request and replace the challenge in the request as base64 and/or parse the output returned from the server (JSON) to retrieve the returned license in base64 (called 'license wrapping').
    Last edited by larley; 30th Jun 2024 at 04:23.
    Quote Quote  
  5. Originally Posted by larley View Post
    The long PSSH is used for Microsoft's PlayReady and then short one is for Google's Widevine (that's what you're going to want to use).

    The '08 04' (or CAQ= is base64) (or '\x08\x04' in python) is a fixed data value that can be sent to the same server (even same URL and 99% of the time even the same headers) from which you will receive your license.

    If you have a CDM, you can use pywidevine to retrieve the keys from the license returned by the server.
    Take this pywidevine example from their GitHub:
    Code:
    # prepare pssh
    pssh = PSSH("<Your PSSH>")
    
    # load device
    device = Device.load("<Your Widevine Device File>")
    
    # load cdm
    cdm = Cdm.from_device(device)
    
    # open cdm session
    session_id = cdm.open()
    
    # you could set the requested certificate here, which isn't normally needed as it's static most of the time.
    cdm.set_service_certificate(session_id, "<bytes>")
    
    # get license challenge
    challenge = cdm.get_license_challenge(session_id, pssh)
    
    # send license challenge (without license wrapping)
    licence = requests.post("https://...", data=challenge)
    licence.raise_for_status()
    
    # parse license challenge
    cdm.parse_license(session_id, licence.content)
    
    # print keys
    for key in cdm.get_keys(session_id):
        print(f"[{key.type}] {key.kid.hex}:{key.key.hex()}")
    
    # close session, disposes of session data
    cdm.close(session_id)
    If your license server (always a POST request) is not responding to your challenge in raw bytes or even denies your request, then you have to look at the server request and replace the challenge in the request as base64 and/or parse the output returned from the server (JSON) to retrieve the returned license in base64 (called 'license wrapping').
    Why am I so stupid?

    0804 is the default value!

    This has been bothering me for a week!!!

    Thanks!
    Quote Quote  
  6. Just be aware that '0804' will get you the service certificate, not the license.
    Quote Quote  
  7. Originally Posted by larley View Post
    Just be aware that '0804' will get you the service certificate, not the license.
    Thank you very much for your advice

    I have successfully achieved decryption

    According to practice, long pssh is not the correct key, short pssh is widevine decryption key

    You explained all my questions。

    Thank you very much for your selfless help!
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!