Search code examples
encryptionffmpeg

Decrypting And Combining .ts Audio Files with .m3u8


I have a few thousand .ts AES-128 encrypted audio files with a .key and .m3u8 file.

The key file just contains a key comprised of 44 characters. The .m3ud files appears to be some type of playlist.

#EXTM3U
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:[port]/hls/keys/nax_9781843794066.key"
#EXTINF:10,
http://localhost:[port]/filesequence0000000.ts
#EXTINF:10,
etc...

Note that both the key URI and path to the .ts files is now wrong.

Looking around, it appears ffmpeg might work with this format. But I am unsure of the syntax.

How can I decrypt and combine these files?

I have been playing around with fixing the playlist syntax and figuring out how to use ffmpeg and got to.

ffmpeg -i nax_9781843794066.m3u8 -c copy output.ts
ffmpeg version N-77197-gdf2ce13 Copyright (c) 2000-2015 the FFmpeg developers
built with gcc 5.2.0 (GCC)
configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libdcadec --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
libavutil      55. 10.100 / 55. 10.100
libavcodec     57. 17.100 / 57. 17.100
libavformat    57. 19.100 / 57. 19.100
libavdevice    57.  0.100 / 57.  0.100
libavfilter     6. 20.100 /  6. 20.100
libswscale      4.  0.100 /  4.  0.100
libswresample   2.  0.101 /  2.  0.101
libpostproc    54.  0.100 / 54.  0.100
[hls,applehttp @ 0000003e6348a660] Error when loading first segment 'filesequence0000000.ts'
nax_9781843794066.m3u8: Invalid data found when processing input

filesequence0000000.ts is the first file, in the same folder. I cannot tell if this is some problem with the encryption or something else.

This is the key file, if it matters: MoOoNvcKlThWBm2T+VzYq9QKZLw7MFUqSyLYjiwquTQ=


Solution

  • I've had few free hours today and toyed with this. Long story short - that base64 key is AES encrypted. This additional encryption is done with key which is dynamically generated from device data... meaning that even if I have whole data folder from your device I wouldn't be able to decrypt it.

    Now, when you posses rooted device with offline data that's another matter - you can obviously inject your code to intercept key when it's decrypted so content can start playing... which is how I got it.

    When you have proper key, decryption and joining of *.ts files is trivial. I recommend that you use FFMPEG for this task, my C# code that I'm leaving for illustration works well works only in some cases (depending on how files are encoded):

    var folder = "path_to_folder";
    byte[] encryptionKey = File.ReadAllBytes(folder + "path_to_key.key");
    
    var outputFile = "c:\\i_love_you_guys.ts";
    using (FileStream outputFileStream = new FileStream(outputFile, FileMode.Create))
    {
        var files = Directory.GetFiles(folder, "*.ts");
        for (int i = 0; i < files.Length; i++)
        {
            byte[] encryptionIV = new byte[16];
            using (FileStream inputFileStream = new FileStream(files[i], FileMode.Open))
            {
                using (var aes = new AesManaged { Key = encryptionKey, IV = encryptionIV, Mode = CipherMode.CBC })
                using (var encryptor = aes.CreateDecryptor())
                using (var cryptoStream = new CryptoStream(inputFileStream, encryptor, CryptoStreamMode.Read))
                {
                    cryptoStream.CopyTo(outputFileStream);
                }
            }
        }
    }
    

    So, this turned out to be wild goose chase. What @aergistal says in his answer is completely valid as long as you have proper my.key. Thus focus on obtaining key in plain format and decryption will then be super easy.