Python API Reference

Side-channel claim limit. Nothing on this page claims constant-time behaviour or side-channel resistance for any target: the side-channel harness covers nothing (finding A48) and no measurement exists. The Rust and C cores are designed for constant time and unmeasured; managed runtimes (JIT, GC, bounds checks) make no timing claim. Where this page names constant-time or side-channel techniques, in prose or in code, they are design intent or recommendations, not measured properties.

Complete API documentation for MetaMUI Crypto Primitives in Python.

Installation

No package is published on a public registry yet (release candidate 1.0.0-rc.6); the coordinates below are the decided public names. Until the launch publishes them, build from the source tree (see the Installation Guide) or install a locally built candidate. The snippet was run against such a candidate; the run is recorded in the source repository’s documents/public-release/evidence/229-documentation.md.

pip install metamui-crypto==1.0.0rc6     # Python 3.10, 3.11 or 3.12

Quick Start

from metamui_crypto.facade import profile

sig = profile("ml-dsa-65")
keys = sig.generate_keypair()
signature = sig.sign(keys.secret_key, b"message", context=b"my-app")
sig.verify(keys.public_key, b"message", signature, context=b"my-app")   # raises InvalidSignatureError on failure

kem = profile("ml-kem-768")
ek, dk = kem.generate_keypair()
ct, ss = kem.encapsulate(ek)
assert kem.decapsulate(dk, ct) == ss

API Documentation

For detailed API documentation, see:

Available Modules

Hash Functions

Digital Signatures

Encryption

Key Exchange

Key Derivation

Utilities

Type Hints

All functions include comprehensive type hints:

from typing import Tuple, Optional
from metamui_crypto import Ed25519, KeyPair

def sign_message(
    message: bytes, 
    private_key: bytes
) -> bytes:
    """Sign a message with Ed25519.
    
    Args:
        message: The message to sign
        private_key: 32-byte private key
        
    Returns:
        64-byte signature
        
    Raises:
        InvalidKeyError: If private key is invalid
    """
    return Ed25519.sign(message, private_key)

Error Handling

from metamui_crypto import (
    CryptoError,
    InvalidKeyError,
    DecryptionError,
    VerificationError
)

try:
    result = some_operation()
except InvalidKeyError as e:
    print(f"Invalid key: {e}")
except DecryptionError as e:
    print(f"Decryption failed: {e}")
except CryptoError as e:
    print(f"Crypto error: {e}")

Examples

Password Hashing

from metamui_crypto import Argon2

# Hash password
password = "user_password"
salt = Argon2.generate_salt()
hash = Argon2.hash(password, salt)

# Verify password
is_valid = Argon2.verify(password, hash)

Authenticated Encryption

from metamui_crypto import ChaCha20Poly1305

# Generate key
key = ChaCha20Poly1305.generate_key()

# Encrypt with associated data
plaintext = b"Secret message"
associated_data = b"metadata"

ciphertext, nonce, tag = ChaCha20Poly1305.encrypt_with_ad(
    plaintext, associated_data, key
)

# Decrypt and verify
decrypted = ChaCha20Poly1305.decrypt_with_ad(
    ciphertext, nonce, tag, associated_data, key
)

Post-Quantum Key Exchange

from metamui_crypto import MLKem768

# Generate keypair
keypair = MLKem768.generate_keypair()

# Encapsulate (sender)
ciphertext, shared_secret = MLKem768.encapsulate(
    keypair.public_key
)

# Decapsulate (receiver)
shared_secret_2 = MLKem768.decapsulate(
    ciphertext, keypair.private_key
)

assert shared_secret == shared_secret_2

Performance

Batch Operations

# Batch signature verification
signatures = [sig1, sig2, sig3]
messages = [msg1, msg2, msg3]
public_keys = [pk1, pk2, pk3]

results = Ed25519.batch_verify(
    signatures, messages, public_keys
)

Streaming

from metamui_crypto import Blake3

# Hash large file
hasher = Blake3.new()
with open('large_file.bin', 'rb') as f:
    while chunk := f.read(8192):
        hasher.update(chunk)
        
hash = hasher.finalize()

Security Notes

from metamui_crypto import SecureBytes

with SecureBytes(32) as key:
    # Use key
    cipher = ChaCha20Poly1305(key)
    encrypted = cipher.encrypt(data)
# key is automatically cleared

See Also