High-performance Matrix event signing library
Project description
Matrices Evolved
Features
- Dual Implementation Support - Choose between C++ (nanobind) or Rust (PyO3) backends
- Ed25519 Digital Signatures - Fast cryptographic signing and verification
- JSON Canonicalization - Matrix-compatible canonical JSON encoding
- Base64 Operations - Optimized encoding/decoding
- Hash Computation - SHA256 content and reference hashing
- Key Management - Generate, encode, and manage signing keys
- Matrix Protocol Compatible - Drop-in replacement for Matrix implementations
- High Performance - 10-100% faster than pure Python implementations
Installation
Prerequisites
For C++ Implementation:
- Clang 20 (required for C++23 support)
- Python 3.8+
- CMake 3.15+
For Rust Implementation:
- Rust 1.86+ (required for latest PyO3 features)
- Cargo
Install from PyPI
Only Python 3.11 wheels available. RHEL9/Ubuntu 22.04 both support it.
Maybe Python 3.12 in future but for now only 3.11.
pip install matrices-evolved
Build from Source
C++ Implementation (default):
git clone https://github.com/alessblaze/matrices_evolved.git
cd matrices_evolved
pip install .
Rust Implementation:
pip install . -C cmake.define.BUILD_RUST=ON -C cmake.define.BUILD_CPP=OFF
Both Implementations:
pip install . -C cmake.define.BUILD_RUST=ON
Quick Start
import matrices_evolved
# Generate signing keys
signing_key = matrices_evolved.generate_signing_key('ed25519')
verify_key = matrices_evolved.get_verify_key(signing_key)
# Sign a Matrix event
event = {"type": "m.room.message", "content": {"body": "Hello!"}}
signed_event = matrices_evolved.sign_json_object_fast(
event, "myserver.com", signing_key, "ed25519:v1"
)
# Verify the signature
matrices_evolved.verify_signed_json_fast(signed_event, "myserver.com", verify_key)
print("✅ Signature verified!")
Implementation Selection
# Auto-select (prefers C++ if available)
import matrices_evolved
# Explicit C++ implementation
import matrices_evolved.cpp as crypto
# Explicit Rust implementation
import matrices_evolved.rust as crypto
# Check available implementations
print(matrices_evolved.__implementations__) # ['cpp', 'rust']
Performance
Both implementations provide significant performance improvements over pure Python:
- 10-100x faster signing and verification
- 5-50x faster JSON canonicalization
- 2-10x faster base64 operations
- Minimal memory overhead with zero-copy operations
Import Performance:
- C++ import: ~3.5ms
- Rust import: ~0.1ms (25x faster)
Development
For detailed build instructions, compiler requirements, and build options, see BUILD.md.
Quick Development Setup
# Install Clang 20 from LLVM repository
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-20 main" | sudo tee /etc/apt/sources.list.d/llvm.list
sudo apt update && sudo apt install clang-20
# Install Rust 1.86+
rustup toolchain install 1.86.0
# Development build with both implementations
pip install -e . -C cmake.define.BUILD_RUST=ON
Compatibility
- Python 3.8+
- Linux (Ubuntu/Debian recommended)
- 100% compatible with Matrix protocol specifications
- Thread-safe operations
- Drop-in replacement for existing Matrix crypto libraries
Architecture
matrices_evolved/
├── cpp/ # C++ nanobind implementation
│ ├── base64/ # SIMD-optimized base64 encoders/decoders
│ │ ├── encoders/ # Multiple encoder implementations
│ │ └── decoders/ # Multiple decoder implementations
│ ├── benchmark/ # Performance benchmarking suite
│ │ ├── simde/ # SIMD Everywhere submodule
│ │ └── full_bench.cpp # Comprehensive benchmarks
│ ├── crypto/ # Ed25519 cryptographic operations
│ │ └── ed25519.cpp # Digital signatures & key management
│ ├── json/ # JSON canonicalization
│ │ └── canonicalization.cpp # SIMD-optimized JSON processing
│ ├── debug.h # Debug infrastructure & shared definitions
│ ├── global.h # Global includes & nanobind setup
│ └── lib.cpp # Python bindings & module definition
├── rust/ # Rust PyO3 implementation
│ ├── crypto/
│ │ ├── event_signing.rs # Ed25519 operations
│ │ ├── cache.rs # LRU cache implementation
│ │ └── stream_change_cache.rs # Stream change tracking
│ ├── Cargo.toml
│ └── lib.rs
├── matrices_evolved/ # Python package
│ ├── __init__.py # Auto-selection logic
│ ├── cpp.py # C++ wrapper
│ └── rust.py # Rust wrapper
└── CMakeLists.txt # Build configuration
In Progress
LRU, Stream Cache. You would need a wrapper to function these properly. these expose core functionality in cache.rs and event_signing.rs but more needed on python wrapper. the bindings are already there but currently not written in api docs.
Synthetic Benchmarks
Lru New results would be available after testing new changes.
crypto:
Pure rust bench:
benches/crypto_bench.rs (/mnt/build/Tests/signal/hula/synapse/target/release/deps/crypto_bench-b4730a09c1fd000f)
Gnuplot not found, using plotters backend
Benchmarking pure_rust_canonicalization
Benchmarking pure_rust_canonicalization: Warming up for 3.0000 s
Benchmarking pure_rust_canonicalization: Collecting 100 samples in estimated 5.0027 s (9.1M iterations)
Benchmarking pure_rust_canonicalization: Analyzing
pure_rust_canonicalization
time: [533.77 ns 534.46 ns 535.21 ns]
Benchmarking pure_rust_ed25519_sign
Benchmarking pure_rust_ed25519_sign: Warming up for 3.0000 s
Benchmarking pure_rust_ed25519_sign: Collecting 100 samples in estimated 5.0250 s (601k iterations)
Benchmarking pure_rust_ed25519_sign: Analyzing
pure_rust_ed25519_sign time: [8.3256 µs 8.3447 µs 8.3633 µs]
Found 2 outliers among 100 measurements (2.00%)
2 (2.00%) high severe
Benchmarking pure_rust_base64_encode
Benchmarking pure_rust_base64_encode: Warming up for 3.0000 s
Benchmarking pure_rust_base64_encode: Collecting 100 samples in estimated 5.0004 s (26M iterations)
Benchmarking pure_rust_base64_encode: Analyzing
pure_rust_base64_encode time: [194.77 ns 195.08 ns 195.39 ns]
Found 3 outliers among 100 measurements (3.00%)
1 (1.00%) low severe
2 (2.00%) high severe
Synmark bench Crypto:
Note: Python code probably has no keycaching as we did not write these functions. they are directly tested
against synapse provided functions.
Running PYTHON implementation:
canonicalization: 1.99 μs per operation
base64_encoding: 0.68 μs per operation
base64_decoding: 1.34 μs per operation
content_hash: 2.41 μs per operation
json_signing: 19.75 μs per operation
signature_verification: 48.15 μs per operation
synmark.suites.crypto_operations_auto: Mean +- std dev: 73.0 us +- 1.5 us
Note: Now Rust implementation also uses keycaching but the vectorization is not done manually thus
the mean result may be a bit misleading in real life scenarios.
Running RUST implementation:
canonicalization: 0.99 μs per operation
base64_encoding: 4.74 μs per operation
base64_decoding: 0.38 μs per operation
content_hash: 0.99 μs per operation
json_signing: 10.99 μs per operation
signature_verification: 36.73 μs per operation
synmark.suites.crypto_operations_auto: Mean +- std dev: 55.3 us +- 0.3 us
Note: C++ uses Vecorization if enables so synthetic benchmarks like synmark spawn many processes
usually in practice it would be faster due to continouous runs which reduces vecorization setup
times. Mainly in smaller inputs vectorizations is not recomended but we can utilize the workload
well in our scenatio, added private key caching improved the json signing but it is thread local
matrix signing usually uses one single key to sign so caching a key helps for key object processing
on openssl reduction on every call.
Note: C++ uses an iterative approach to json structure walk, Rust uses recursion.
Running C++ implementation:
canonicalization: 0.60 μs per operation
base64_encoding: 0.25 μs per operation
base64_decoding: 0.16 μs per operation
content_hash: 0.72 μs per operation
json_signing: 9.69 μs per operation
signature_verification: 35.68 μs per operation
synmark.suites.crypto_operations_auto: Mean +- std dev: 46.5 us +- 1.3 us
Stream Change Bench Results :
Pure python:
synmark.suites.stream_change_cache_auto: Mean +- std dev: 2.26 us +- 0.12 us
Rust Wrapper:
synmark.suites.stream_change_cache_rust_auto: Mean +- std dev: 559 ns +- 28 ns
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
Code Style
- C++: Follow C++23 best practices, use clang-format
- Rust: Follow rustfmt conventions, use clippy
- Python: Follow PEP 8, use black formatter
License
See LICENSE file for details.
Links
- API Documentation: API.md
- Build Instructions: BUILD.md
- Issues: GitHub Issues
- Matrix Protocol: Matrix Specification
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file matrices_evolved-1.0.8-cp311-cp311-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: matrices_evolved-1.0.8-cp311-cp311-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.11, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0rc1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ef1aa207c4a0dee391a9bf6a0027fb4184a6f6c63de47801a37ba929d8ce89a
|
|
| MD5 |
8892bbcc416cc0b1d1162f1821a0babd
|
|
| BLAKE2b-256 |
d3244b763ad158ef1d5175cdebc22615e3285f63f9e534c4e27b46bdceda09af
|
File details
Details for the file matrices_evolved-1.0.8-cp311-cp311-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: matrices_evolved-1.0.8-cp311-cp311-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 3.0 MB
- Tags: CPython 3.11, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e5432d704052a3603c4149794fb46cb6bedbb3758ff91431e79d75b9afe09b8
|
|
| MD5 |
71e4eab8af96748a34c396229eb1334f
|
|
| BLAKE2b-256 |
b2dd8fbff7022e55ed4e705418efb5b9b3c464f952653f8b26dcf4492b0dd03a
|
File details
Details for the file matrices_evolved-1.0.8-cp310-cp310-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: matrices_evolved-1.0.8-cp310-cp310-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.10, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0rc1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8de7daae5a75d2edfc27498f0d922c135baf242e9ba9c7a43fefea260af40762
|
|
| MD5 |
31e9f2e7ebc3327a2e2e565a9a0cb70b
|
|
| BLAKE2b-256 |
f47375379ff57bf6f1b7379691efadda6c482a91393634971b90348bc1124348
|
File details
Details for the file matrices_evolved-1.0.8-cp310-cp310-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: matrices_evolved-1.0.8-cp310-cp310-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 3.0 MB
- Tags: CPython 3.10, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2014f0b06c362415f9acfb46b95711656268e27f21be09d7cafd5f1330b7a50c
|
|
| MD5 |
cdc188c4066910ce8d6afac09d057896
|
|
| BLAKE2b-256 |
1d1765fc674411941b5b5ddd75ca96d1f58b605f10a0bdb7057c37ea50eea129
|