Decrypting And Combining .ts Audio Files with .m3u

2020-02-17 09:00发布

问题:

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=

回答1:

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.



回答2:

Recent versions of ffmpeg should be able to decrypt the AES-128 HLS streams. You don't need a webserver. If the m3u8 URIs/paths are wrong you can:

  • create a directory
  • copy the key to a key file, ie my.key, and place it in the dir. Note that keys can be rotated, if the playlist has multiple keys copy all of them to different files.
  • copy all .ts segments to the same dir
  • copy and edit the playlist.m3u8 and use just the filename(s) for the key(s) URI(s) and segments.
  • to obtain a single .ts file do:

    ffmpeg -i playlist.m3u8 -c copy output.ts
    
  • if you want just the audio stream without the .ts container you can extract it. Eg: assuming you have a single audio stream using the AAC codec run:

    ffmpeg -i playlist.m3u8 -map 0:a -c copy output.aac
    

This will extract the AAC stream to a file without re-encoding. If you want a codec different than your source you will have to re-encode.

If for some reason you have to use openssl to decrypt the segments keep in mind that if no IV is specified then the IV is equal to the segment's media sequence, ie. the first segment has IV=0, the second has IV=1 and so on. After decryption update the playlist to point the decrypted segments and remove the EXT-X-KEY line. If you go this route you don't even need ffmpeg to obtain a single .ts file as MPEG-TS is directly concatenable, ie. you can just use cat on the decrypted segments.