or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-tgcrypto

Fast and portable cryptography extension library for Pyrogram implementing AES-256-IGE, AES-256-CTR, and AES-256-CBC encryption modes for Telegram's MTProto protocol

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/tgcrypto@1.2.x

To install, run

npx @tessl/cli install tessl/pypi-tgcrypto@1.2.0

index.mddocs/

tgcrypto

A high-performance cryptography library written in C as a Python extension, specifically designed for Telegram's MTProto protocol. tgcrypto implements three essential AES-256 encryption algorithms required by Telegram: IGE mode for MTProto v2.0, CTR mode for CDN encrypted files, and CBC mode for encrypted passport credentials.

Package Information

  • Package Name: tgcrypto
  • Language: C/Python
  • Installation: pip install tgcrypto
  • Platform: Cross-platform (Windows, macOS, Linux)
  • Python Compatibility: 3.7+ (CPython, PyPy)

Core Imports

import tgcrypto

Basic Usage

import os
import tgcrypto

# Generate random key and data
key = os.urandom(32)  # 32-byte key for AES-256
data = os.urandom(64)  # Example data (must be multiple of 16 for IGE/CBC)

# IGE Mode - for MTProto v2.0
iv_ige = os.urandom(32)  # 32-byte IV for IGE
encrypted_ige = tgcrypto.ige256_encrypt(data, key, iv_ige)
decrypted_ige = tgcrypto.ige256_decrypt(encrypted_ige, key, iv_ige)

# CTR Mode - for CDN encrypted files  
iv_ctr = os.urandom(16)  # 16-byte IV for CTR
state = bytes([0])  # Counter state (0-15)
encrypted_ctr = tgcrypto.ctr256_encrypt(data, key, iv_ctr, state)
decrypted_ctr = tgcrypto.ctr256_decrypt(encrypted_ctr, key, iv_ctr, bytes([0]))

# CBC Mode - for encrypted passport credentials
iv_cbc = os.urandom(16)  # 16-byte IV for CBC
encrypted_cbc = tgcrypto.cbc256_encrypt(data, key, iv_cbc)
decrypted_cbc = tgcrypto.cbc256_decrypt(encrypted_cbc, key, iv_cbc)

print(data == decrypted_ige)  # True
print(data == decrypted_ctr)  # True  
print(data == decrypted_cbc)  # True

Architecture

tgcrypto is designed for maximum performance and portability:

  • C Implementation: Core algorithms implemented in optimized C code
  • Python Extension: Seamless integration with Python through the C API
  • Zero Dependencies: No external dependencies beyond Python standard library
  • Thread Safety: Releases GIL during encryption/decryption for concurrent operations
  • Memory Efficient: Direct buffer operations without unnecessary copying

Capabilities

IGE Mode (AES-256-IGE)

AES-256 in Infinite Garble Extension mode, used specifically for Telegram's MTProto v2.0 protocol. IGE provides enhanced security properties compared to standard CBC mode.

def ige256_encrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
    """
    Encrypt data using AES-256-IGE mode.
    
    Parameters:
    - data: Input data to encrypt (must be multiple of 16 bytes)
    - key: 32-byte encryption key  
    - iv: 32-byte initialization vector
    
    Returns:
    bytes: Encrypted data
    
    Raises:
    ValueError: If data is empty, not multiple of 16 bytes, key not 32 bytes, or IV not 32 bytes
    TypeError: If arguments are not bytes-like objects
    """

def ige256_decrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
    """
    Decrypt data using AES-256-IGE mode.
    
    Parameters:
    - data: Input data to decrypt (must be multiple of 16 bytes)
    - key: 32-byte decryption key
    - iv: 32-byte initialization vector
    
    Returns:
    bytes: Decrypted data
    
    Raises:
    ValueError: If data is empty, not multiple of 16 bytes, key not 32 bytes, or IV not 32 bytes
    TypeError: If arguments are not bytes-like objects
    """

Usage Example:

import os
import tgcrypto

# IGE requires data to be multiple of 16 bytes
data = os.urandom(1024)  # Already multiple of 16
key = os.urandom(32)
iv = os.urandom(32)

# For data that's not a multiple of 16, add padding
data_with_padding = data + bytes(-len(data) % 16)

encrypted = tgcrypto.ige256_encrypt(data_with_padding, key, iv)
decrypted = tgcrypto.ige256_decrypt(encrypted, key, iv)

print(data_with_padding == decrypted)  # True

CTR Mode (AES-256-CTR)

AES-256 in Counter mode, used for CDN encrypted file downloads in Telegram. CTR mode provides streaming encryption capabilities and doesn't require padding.

def ctr256_encrypt(data: bytes, key: bytes, iv: bytes, state: bytes) -> bytes:
    """
    Encrypt data using AES-256-CTR mode.
    
    Parameters:
    - data: Input data to encrypt (any length)
    - key: 32-byte encryption key
    - iv: 16-byte initialization vector (modified during operation)
    - state: 1-byte counter state (value 0-15)
    
    Returns:
    bytes: Encrypted data
    
    Raises:
    ValueError: If data is empty, key not 32 bytes, IV not 16 bytes, state not 1 byte, or state value > 15
    TypeError: If arguments are not bytes-like objects
    """

def ctr256_decrypt(data: bytes, key: bytes, iv: bytes, state: bytes) -> bytes:
    """
    Decrypt data using AES-256-CTR mode.
    
    Parameters:
    - data: Input data to decrypt (any length)
    - key: 32-byte decryption key
    - iv: 16-byte initialization vector (modified during operation)
    - state: 1-byte counter state (value 0-15)
    
    Returns:
    bytes: Decrypted data
    
    Raises:
    ValueError: If data is empty, key not 32 bytes, IV not 16 bytes, state not 1 byte, or state value > 15
    TypeError: If arguments are not bytes-like objects
    """

Single Chunk Usage:

import os
import tgcrypto

data = os.urandom(10 * 1024 * 1024)  # 10 MB of data
key = os.urandom(32)

# Use bytearray for IV since it gets modified
enc_iv = bytearray(os.urandom(16))
dec_iv = enc_iv.copy()

encrypted = tgcrypto.ctr256_encrypt(data, key, enc_iv, bytes([0]))
decrypted = tgcrypto.ctr256_decrypt(encrypted, key, dec_iv, bytes([0]))

print(data == decrypted)  # True

Streaming Usage:

import os
from io import BytesIO
import tgcrypto

# Setup
data = BytesIO(os.urandom(10 * 1024 * 1024))
key = os.urandom(32)
enc_iv = bytearray(os.urandom(16))
dec_iv = enc_iv.copy()
enc_state = bytes([0])
dec_state = bytes([0])

encrypted_buffer = BytesIO()
decrypted_buffer = BytesIO()

# Encrypt in chunks
while True:
    chunk = data.read(1024)
    if not chunk:
        break
    encrypted_buffer.write(tgcrypto.ctr256_encrypt(chunk, key, enc_iv, enc_state))

# Decrypt in chunks
encrypted_buffer.seek(0)
while True:
    chunk = encrypted_buffer.read(1024)
    if not chunk:
        break
    decrypted_buffer.write(tgcrypto.ctr256_decrypt(chunk, key, dec_iv, dec_state))

print(data.getvalue() == decrypted_buffer.getvalue())  # True

CBC Mode (AES-256-CBC)

AES-256 in Cipher Block Chaining mode, used for encrypting passport credentials in Telegram. CBC provides strong security with proper IV handling.

def cbc256_encrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
    """
    Encrypt data using AES-256-CBC mode.
    
    Parameters:
    - data: Input data to encrypt (must be multiple of 16 bytes)
    - key: 32-byte encryption key
    - iv: 16-byte initialization vector
    
    Returns:
    bytes: Encrypted data
    
    Raises:
    ValueError: If data is empty, not multiple of 16 bytes, key not 32 bytes, or IV not 16 bytes
    TypeError: If arguments are not bytes-like objects
    """

def cbc256_decrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
    """
    Decrypt data using AES-256-CBC mode.
    
    Parameters:
    - data: Input data to decrypt (must be multiple of 16 bytes)
    - key: 32-byte decryption key
    - iv: 16-byte initialization vector
    
    Returns:
    bytes: Decrypted data
    
    Raises:
    ValueError: If data is empty, not multiple of 16 bytes, key not 32 bytes, or IV not 16 bytes  
    TypeError: If arguments are not bytes-like objects
    """

Usage Example:

import os
import tgcrypto

# CBC requires data to be multiple of 16 bytes
data = os.urandom(1024 + 7)  # Add 7 bytes to demonstrate padding
key = os.urandom(32)

# Separate IVs for encryption and decryption
enc_iv = bytearray(os.urandom(16))
dec_iv = enc_iv.copy()

# Pad data to multiple of 16 bytes
padded_data = data + bytes(-len(data) % 16)

encrypted = tgcrypto.cbc256_encrypt(padded_data, key, enc_iv)
decrypted = tgcrypto.cbc256_decrypt(encrypted, key, dec_iv)

print(padded_data == decrypted)  # True

Error Handling

All functions perform comprehensive input validation and raise specific exceptions:

Common Errors:

  • ValueError: Input validation failures (empty data, wrong sizes, invalid state values)
  • TypeError: Non-bytes arguments passed to functions

Validation Rules:

  • Data: Must not be empty; IGE/CBC require multiples of 16 bytes
  • Key: Must be exactly 32 bytes for all modes
  • IV: Must be 32 bytes for IGE, 16 bytes for CTR/CBC
  • State (CTR only): Must be 1 byte with value 0-15

Error Handling Example:

import tgcrypto

try:
    # This will raise ValueError: Data size must match a multiple of 16 bytes
    tgcrypto.ige256_encrypt(b"hello", b"x" * 32, b"y" * 32)
except ValueError as e:
    print(f"Validation error: {e}")

try:
    # This will raise ValueError: Key size must be exactly 32 bytes
    tgcrypto.ctr256_encrypt(b"hello", b"short", b"x" * 16, bytes([0]))
except ValueError as e:
    print(f"Key size error: {e}")

Performance Considerations

  • Thread Safety: All functions release the Python GIL during computation
  • Memory Efficiency: Direct buffer operations minimize memory allocation
  • Optimized C Code: Hand-optimized AES implementation for maximum performance
  • No Dependencies: Zero external dependencies reduce attack surface and improve portability

Telegram Integration

tgcrypto is specifically designed for Telegram's cryptographic requirements:

  • MTProto v2.0: Uses IGE mode for message encryption
  • CDN Files: Uses CTR mode for streaming file downloads
  • Passport: Uses CBC mode for credential encryption

The library ensures compatibility with Telegram's exact specifications while providing optimal performance for bot development and MTProto implementations.