Skip to content

Commit

Permalink
[HLS] Fix decryption issues (#1117)
Browse files Browse the repository at this point in the history
* Unpad HLS fragments with PKCS#7 according to datatracker.ietf.org/doc/html/rfc8216
* media_sequence should only be incremented in for media fragments
* The native decryption should only be used if ffmpeg is unavailable since it is significantly slower. Closes #1086

Authored by: shirt-dev, pukkandan
  • Loading branch information
shirt-dev committed Sep 28, 2021
1 parent 80c360d commit 7687c8a
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 8 deletions.
3 changes: 2 additions & 1 deletion yt_dlp/downloader/fragment.py
Expand Up @@ -355,7 +355,8 @@ def decrypt_fragment(fragment, frag_content):
# not what it decrypts to.
if self.params.get('test', False):
return frag_content
return aes_cbc_decrypt_bytes(frag_content, decrypt_info['KEY'], iv)
decrypted_data = aes_cbc_decrypt_bytes(frag_content, decrypt_info['KEY'], iv)
return decrypted_data[:-decrypted_data[-1]]

return decrypt_fragment

Expand Down
20 changes: 13 additions & 7 deletions yt_dlp/downloader/hls.py
Expand Up @@ -9,6 +9,7 @@
from .external import FFmpegFD

from ..compat import (
compat_pycrypto_AES,
compat_urlparse,
)
from ..utils import (
Expand Down Expand Up @@ -68,14 +69,20 @@ def real_download(self, filename, info_dict):
man_url = urlh.geturl()
s = urlh.read().decode('utf-8', 'ignore')

if not self.can_download(s, info_dict, self.params.get('allow_unplayable_formats')):
if info_dict.get('extra_param_to_segment_url') or info_dict.get('_decryption_key_url'):
self.report_error('pycryptodome not found. Please install')
return False
can_download, message = self.can_download(s, info_dict, self.params.get('allow_unplayable_formats')), None
if can_download and not compat_pycrypto_AES and '#EXT-X-KEY:METHOD=AES-128' in s:
if FFmpegFD.available():
can_download, message = False, 'The stream has AES-128 encryption and pycryptodome is not available'
else:
message = ('The stream has AES-128 encryption and neither ffmpeg nor pycryptodome are available; '
'Decryption will be performed natively, but will be extremely slow')
if not can_download:
message = message or 'Unsupported features have been detected'
fd = FFmpegFD(self.ydl, self.params)
self.report_warning(
'%s detected unsupported features; extraction will be delegated to %s' % (self.FD_NAME, fd.get_basename()))
self.report_warning(f'{message}; extraction will be delegated to {fd.get_basename()}')
return fd.real_download(filename, info_dict)
elif message:
self.report_warning(message)

is_webvtt = info_dict['ext'] == 'vtt'
if is_webvtt:
Expand Down Expand Up @@ -232,7 +239,6 @@ def is_ad_fragment_end(s):
elif line.startswith('#EXT-X-DISCONTINUITY'):
discontinuity_count += 1
i += 1
media_sequence += 1

# We only download the first fragment during the test
if self.params.get('test', False):
Expand Down

1 comment on commit 7687c8a

@pukkandan
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closes #1087, not 1086 :(

Please sign in to comment.