VideoHelp Forum



Support our site by donate $5 directly to us Thanks!!!

Try StreamFab Downloader and download streaming video from Netflix, Amazon!



+ Reply to Thread
Page 2 of 4
FirstFirst 1 2 3 4 LastLast
Results 31 to 60 of 91
  1. ignore that error, theres a few sites that use both the kid and the content id in the pssh.
    Quote Quote  
  2. Originally Posted by ElCap View Post
    ignore that error, theres a few sites that use both the kid and the content id in the pssh.
    understood....
    Last edited by gx3541; 16th Apr 2022 at 08:36. Reason: update
    Quote Quote  
  3. Sokmil authorization token is single use - generated in the request to 'puchase_auth'.
    Generate a new one and use it with the above info
    Quote Quote  
  4. BOTH ERROR
    Error 404: {"errors":[{"code":"2102","message":"Invalid auth token"}]}


    Last edited by gx3541; 16th Apr 2022 at 08:34. Reason: private
    Quote Quote  
  5. copy only authorization: Bearer eyJ0e...
    on headers section and untick cache
    (fresh value, this has expired)
    Quote Quote  
  6. Code:
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0IjoidHZvZCIsIm0iOiIxMDI5OTY4IiwiaWF0IjoxNjUwMTExMDkwLCJleHAiOjE2NTAyMDEwOTAsImp0aSI6ImNWTXpOMDF5WmpGdWRWRk1lRFZyTnc9PSJ9.bBvpM96rarnHQgvMa4ZWOu1c46PGv_iO29cYAQGarIUbajxybZO16Yy67lF9zk4opKbYlm0r6XY3NKWpYkeo3w
    this token is a single use token. if you try to take it from the license request, the browser has already used it so it wont work anymore.
    you need to generate it again by resending the request with url "https://www.sokmil.com/purchase_auth/"

    anyways, heres the decryption key for that video
    Code:
    --key 179bcb6d680d4b3899d4364576c75bb3:7dabb2224df1b1940278534c9245ccd6
    Quote Quote  
  7. oh i see
    i got it
    thank you so much ElCap & lomero
    Quote Quote  
  8. I solve it myself, thank you guys.
    Last edited by Wallace42; 22nd May 2022 at 06:02.
    Quote Quote  
  9. Originally Posted by rajhlinux View Post
    Originally Posted by ridibunda View Post
    Single mp4-files incoming (no init mp4. A mp4 file for each resolution and for each audio track):

    If you don't like my posts, add me to your ignore list.
    Udemy.com (World's largest online learning platform) does not have PSSH or KID in the ".mpd" file, it was really tricky to find it. since 99% of the internet widevine drm places it on the ".mpd" file, udemy.com puts it on the init.mp4

    I was able to get the kid from init.mp4 but was kinda confused on how to properly get pssh from those weird online converter tools with so many boxes and options that needs to be filled out...

    Thanks to "[ss]vegeta" I was able to get the system ID and Key ID...

    Image
    [Attachment 64024 - Click to enlarge]


    Anyways I was able to get the PSSH: AAAAMnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABISEHUXX0 puHECllyc8O0EzkkY=

    From this Key ID: 75175f4a6e1c40a597273c3b41339246

    and I got these three decryption keys from the CDM:

    1) aefc537bda2a545a80d72d93824ffcc9:32fccf818a6e210d8 ef1acec269deb6d
    2) d4d019341ba95d60be4b560e6e877ebd:87651d63fa5267667 2a714815c64f5d9
    3) 32ef1e4098665cfbb042d712b6ec527f:33750ba44971a46f9 318a5984eb74769

    oddly enough, none of those decryption keys have a matching default key id: "75175f4a6e1c40a597273c3b41339246"

    regardless of the fact, I tried decrypting some videos and it did not work...

    Hello good day!

    Could you pass details on how to get to init.mp4 in the browser?
    Quote Quote  
  10. Member
    Join Date
    Feb 2022
    Location
    Search the forum first!
    Search PM
    Originally Posted by elfoeda View Post
    Could you pass details on how to get to init.mp4 in the browser?
    Just your lucky day! I spent yesterday playing with mp4dump and produced this:-

    Code:
    import subprocess, os
    from getPSSH import return_pssh
    import fnmatch
    
    
    '''This program will find a Key_Id and a pssh from an mpd url by using mp4dump to extact the key_ID from the audio stream
        NOTE: this program deletes all m4a files in the current directory!!
    '''
    
    def initialize():
        
        currentFile = __file__
        realPath = os.path.realpath(currentFile)
        dirPath = os.path.dirname(realPath)
        #FInput_audio = dirPath + '/test.faudio=128000.m4a'
    
    def get_m4a():
        global FInput_audio
        mpd_url = input("MPD: \n>")
        os.system(f"yt-dlp -f 'ba'  --allow-u --test --no-warnings '{mpd_url}'  >/dev/null 2>&1")
        for file in os.listdir('.'):
            if fnmatch.fnmatch(file, '*.m4a'):
                FInput_audio = file
                print(f"\n[info] An m4a file has been downloaded as  '{FInput_audio}'")
        
    
    
    
    def get_kid():  
        global KID_video
        KID = ''
    
        def find_str(s, char):
            index = 0
            if char in s:
                c = char[0]
                for ch in s:
                    if ch == c and s[index:index + len(char)] == char:
                        return index
                    index += 1           
            return -1
    
    
        mymp4dump = subprocess.Popen([mp4dumpexe, FInput_audio], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
        mymp4dump = str(mymp4dump.stdout.read())
        A = find_str(mymp4dump, 'key_ID ') # space after ID is important otherwise 'key_IDs' gets returned
        KID = mymp4dump[A:A + 45].replace('key_ID = ', '').replace('[', '').replace(']', '').replace(' ', '').replace('-','')
        KID = KID.upper()
        KID_video = KID[0:8] + '-' + KID[8:12] + '-' + KID[12:16] + '-' + KID[16:20] + '-' + KID[20:32]
        return KID_video
    
    def cleanup():
        try:
            os.system("rm *.m4a .*m4a >/dev/null 2>&1")
        except:
            pass
    
    
    
    
    global mp4dumpexe
    global FInput_audio
    mp4dumpexe = "mp4dump"
    currentFile = __file__
    realPath = os.path.realpath(currentFile)
    dirPath = os.path.dirname(realPath)
    
    
    get_m4a()
    print(f"\n\nkey_ID: {get_kid()}")
    print(return_pssh(KID_video))
    print("\n\n[info] Done.")
    cleanup()
    It dumps Default_KID and calculates pssh from reading the first audio fragment from an mpd link. Copy code and rename as anything you like - such as keyIdDump.py ; run with 'python3 keyIdDump.py'.

    Works fine on my Linux system; Windoze may need .exe added to yt-dlp and mp4dump. And in cleanup() 'rm' changes to 'del' in windoze.

    Interesting find was
    Code:
    yt-dlp --allow-u -f 'ba' --test <mpd url>
    returns a single fragment.

    The image shows rte.ie giving up its key_ID and pssh

    Image
    [Attachment 66990 - Click to enlarge]


    Acknowledgement: I got a lot of help from narrowvine-reborn code by Vankon (I wonder is he still is..?); although it should now be named Narrowvine-Exhumed!
    Last edited by A_n_g_e_l_a; 26th Sep 2022 at 10:01. Reason: typos
    Quote Quote  
  11. Thanks for sharing and for the many help!
    Quote Quote  
  12. Originally Posted by A_n_g_e_l_a View Post
    It dumps Default_KID and calculates pssh from reading the first audio fragment from an mpd link. Copy code and rename as anything you like - such as keyIdDump.py ; run with 'python3 keyIdDump.py'... Works fine on my Linux system; Windoze may need .exe added to yt-dlp and mp4dump. And in cleanup() 'rm' changes to 'del' in windoze.
    Could be better if you explained it a little bit more clearly for non-experts.

    I changed "rm" to "del". I have yt-dlp.exe and mp4dump under the same folder. I have Python 3.10.1 installed.

    The result is: ModuleNotFoundError: No module named 'getPSSH'

    Is there a line we should modify for each case? How to install all dependecies, etc?
    Quote Quote  
  13. Member
    Join Date
    Feb 2022
    Location
    Search the forum first!
    Search PM
    Originally Posted by ridibunda View Post

    Could be better if you explained it a little bit more clearly for non-experts.
    Me non-expert too; me think a bit, select parts of other people's code and hack!
    Originally Posted by ridibunda View Post
    Is there a line we should modify for each case? How to install all dependencies, etc?
    Bloomin' Norah! Yes of course!! My error - sorry!!
    I'd been playing around tarting it up and produced a few versions and I thought I had an early all in one - clearly there IS a dependency to add. Here is a python file called 'getPSSH.py':-

    Code:
    import base64
    
    def get_pssh(keyId):
        array_of_bytes = bytearray( b'\x00\x00\x002pssh\x00\x00\x00\x00')
        array_of_bytes.extend(bytes.fromhex("edef8ba979d64acea3c827dcd51d21ed"))
        array_of_bytes.extend(b'\x00\x00\x00\x12\x12\x10')
        array_of_bytes.extend(bytes.fromhex( keyId.replace("-", "")))
        return base64.b64encode(bytes.fromhex(array_of_bytes.hex()))
    
    # entry call
    def return_pssh(kid):
        kid = kid.replace('-', '')
        assert len(kid) == 32 and not isinstance(kid, bytes), "wrong KID length"
        return ("PSSH {}".format(get_pssh(kid).decode('utf-8')))
    Put it in the same folder and you should be good to go.

    As regards to help - what can I say? You run the program with 'python keydump.py' or whatever you named it and enter the mpd when asked and press return. The output will look something like this:-
    Image
    [Attachment 67014 - Click to enlarge]

    I haven't used windoze for ages and really cannot give advice on conversions _ I am sure a bright chap like you will manage.

    I've created a zip as the easier option: https://anonfiles.com/j1Fcj4A2y2/keydump_zip
    Last edited by A_n_g_e_l_a; 28th Sep 2022 at 06:07. Reason: added zip file of complete code
    Quote Quote  
  14. It's worth pointing out that license servers often have a custom PSSH implementation thus making it impossible to generate the correct PSSH from a KID. Using a script like this on a custom implementation is a quick way to get your CDM banned.

    An example of this is the Channel 4 PSSH - https://github.com/Diazole/c4-dl/blob/master/c4-dl.py#L254. Their implementation requires the provider to be set to "rbmch4tv" and the policy needs to be an empty string.
    Quote Quote  
  15. Member
    Join Date
    Feb 2022
    Location
    Search the forum first!
    Search PM
    Originally Posted by Diazole View Post
    An example of this is the Channel 4 PSSH - https://github.com/Diazole/c4-dl/blob/master/c4-dl.py#L254. Their implementation requires the provider to be set to "rbmch4tv" and the policy needs to be an empty string.
    Yes, I saw your implementation supposing channel 4 are a special case having 'Red Bee Media Channel 4 TV' type ident of their own.

    And running a channel4 pssh with rbmch4tv encoded through https://tools.axinom.com/decoders/PsshBox gives this:-
    Image
    [Attachment 67016 - Click to enlarge]


    says
    Provider
    rbmch4tv
    Warning! This field is deprecated. Remove it
    .

    In my version it is removed.
    So no panic; and no to CDM's being declared dead I think.
    Quote Quote  
  16. Just because a field is deprecated doesn't mean it should be removed. It's what C4 use to generate the PSSH so you should too, otherwise you're making yourself stand out.
    Quote Quote  
  17. Member
    Join Date
    Feb 2022
    Location
    Search the forum first!
    Search PM
    Originally Posted by Diazole View Post
    Just because a field is deprecated doesn't mean it should be removed. It's what C4 use to generate the PSSH so you should too, otherwise you're making yourself stand out.
    Possibly but think on the variations of web-browser that exist and does the decoding using their own javascript engine. I'm sure there will be some that produce enough variations in response so that CH4 is a little lenient.

    I just used a short form pssh against all 4 and got a set of keys. Not the same endpoint you are using though.

    Have you thought Channel4 may notice your calls because you are using a deprecated method?

    PS
    Is it old Vine Trimmer code you've used as your base?
    Last edited by A_n_g_e_l_a; 28th Sep 2022 at 08:36. Reason: clarification of language and spelling! plus a PS
    Quote Quote  
  18. Member
    Join Date
    Aug 2022
    Location
    Portugal
    Search Comp PM
    Topic
    Last edited by jonatasants; 29th Oct 2022 at 13:07.
    Quote Quote  
  19. Originally Posted by A_n_g_e_l_a View Post
    Have you thought Channel4 may notice your calls because you are using a deprecated method?
    I don't get what you're getting at here? C4 literally use this field themselves. Why would making your own custom PSSH init data be better than using the original PSSH generated by the provider? Have you considered that the proto C4 uses is older than the one Axinom uses?

    Originally Posted by A_n_g_e_l_a View Post
    PS
    Is it old Vine Trimmer code you've used as your base?
    I wrote the script myself, it's not based off anything.
    Quote Quote  
  20. Member
    Join Date
    Feb 2022
    Location
    Search the forum first!
    Search PM
    Originally Posted by Diazole View Post
    I don't get what you're getting at here? C4 literally use this field themselves. Why would making your own custom PSSH init data be better than using the original PSSH generated by the provider? Have you considered that the proto C4 uses is older than the one Axinom uses?
    .
    Axinom is an industry tool.
    What gets returned to channel4 during the license interactions is wholly determined by the browser's JavaScript engine - which you are emulating in your code. Your emulation I assume is based on a copy of the interactions from some browser under your scrutiny with C4. Pywidevine emulation of a browser JavaScript engine has the possibility to be 'strict or lenient' - see below, so I assume the browser JavaScript engine can be strict or lenient too depending on which browser.

    The following is some rubrik taken from the python pywidevine module
    [Strict mode (strict=True)]

    Supports the following forms of input data in either Base64 or Bytes form:
    - Full PSSH mp4 boxes (as defined by pymp4 Box).
    - Full Widevine Cenc Headers (as defined by WidevinePsshData proto).

    [Lenient mode (strict=False, default)]

    If the data is not supported in Strict mode, and is assumed not to be corrupt or
    parsed incorrectly, the License Server likely accepts a custom init_data value
    during a License Request call. This is uncommon behavior but not out of realm of
    possibilities. For example, Netflix does this with it's MSL WidevineExchange
    scheme.
    Strict mode follows pymp4 Box. And that module has a range of pssh boxes that are acceptable.
    As I said it is unlikely that channel 4 need its ident in the pssh.

    This is even more probable as:-
    • C4 does not supply a pssh, only a KID
    • The pssh is only used to initialize a widevine session
    • remarkably, with the script I have, pssh is a fixed value (not dynamic) string from some other C4 program; it still produces correct keys - further evidence of no scrutiny of pssh!!
    So my conclusions are that the pssh dump script provided above, and in so many other guises elsewhere, is not going to get anyone's CDM revoked. And the sky isn't falling in.
    Quote Quote  
  21. Pywidevine emulation of a browser JavaScript engine has the possibility to be 'strict or lenient' - see below, so I assume the browser JavaScript engine can be strict or lenient too depending on which browser.
    ???
    That is probably just some option for convenience defined by the dev of that module. Nothing like that happens in the browser EME.

    Generating your own PSSH probably would not get your L3 key blacklisted but it is a bad practice nonetheless. The original PSSH provided by the provider should be utilized because it is their own implementation.
    Quote Quote  
  22. Originally Posted by gx3541 View Post
    BOTH ERROR
    Error 404: {"errors":[{"code":"2102","message":"Invalid auth token"}]}


    Originally Posted by ElCap View Post
    Code:
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0IjoidHZvZCIsIm0iOiIxMDI5OTY4IiwiaWF0IjoxNjUwMTExMDkwLCJleHAiOjE2NTAyMDEwOTAsImp0aSI6ImNWTXpOMDF5WmpGdWRWRk1lRFZyTnc9PSJ9.bBvpM96rarnHQgvMa4ZWOu1c46PGv_iO29cYAQGarIUbajxybZO16Yy67lF9zk4opKbYlm0r6XY3NKWpYkeo3w
    this token is a single use token. if you try to take it from the license request, the browser has already used it so it wont work anymore.
    you need to generate it again by resending the request with url "https://www.sokmil.com/purchase_auth/"

    anyways, heres the decryption key for that video
    Code:
    --key 179bcb6d680d4b3899d4364576c75bb3:7dabb2224df1b1940278534c9245ccd6
    I am using "widevine_keys" and am getting similar errors with a site that uses a very similar system. I'm not fully understanding what it means to "generate it again by resending the request with url [https://www.videx.jp/purchase_auth/]"

    I've got this MPD: https://idc105.candl.jp/watch/?a=R3rsfb00-Nbkq90skbu7jsoDa89tEjcx.pX1dnkrDVg&h=105&f=c...ismv&style.mpd
    And this license URL: https://license.candl.jp/videx/widevine/

    I used the KID in the MPD to generate this PSSH: AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEI1dpb WV1EJ0ppVHTYZGVLVI49yVmwY=

    Here's the header information I generated

    Code:
    import requests
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:106.0) Gecko/20100101 Firefox/106.0',
        'Accept': '*/*',
        'Accept-Language': 'en-US,en;q=0.5',
        # 'Accept-Encoding': 'gzip, deflate, br',
        'Referer': 'https://www.videx.jp/',
        'authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1c2VySWQiOjExNjEyNzYsImxpY2Vuc2UiOiJ2b2QiLCJraWQiOiI4ZDVkYTViNTk1ZDQ0Mjc0YTY5NTQ3NGQ4NjQ2NTRiNSIsImV4cGlyZSI6MTY2ODE4MzIwOSwibG9nSG9sZGVySWQiOjEwNSwiaWF0IjoxNjY3NjE5NjU3LCJleHAiOjE2Njc2MTk3MTcsImp0aSI6Ik56Wmhibk5SVFdkTVUwVmlZMUpVVWc9PSJ9.Qlneqs39oRGxjC0u5_qipAfCCQo0QHsUCf0A5uKgSzapAYMZyskGw5lqjmsj-w9KTWknRa-oCQz4eH7D01S6EA',
        'Origin': 'https://www.videx.jp',
        'DNT': '1',
        'Connection': 'keep-alive',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'cross-site',
        'Content-Type': 'application/x-www-form-urlencoded',
    }
    So from what I'm understanding, I need to replace the string after " 'authorization': 'Bearer" with a new string? How exactly do I generate that with https://www.videx.jp/purchase_auth/?

    Help would be greatly appreciated.
    Quote Quote  
  23. on headers put only
    'authorization': 'Bearer eyJ0eXAiOiJKV1QiL.......
    Quote Quote  
  24. Originally Posted by lomero View Post
    on headers put only
    'authorization': 'Bearer eyJ0eXAiOiJKV1QiL.......
    Were you able to decrypt from that provider? I'm also trying to decrypt a video from the same source, I'm using fresh Bearer and I get an ERROR with no explanation.
    Image
    [Attachment 67511 - Click to enlarge]
    Quote Quote  
  25. No, I have tried the advice above about the headers.

    This is what my headers.py looks like

    Image
    [Attachment 67513 - Click to enlarge]


    When I run it, this is what I get

    Image
    [Attachment 67515 - Click to enlarge]


    While the streaming video is paused in my browser, I tried opening https://www.videx.jp/purchase_auth/ in another tab. It downloads a text file which contains a string that starts with "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9". I tried copying that new string into my headers.py and running the terminal again, but I get the same error.

    So I'm still stuck.
    Quote Quote  
  26. you need to resend the request for "https://www.videx.jp/purchase_auth/" with all the information from dev tools.
    there are a number of ways of doing this:
    - copy as curl (cmd) (use cmd prompt)
    - copy as powershell (use powershell window)
    - copy as fetch (use console window)
    - replay XHR

    response is your new authorization bearer token

    it could have a short expiry too (i forget) so try to use it quickly
    Quote Quote  
  27. I can confirm it has a short expiry time like 30-60 sec. Even I enter the new token on time it still gives the error message. Should we pass more data other than headers for this provider? I'm out of ideas.
    Quote Quote  
  28. ElCap's explanation did help me understand resending the request. I copied "https://www.videx.jp/purchase_auth/" as curl and ran it in the command prompt, which did spit out a new "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9". I copied that into my headers.py and re-ran widevine_keys. But it's also still not working for me. I either get the same original error

    Code:
    license response status: <Response [401]>
    server reports: {"errors":[{"code":"2104","message":"Invalid auth token"}]}
    server did not issue license, make sure you have correctly pasted all the required headers in the headers.py. Also check json/raw params of POST request.
    Or sometimes I get

    Code:
    license response status: <Response [400]>
    server reports: {"errors":[{"code":"2110","message":"License server error"}]}
    server did not issue license, make sure you have correctly pasted all the required headers in the headers.py. Also check json/raw params of POST request.
    I've timed myself and from the point where I run the "purchase_auth" curl to receiving the error, it's less than 15 seconds. I even tried it using all the headers generated by "https://license.candl.jp/videx/widevine/" and not just "'authorization': 'Bearer eyJ0eXAiOiJKV1QiL......." but that didn't work either.
    Quote Quote  
  29. the license server response is in json, so you cant use getwvkeys or cdrm-project via the browser, you have to use a script that will parse out the license response.
    Quote Quote  
  30. Member
    Join Date
    Dec 2020
    Location
    Croatia
    Search PM
    i'll hijack this thread for a second:

    i've been looking to figure out how to automate downloading from ctv.ca (supplying just the episode/movie link) so i can copy a bunch of episode sinto a txt file and then set them to be downloaded without any other input

    the final step - pssh - is giving me trouble - wks errors out
    i've used angela's code from this thread (rearranged for my own script) and I do get a kid and a pssh but the pssh I get is shorter than the one from EME logger which works:
    AAAAMnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABISEOBxMk lNTaXhn4z5jG11vxg=
    vs
    AAAAUnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADIIARIQ4H EySU1NpeGfjPmMbXW/GBoJYmVsbG1lZGlhIhFmZi1mMmY2N2UzMi04Njg3NQ==

    so, does anyone know what the deal is? i mean eme is obviously doing something right, can it be incorporated into a script that runs by itself? i've looked at the code and it's beyond me.
    Quote Quote  



Similar Threads

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