CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-oscrypto

Cross-platform cryptographic library providing TLS sockets, asymmetric/symmetric encryption, and key operations using OS-native crypto libraries

Pending
Overview
Eval results
Files

utility.mddocs/

Utility Functions

Cryptographic utilities including secure random number generation and constant-time comparison for security-critical operations. These functions provide essential building blocks for secure cryptographic implementations.

Capabilities

Secure Random Generation

Generate cryptographically secure random bytes using the operating system's entropy source.

def rand_bytes(length: int) -> bytes:
    """
    Generate cryptographically secure random bytes.

    Parameters:
    - length: int - Number of random bytes to generate

    Returns:
    Random bytes of specified length

    Note:
    Uses OS entropy sources (CryptGenRandom on Windows, /dev/urandom on Unix)
    """

Constant-Time Comparison

Compare byte strings in constant time to prevent timing attacks in security-critical code.

def constant_compare(a: bytes, b: bytes) -> bool:
    """
    Compare two byte strings in constant time.

    Parameters:
    - a: bytes - First byte string
    - b: bytes - Second byte string

    Returns:
    True if byte strings are equal, False otherwise

    Raises:
    TypeError if either parameter is not bytes

    Note:
    Comparison time is independent of where strings differ, preventing timing attacks
    """

Usage Examples

Secure Random Generation

from oscrypto.util import rand_bytes

# Generate random keys of various sizes
aes_128_key = rand_bytes(16)  # 128-bit AES key
aes_256_key = rand_bytes(32)  # 256-bit AES key
random_salt = rand_bytes(16)  # Salt for key derivation
session_id = rand_bytes(32)   # Session identifier

print(f"AES-128 key: {aes_128_key.hex()}")
print(f"AES-256 key: {aes_256_key.hex()}")
print(f"Salt: {random_salt.hex()}")
print(f"Session ID: {session_id.hex()}")

# Generate random initialization vectors
aes_iv = rand_bytes(16)    # AES block size
des_iv = rand_bytes(8)     # DES block size

print(f"AES IV: {aes_iv.hex()}")
print(f"DES IV: {des_iv.hex()}")

Constant-Time Comparison

from oscrypto.util import constant_compare
import time

def timing_attack_demo():
    """Demonstrate why constant-time comparison is important."""
    
    # Create two similar strings that differ at different positions
    target = b"secret_authentication_token_12345678"
    
    # Attack string differs at position 0
    attack1 = b"xxxxxx_authentication_token_12345678"
    
    # Attack string differs at position 30
    attack2 = b"secret_authentication_token_1234xxxx"
    
    # Measure time for regular comparison (vulnerable to timing attacks)
    start = time.perf_counter()
    for _ in range(100000):
        result = target == attack1
    time1 = time.perf_counter() - start
    
    start = time.perf_counter()
    for _ in range(100000):
        result = target == attack2
    time2 = time.perf_counter() - start
    
    print("Regular comparison timing:")
    print(f"  Early difference: {time1:.6f} seconds")
    print(f"  Late difference:  {time2:.6f} seconds")
    print(f"  Timing difference: {abs(time1 - time2):.6f} seconds")
    
    # Measure time for constant-time comparison (secure)
    start = time.perf_counter()
    for _ in range(100000):
        result = constant_compare(target, attack1)
    time1 = time.perf_counter() - start
    
    start = time.perf_counter()
    for _ in range(100000):
        result = constant_compare(target, attack2)
    time2 = time.perf_counter() - start
    
    print("\nConstant-time comparison:")
    print(f"  Early difference: {time1:.6f} seconds")
    print(f"  Late difference:  {time2:.6f} seconds")
    print(f"  Timing difference: {abs(time1 - time2):.6f} seconds")

# Run timing demonstration
timing_attack_demo()

Secure Token Generation

from oscrypto.util import rand_bytes, constant_compare
import base64
import hashlib

class SecureTokenManager:
    """Example secure token management using oscrypto utilities."""
    
    def __init__(self):
        # Generate master key for token signing
        self.master_key = rand_bytes(32)
    
    def generate_token(self, user_id: str, expires_at: int) -> str:
        """Generate a secure token for a user."""
        # Create token payload
        payload = f"{user_id}:{expires_at}".encode('utf-8')
        
        # Generate random nonce
        nonce = rand_bytes(16)
        
        # Create HMAC signature
        hmac_key = hashlib.pbkdf2_hmac('sha256', self.master_key, nonce, 10000)
        signature = hashlib.hmac.new(hmac_key, payload, hashlib.sha256).digest()
        
        # Combine nonce + payload + signature
        token_data = nonce + payload + signature
        
        # Encode as base64
        return base64.urlsafe_b64encode(token_data).decode('ascii')
    
    def verify_token(self, token: str, user_id: str, expires_at: int) -> bool:
        """Verify a token in constant time."""
        try:
            # Decode token
            token_data = base64.urlsafe_b64decode(token.encode('ascii'))
            
            # Extract components
            nonce = token_data[:16]
            payload = token_data[16:-32]
            signature = token_data[-32:]
            
            # Verify payload matches expected values
            expected_payload = f"{user_id}:{expires_at}".encode('utf-8')
            if not constant_compare(payload, expected_payload):
                return False
            
            # Recreate signature
            hmac_key = hashlib.pbkdf2_hmac('sha256', self.master_key, nonce, 10000)
            expected_signature = hashlib.hmac.new(hmac_key, payload, hashlib.sha256).digest()
            
            # Constant-time signature verification
            return constant_compare(signature, expected_signature)
            
        except Exception:
            return False

# Example usage
token_manager = SecureTokenManager()

# Generate token
user_id = "user123"
expires_at = 1735689600  # Timestamp
token = token_manager.generate_token(user_id, expires_at)
print(f"Generated token: {token}")

# Verify valid token
is_valid = token_manager.verify_token(token, user_id, expires_at)
print(f"Token valid: {is_valid}")

# Verify invalid token
is_valid = token_manager.verify_token(token + "x", user_id, expires_at)
print(f"Modified token valid: {is_valid}")

Cryptographic Key Generation

from oscrypto.util import rand_bytes
from oscrypto.kdf import pbkdf2
import base64

def generate_keypair_seed() -> str:
    """Generate a high-entropy seed for deterministic key generation."""
    # Generate 256 bits of entropy
    seed = rand_bytes(32)
    
    # Encode as base64 for storage/transmission
    return base64.b64encode(seed).decode('ascii')

def derive_multiple_keys(master_secret: bytes, key_count: int = 3) -> dict:
    """Derive multiple keys from a master secret."""
    keys = {}
    
    for i in range(key_count):
        # Use different salt for each key
        salt = f"key_derivation_{i}".encode('utf-8') + rand_bytes(8)
        
        # Derive 32-byte key
        key = pbkdf2('sha256', master_secret, salt, 100000, 32)
        keys[f"key_{i}"] = key
    
    return keys

def secure_key_splitting(secret: bytes, threshold: int, shares: int) -> list:
    """Simple secret sharing using XOR (for demonstration)."""
    if threshold != shares:
        raise ValueError("This example only supports threshold == shares")
    
    # Generate random shares
    share_list = []
    running_xor = secret
    
    for i in range(shares - 1):
        share = rand_bytes(len(secret))
        share_list.append(share)
        
        # XOR with running total
        running_xor = bytes(a ^ b for a, b in zip(running_xor, share))
    
    # Last share is the XOR of all previous shares with the secret
    share_list.append(running_xor)
    
    return share_list

def reconstruct_secret(shares: list) -> bytes:
    """Reconstruct secret from XOR shares."""
    result = shares[0]
    for share in shares[1:]:
        result = bytes(a ^ b for a, b in zip(result, share))
    return result

# Example usage
print("Generating master seed...")
seed_b64 = generate_keypair_seed()
print(f"Seed (base64): {seed_b64}")

# Convert back to bytes
master_secret = base64.b64decode(seed_b64)

print("\nDeriving multiple keys...")
keys = derive_multiple_keys(master_secret, 3)
for name, key in keys.items():
    print(f"{name}: {key[:8].hex()}...")

print("\nSecret sharing example...")
secret = b"This is a very secret message!"
shares = secure_key_splitting(secret, 3, 3)
print(f"Split secret into {len(shares)} shares")

# Reconstruct
reconstructed = reconstruct_secret(shares)
print(f"Reconstructed: {reconstructed}")
print(f"Match: {secret == reconstructed}")

Secure Random Testing

from oscrypto.util import rand_bytes
import collections

def test_randomness_quality(samples: int = 10000, byte_length: int = 16):
    """Basic statistical tests for random number quality."""
    
    print(f"Testing randomness with {samples} samples of {byte_length} bytes each")
    
    # Collect random samples
    byte_counts = collections.defaultdict(int)
    bit_counts = [0, 0]  # [0-bits, 1-bits]
    
    for _ in range(samples):
        random_bytes = rand_bytes(byte_length)
        
        # Count byte values
        for byte_val in random_bytes:
            byte_counts[byte_val] += 1
        
        # Count bits
        for byte_val in random_bytes:
            for bit_pos in range(8):
                bit_counts[(byte_val >> bit_pos) & 1] += 1
    
    # Analyze results
    total_bytes = samples * byte_length
    total_bits = total_bytes * 8
    
    print(f"\nBit distribution:")
    print(f"  0-bits: {bit_counts[0]} ({bit_counts[0]/total_bits*100:.2f}%)")
    print(f"  1-bits: {bit_counts[1]} ({bit_counts[1]/total_bits*100:.2f}%)")
    print(f"  Balance: {abs(bit_counts[0] - bit_counts[1])} difference")
    
    # Check for repeated sequences
    sequences = set()
    duplicates = 0
    
    for _ in range(1000):
        seq = rand_bytes(16)
        if seq in sequences:
            duplicates += 1
        sequences.add(seq)
    
    print(f"\nSequence uniqueness (1000 samples):")
    print(f"  Duplicates: {duplicates}")
    print(f"  Unique: {1000 - duplicates}")
    
    # Byte value distribution
    expected_per_value = total_bytes / 256
    max_deviation = max(abs(count - expected_per_value) for count in byte_counts.values())
    
    print(f"\nByte value distribution:")
    print(f"  Expected per value: {expected_per_value:.1f}")
    print(f"  Max deviation: {max_deviation:.1f}")

# Run randomness tests
test_randomness_quality()

Install with Tessl CLI

npx tessl i tessl/pypi-oscrypto

docs

asymmetric.md

backend.md

index.md

kdf.md

keys.md

symmetric.md

tls.md

trust-store.md

utility.md

tile.json