Back to Repositories

Validating AES Cryptographic Operations in youtube-dl

This test suite validates the AES encryption/decryption functionality in youtube-dl, covering various AES modes including ECB, CBC, and text-based encryption. The tests ensure cryptographic operations work correctly with different key sizes and input formats.

Test Coverage Overview

The test suite provides comprehensive coverage of AES cryptographic operations.

Key functionality tested:
  • Basic AES encryption/decryption
  • CBC mode encryption/decryption
  • Text-based encryption with base64 encoding
  • ECB mode encryption
Edge cases include different key sizes (16 and 32 bytes) and varying input formats including bytes and text.

Implementation Analysis

The testing approach uses Python’s unittest framework with a structured TestAES class. Each test method validates a specific AES operation against known test vectors.

Technical patterns include:
  • setUp method for test initialization
  • Byte-to-integer list conversions
  • Base64 encoding/decoding
  • Known plaintext/ciphertext pair validation

Technical Details

Testing tools and configuration:
  • Python unittest framework
  • Custom AES implementation from youtube_dl.aes
  • Utility functions for byte/integer conversions
  • Base64 encoding for text-based encryption
  • Predefined test vectors for validation

Best Practices Demonstrated

The test suite exemplifies strong testing practices through modular test organization and thorough validation.

Notable practices:
  • Isolated test cases for each encryption mode
  • Consistent test data initialization
  • Known test vector validation
  • Clear separation of different AES modes
  • Comprehensive coverage of encryption/decryption pairs

ytdl-org/youtube-dl

test/test_aes.py

            
#!/usr/bin/env python

from __future__ import unicode_literals

# Allow direct execution
import os
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from youtube_dl.aes import aes_decrypt, aes_encrypt, aes_cbc_decrypt, aes_cbc_encrypt, aes_decrypt_text, aes_ecb_encrypt
from youtube_dl.utils import bytes_to_intlist, intlist_to_bytes
import base64

# the encrypted data can be generate with 'devscripts/generate_aes_testdata.py'


class TestAES(unittest.TestCase):
    def setUp(self):
        self.key = self.iv = [0x20, 0x15] + 14 * [0]
        self.secret_msg = b'Secret message goes here'

    def test_encrypt(self):
        msg = b'message'
        key = list(range(16))
        encrypted = aes_encrypt(bytes_to_intlist(msg), key)
        decrypted = intlist_to_bytes(aes_decrypt(encrypted, key))
        self.assertEqual(decrypted, msg)

    def test_cbc_decrypt(self):
        data = bytes_to_intlist(
            b"\x97\x92+\xe5\x0b\xc3\x18\x91ky9m&\xb3\xb5@\xe6'\xc2\x96.\xc8u\x88\xab9-[\x9e|\xf1\xcd"
        )
        decrypted = intlist_to_bytes(aes_cbc_decrypt(data, self.key, self.iv))
        self.assertEqual(decrypted.rstrip(b'\x08'), self.secret_msg)

    def test_cbc_encrypt(self):
        data = bytes_to_intlist(self.secret_msg)
        encrypted = intlist_to_bytes(aes_cbc_encrypt(data, self.key, self.iv))
        self.assertEqual(
            encrypted,
            b"\x97\x92+\xe5\x0b\xc3\x18\x91ky9m&\xb3\xb5@\xe6'\xc2\x96.\xc8u\x88\xab9-[\x9e|\xf1\xcd")

    def test_decrypt_text(self):
        password = intlist_to_bytes(self.key).decode('utf-8')
        encrypted = base64.b64encode(
            intlist_to_bytes(self.iv[:8])
            + b'\x17\x15\x93\xab\x8d\x80V\xcdV\xe0\t\xcdo\xc2\xa5\xd8ksM\r\xe27N\xae'
        ).decode('utf-8')
        decrypted = (aes_decrypt_text(encrypted, password, 16))
        self.assertEqual(decrypted, self.secret_msg)

        password = intlist_to_bytes(self.key).decode('utf-8')
        encrypted = base64.b64encode(
            intlist_to_bytes(self.iv[:8])
            + b'\x0b\xe6\xa4\xd9z\x0e\xb8\xb9\xd0\xd4i_\x85\x1d\x99\x98_\xe5\x80\xe7.\xbf\xa5\x83'
        ).decode('utf-8')
        decrypted = (aes_decrypt_text(encrypted, password, 32))
        self.assertEqual(decrypted, self.secret_msg)

    def test_ecb_encrypt(self):
        data = bytes_to_intlist(self.secret_msg)
        encrypted = intlist_to_bytes(aes_ecb_encrypt(data, self.key))
        self.assertEqual(
            encrypted,
            b'\xaa\x86]\x81\x97>\x02\x92\x9d\x1bR[[L/u\xd3&\xd1(h\xde{\x81\x94\xba\x02\xae\xbd\xa6\xd0:')


if __name__ == '__main__':
    unittest.main()