Python package: metamui-crypto

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.

Version: 1.0.0rc7 (the 1.0.0-rc.7 release line in PyPI form; no package is published on PyPI yet) Python: 3.10, 3.11, 3.12 (requires-python >= 3.10) Licence: Apache-2.0 Distribution: one package, metamui-crypto, importing as metamui_crypto. The wheel carries compiled extensions (SHA-2, SHA-3, SHAKE and HMAC compiled from metamui-crypto-c, and the post-quantum cores), one wheel per interpreter; the sdist builds them with a C compiler. Nothing in the package wraps an external cryptography library.

This page is the package summary; the Python API Reference and the Python platform guide carry the installation and build detail.

Installation

pip install metamui-crypto==1.0.0rc7

Until the package is published, install the wheel of a locally built candidate or the source directory itself (pip install metamui-crypto-python/ from a checkout).

The facade

metamui_crypto.facade names every post-quantum profile of the release catalog by its identifier and holds each to the public API contract (explicit selection, validated byte boundaries, no boolean verify, required context strings, OS randomness only; see the Public API Reference). The block below was run on 2026-10-16 against this source tree: pip install metamui-crypto-python/ into a fresh Python 3.12 virtual environment, then python -I on the file; it exited 0.

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

A family name is refused rather than substituted (also run on 2026-10-16; it printed refused: unsupported profile 'ml-kem'):

from metamui_crypto.facade import profile, UnsupportedProfileError

try:
    profile("ml-kem")          # a family name is not a profile
except UnsupportedProfileError as e:
    print("refused:", e)

Profile objects: falcon512_compressed, falcon512_padded, falcon1024_compressed, falcon1024_padded, mlkem512, mlkem768, mlkem1024, mldsa44, mldsa65, mldsa87, the twelve SLH-DSA sets, smaugt modes 1/3/5, haetae2, haetae3, haetae5, aimer128s … aimer256f, ntruplus768, ntruplus864, ntruplus1152 — the 37 profiles the facade admits. Every error is a MetaMuiCryptoError subclass: UnsupportedProfileError, InvalidLengthError, InvalidHeaderError, MalformedKeyError, InvalidSignatureError, SigningFailedError, KeyGenerationFailedError, EntropyUnavailableError, EncapsulationFailedError, DecapsulationFailedError (NTRU+ only).

Modules in the package

Classical and supporting primitives are modules of metamui_crypto: sha2, sha3, shake, keccak, blake2b, blake2s, blake3, siphash, flathash, hmac, hkdf, pbkdf2, argon2, cmac, poly1305, aes256, aes_ctr_drbg, hmac_drbg, chacha20, chacha20_poly1305, camellia, aria256, ascon, deoxys, ed25519, ed25519zip215, rsa2048, mnemonic, hdwallet; the post-quantum families are falcon, mlkem, dilithium, slhdsa, smaug_t, haetae, aimer, ntru_plus. The catalog records the classical profiles blake3, sha3-256, shake-256, keccak-256, aes-256-gcm, hkdf-sha256, ed25519 and sr25519 as validated on the Python target; the other modules are present with their own tests and no catalog claim.

metamui_crypto.DEFERRED_FAMILIES names the families the release catalog defers (Classic McEliece, FrodoKEM, HQC, LMS, NTRU Prime, XMSS); their modules are present for evaluation and no cell of the catalog claims them.

Testing

python3 -m pytest

The suite replays the upstream answer files under test-vectors/ through the public API; a missing vector file fails the run. (Not re-run for this page; the command is the package’s own, from its README.)

What is not claimed