From 104af51a208e13398f605e4cc8b849f02e84a2d2 Mon Sep 17 00:00:00 2001 From: Matthew Broadway Date: Thu, 17 Jun 2021 20:32:43 +0100 Subject: [PATCH] added compatability wrapper for pbkdf2_sha1 --- test/test_cookies.py | 41 ++++++++++++++++++++++++++++------------- youtube_dl/cookies.py | 23 ++++++++++++++++++++--- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/test/test_cookies.py b/test/test_cookies.py index 091326012..f1f32923d 100644 --- a/test/test_cookies.py +++ b/test/test_cookies.py @@ -1,44 +1,51 @@ +import sys import unittest from datetime import datetime, timezone from youtube_dl import cookies from youtube_dl.cookies import LinuxChromeCookieDecryptor, WindowsChromeCookieDecryptor, CRYPTO_AVAILABLE, \ - MacChromeCookieDecryptor, Logger, parse_safari_cookies + MacChromeCookieDecryptor, Logger, parse_safari_cookies, pbkdf2_sha1, PBKDF2_AVAILABLE class MonkeyPatch: - def __init__(self, module, name, temp_value): + def __init__(self, module, temporary_values): self._module = module - self._name = name - self._temp_value = temp_value - self._backup_value = None + self._temporary_values = temporary_values + self._backup_values = {} def __enter__(self): - self._backup_value = getattr(self._module, self._name) - setattr(self._module, self._name, self._temp_value) + for name, temp_value in self._temporary_values.items(): + self._backup_values[name] = getattr(self._module, name) + setattr(self._module, name, temp_value) def __exit__(self, exc_type, exc_val, exc_tb): - setattr(self._module, self._name, self._backup_value) + for name, backup_value in self._backup_values.items(): + setattr(self._module, name, backup_value) class TestCookies(unittest.TestCase): + @unittest.skipIf(not PBKDF2_AVAILABLE, 'PBKDF2 not available') def test_chrome_cookie_decryptor_linux_derive_key(self): key = LinuxChromeCookieDecryptor.derive_key(b'abc') assert key == b'7\xa1\xec\xd4m\xfcA\xc7\xb19Z\xd0\x19\xdcM\x17' + @unittest.skipIf(not PBKDF2_AVAILABLE, 'PBKDF2 not available') def test_chrome_cookie_decryptor_mac_derive_key(self): key = MacChromeCookieDecryptor.derive_key(b'abc') assert key == b'Y\xe2\xc0\xd0P\xf6\xf4\xe1l\xc1\x8cQ\xcb|\xcdY' + @unittest.skipIf(not PBKDF2_AVAILABLE, 'PBKDF2 not available') def test_chrome_cookie_decryptor_linux_v10(self): - with MonkeyPatch(cookies, '_get_linux_keyring_password', lambda *args, **kwargs: b''): + with MonkeyPatch(cookies, {'_get_linux_keyring_password': lambda *args, **kwargs: b''}): encrypted_value = b'v10\xccW%\xcd\xe6\xe6\x9fM" \xa7\xb0\xca\xe4\x07\xd6' value = 'USD' decryptor = LinuxChromeCookieDecryptor('Chrome') assert decryptor.decrypt(encrypted_value) == value + @unittest.skipIf(not PBKDF2_AVAILABLE, 'PBKDF2 not available') def test_chrome_cookie_decryptor_linux_v11(self): - with MonkeyPatch(cookies, '_get_linux_keyring_password', lambda *args, **kwargs: b''): + with MonkeyPatch(cookies, {'_get_linux_keyring_password': lambda *args, **kwargs: b'', + 'KEYRING_AVAILABLE': True}): encrypted_value = b'v11#\x81\x10>`w\x8f)\xc0\xb2\xc1\r\xf4\x1al\xdd\x93\xfd\xf8\xf8N\xf2\xa9\x83\xf1\xe9o\x0elVQd' value = 'tz=Europe.London' decryptor = LinuxChromeCookieDecryptor('Chrome') @@ -46,15 +53,16 @@ class TestCookies(unittest.TestCase): @unittest.skipIf(not CRYPTO_AVAILABLE, 'cryptography library not available') def test_chrome_cookie_decryptor_windows_v10(self): - with MonkeyPatch(cookies, '_get_windows_v10_key', - lambda *args, **kwargs: b'Y\xef\xad\xad\xeerp\xf0Y\xe6\x9b\x12\xc2= (3, 4) or CRYPTO_AVAILABLE + + +def pbkdf2_sha1(password, salt, iterations, key_length): + try: + from hashlib import pbkdf2_hmac + return pbkdf2_hmac('sha1', password, salt, iterations, key_length) + except ImportError: + try: + from Crypto.Protocol.KDF import PBKDF2 + from Crypto.Hash import SHA1 + return PBKDF2(password, salt, key_length, iterations, hmac_hash_module=SHA1) + except ImportError: + warnings.warn('PBKDF2 is not available. You must either upgrade to ' + 'python >= 3.4 or install the pycryptodome package') + return None + + def _decrypt_aes_cbc(ciphertext, key, initialization_vector=b' ' * 16): plaintext = aes_cbc_decrypt(bytes_to_intlist(ciphertext), bytes_to_intlist(key),