mirror of
https://github.com/ytdl-org/youtube-dl
synced 2025-07-22 19:34:14 +09:00
added compatability wrapper for pbkdf2_sha1
This commit is contained in:
parent
613fe995f5
commit
104af51a20
@ -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<z\x16]\n\xbb\xb8\xcb\xd7\x9bA\xc3\x14e\x99{\xd6\xf4&'):
|
||||
with MonkeyPatch(cookies, {
|
||||
'_get_windows_v10_key': lambda *args, **kwargs: b'Y\xef\xad\xad\xeerp\xf0Y\xe6\x9b\x12\xc2<z\x16]\n\xbb\xb8\xcb\xd7\x9bA\xc3\x14e\x99{\xd6\xf4&'
|
||||
}):
|
||||
encrypted_value = b'v10T\xb8\xf3\xb8\x01\xa7TtcV\xfc\x88\xb8\xb8\xef\x05\xb5\xfd\x18\xc90\x009\xab\xb1\x893\x85)\x87\xe1\xa9-\xa3\xad='
|
||||
value = '32101439'
|
||||
decryptor = WindowsChromeCookieDecryptor('', Logger())
|
||||
assert decryptor.decrypt(encrypted_value) == value
|
||||
|
||||
def test_chrome_cookie_decryptor_mac_v10(self):
|
||||
with MonkeyPatch(cookies, '_get_mac_keyring_password', lambda *args, **kwargs: b'6eIDUdtKAacvlHwBVwvg/Q=='):
|
||||
with MonkeyPatch(cookies, {'_get_mac_keyring_password': lambda *args, **kwargs: b'6eIDUdtKAacvlHwBVwvg/Q=='}):
|
||||
encrypted_value = b'v10\xb3\xbe\xad\xa1[\x9fC\xa1\x98\xe0\x9a\x01\xd9\xcf\xbfc'
|
||||
value = '2021-06-01-22'
|
||||
decryptor = MacChromeCookieDecryptor('')
|
||||
@ -80,3 +88,10 @@ class TestCookies(unittest.TestCase):
|
||||
assert not cookie.secure
|
||||
expected_expiration = datetime(2021, 6, 18, 20, 39, 19, tzinfo=timezone.utc)
|
||||
assert cookie.expires == expected_expiration.timestamp()
|
||||
|
||||
def test_pbkdf2_sha1(self):
|
||||
key = pbkdf2_sha1(b'peanuts', b' ' * 16, 1, 16)
|
||||
if PBKDF2_AVAILABLE:
|
||||
assert key == b'g\xe1\x8e\x0fQ\x1c\x9b\xf3\xc9`!\xaa\x90\xd9\xd34'
|
||||
else:
|
||||
assert key is None
|
||||
|
@ -1,5 +1,4 @@
|
||||
import ctypes
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
@ -294,7 +293,7 @@ class LinuxChromeCookieDecryptor(ChromeCookieDecryptor):
|
||||
def derive_key(password):
|
||||
# values from
|
||||
# https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/os_crypt_linux.cc
|
||||
return hashlib.pbkdf2_hmac('sha1', password, salt=b'saltysalt', iterations=1, dklen=16)
|
||||
return pbkdf2_sha1(password, salt=b'saltysalt', iterations=1, key_length=16)
|
||||
|
||||
def decrypt(self, encrypted_value):
|
||||
version = encrypted_value[:3]
|
||||
@ -321,7 +320,7 @@ class MacChromeCookieDecryptor(ChromeCookieDecryptor):
|
||||
def derive_key(password):
|
||||
# values from
|
||||
# https://chromium.googlesource.com/chromium/src/+/refs/heads/main/components/os_crypt/os_crypt_mac.mm
|
||||
return hashlib.pbkdf2_hmac('sha1', password, salt=b'saltysalt', iterations=1003, dklen=16)
|
||||
return pbkdf2_sha1(password, salt=b'saltysalt', iterations=1003, key_length=16)
|
||||
|
||||
def decrypt(self, encrypted_value):
|
||||
version = encrypted_value[:3]
|
||||
@ -590,6 +589,24 @@ def _get_windows_v10_key(browser_root, logger):
|
||||
return _decrypt_windows_dpapi(encrypted_key[len(prefix):], logger)
|
||||
|
||||
|
||||
PBKDF2_AVAILABLE = sys.version_info[:2] >= (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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user