Charm
Charm: A Framework for Rapidly Prototyping Cryptosystems
Install / Use
/learn @JHUISI/CharmREADME
Charm-Crypto
| Branch | Status |
| ----------- | --------------------------------------------------------------------------------------------------------------- |
| dev | |
Charm is a framework for rapidly prototyping advanced cryptosystems. Based on the Python language, it was designed from the ground up to minimize development time and code complexity while promoting the reuse of components.
Charm uses a hybrid design: performance-intensive mathematical operations are implemented in native C modules, while cryptosystems themselves are written in a readable, high-level language. Charm additionally provides a number of new components to facilitate the rapid development of new schemes and protocols.
Features
Advanced Cryptographic Schemes
- Attribute-Based Encryption (ABE): Fine-grained access control encryption
- Ciphertext-Policy ABE (CP-ABE): BSW07, Waters09, FAME
- Key-Policy ABE (KP-ABE): LSW08, GPSW06
- Multi-Authority ABE, Decentralized ABE
- Identity-Based Encryption (IBE): Encryption using identities as public keys
- Waters05, Boneh-Boyen (BB04), Boneh-Franklin
- Pairing-Based Cryptography: BN254, BLS12-381 curve support (~128-bit security)
- Bilinear pairings for advanced protocols
- Efficient implementation via PBC library
- Digital Signatures: Comprehensive signature scheme library
- Pairing-based: BLS (Ethereum 2.0), Waters, CL04, Boyen
- Elliptic curve: ECDSA, Schnorr, EdDSA
- Standard: RSA, DSA, Lamport
- Aggregate/Multi-signatures: BLS aggregation, MuSig
- Public-Key Encryption: Standard and advanced PKE schemes
- ElGamal, RSA, Paillier (homomorphic), Cramer-Shoup
- Commitments & Secret Sharing: Pedersen commitments, Feldman/Pedersen VSS
Threshold Cryptography / MPC
- Threshold ECDSA: Production-ready t-of-n distributed signing
- GG18 (Gennaro-Goldfeder 2018) — Classic Paillier-based threshold ECDSA
- CGGMP21 (Canetti et al. 2021) — UC-secure with identifiable aborts
- DKLS23 (Doerner et al. 2023) — Non-interactive presigning with OT-based MtA
- Supports secp256k1 (Bitcoin, XRPL) and other curves
Zero-Knowledge Proofs
- ZKP Compiler: Production-ready compiler for interactive and non-interactive proofs
- Schnorr proofs, Discrete Log Equality (DLEQ)
- Knowledge of Representation proofs
- AND/OR composition for complex statements
- Range proofs via bit decomposition
- Batch verification for improved performance
Infrastructure & Tools
- Mathematical Settings: Integer rings/fields, bilinear and non-bilinear EC groups
- Base Crypto Library: Symmetric encryption (AES), hash functions, PRNGs
- Protocol Engine: Simplifies multi-party protocol implementation
- C/C++ Embed API: Native applications can embed Charm via the Python C API
- Integrated Benchmarking: Built-in performance measurement
Requirements
| Component | Supported Versions | |-----------|-------------------| | Python | 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14 | | Operating Systems | Linux, macOS, Windows | | OpenSSL | 3.0+ |
Installation
One-Line Install (Recommended)
The easiest way to install Charm is using the automated install script, which handles all system dependencies:
curl -sSL https://raw.githubusercontent.com/JHUISI/charm/dev/install.sh | bash
Supported platforms:
- Ubuntu/Debian (and derivatives: Linux Mint, Pop!_OS)
- Fedora/RHEL/CentOS (and derivatives: Rocky, Alma, Oracle Linux)
- Arch Linux (and derivatives: Manjaro, EndeavourOS)
- macOS (Intel and Apple Silicon)
Install options:
# Default: install from PyPI (recommended)
curl -sSL ... | bash
# Install from source (for development)
curl -sSL ... | bash -s -- --from-source
# Only install system dependencies (for manual pip install)
curl -sSL ... | bash -s -- --deps-only
# See all options
./install.sh --help
Quick Install (pip)
If you prefer to install dependencies manually:
pip install charm-crypto-framework
Note: System libraries (GMP, PBC, OpenSSL) must be installed first. See Prerequisites below.
Prerequisites
Charm requires the following system libraries:
| Library | Version | Purpose | |---------|---------|---------| | GMP | 5.0+ | Arbitrary precision arithmetic | | PBC | 1.0.0 | Pairing-based cryptography | | OpenSSL | 3.0+ | Cryptographic primitives |
Ubuntu/Debian:
sudo apt-get install libgmp-dev libssl-dev libpbc-dev flex bison
macOS (Homebrew):
brew install gmp openssl@3 pbc
PBC from Source (if not available via package manager):
wget https://crypto.stanford.edu/pbc/files/pbc-1.0.0.tar.gz
tar xzf pbc-1.0.0.tar.gz
cd pbc-1.0.0
./configure && make && sudo make install
From Source (Development)
git clone https://github.com/JHUISI/charm.git
cd charm
./configure.sh # add --enable-darwin on macOS
pip install -e ".[dev]"
Verify Installation
python -c "from charm.toolbox.pairinggroup import PairingGroup; print('Charm installed successfully\!')"
Testing
Charm includes comprehensive test suites:
# Run all tests
make test-all
# Run specific test categories
make test-unit # Unit tests (toolbox, serialize, vectors)
make test-schemes # Cryptographic scheme tests
make test-zkp # ZKP compiler tests
make test-adapters # Adapter tests
make test-embed # C/C++ embed API tests
# Threshold ECDSA tests (GG18, CGGMP21, DKLS23)
pytest charm/test/schemes/threshold_test.py -v -k "GG18 or CGGMP21 or DKLS23"
# Run with coverage
pytest --cov=charm charm/test/ -v
Documentation
Quick Examples
BLS Signatures (Pairing-Based)
BLS signatures (Boneh-Lynn-Shacham) — standardized in IETF RFC 9380 and used in Ethereum 2.0:
from charm.toolbox.pairinggroup import PairingGroup
from charm.schemes.pksig.pksig_bls04 import BLS01
# Initialize pairing group (BN254 curve, ~128-bit security)
group = PairingGroup('BN254')
bls = BLS01(group)
# Ethereum 2.0 validator attestation
attestation = {'slot': 1234, 'epoch': 38, 'beacon_block_root': '0xabc...'}
(pk, sk) = bls.keygen()
signature = bls.sign(sk['x'], attestation)
assert bls.verify(pk, signature, attestation)
ECDSA with secp256k1 (Bitcoin)
ECDSA on secp256k1 — the curve used by Bitcoin (SEC 2, BIP-340):
import hashlib
import json
from charm.toolbox.ecgroup import ECGroup
from charm.toolbox.eccurve import secp256k1
from charm.schemes.pksig.pksig_ecdsa import ECDSA
group = ECGroup(secp256k1)
ecdsa = ECDSA(group)
# Bitcoin transaction (simplified)
tx = {
'inputs': [{'txid': 'a1b2c3...', 'vout': 0, 'address': '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'}],
'outputs': [{'address': '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy', 'satoshis': 50000}],
'fee': 1000
}
# Serialize and double SHA-256 (SHA-256d) per Bitcoin protocol
tx_bytes = json.dumps(tx, sort_keys=True).encode('utf-8')
tx_hash = hashlib.sha256(hashlib.sha256(tx_bytes).digest()).hexdigest()
(pk, sk) = ecdsa.keygen(0)
signature = ecdsa.sign(pk, sk, tx_hash)
assert ecdsa.verify(pk, signature, tx_hash)
Note: Production Bitcoin implementations should use proper transaction serialization per Bitcoin Developer Documentation.
ECDSA with secp256k1 (XRPL)
ECDSA on secp256k1 — also used by XRP Ledger (SEC 2):
import hashlib
import json
from charm.toolbox.ecgroup import ECGroup
from charm.toolbox.eccurve import secp256k1
from charm.schemes.pksig.pksig_ecdsa import ECDSA
group = ECGroup(secp256k1)
ecdsa = ECDSA(group)
# XRPL Payment transaction
tx = {
'TransactionType': 'Payment',
'Account': 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
'Destination': 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe',
'Amount': '1000000', # drops of XRP
'Sequence': 1
}
# Serialize and hash (XRPL uses canonical binary + SHA-512Half)
tx_bytes = json.dumps(tx, sort_keys=True).encode('utf-8')
tx_hash = hashlib.sha512(tx_bytes).hexdigest()[:64] # SHA-512Half
(pk, sk) = ecdsa.keygen(0)
signature = ecdsa.sign(pk, sk, tx_hash)
assert ecdsa.verify(pk, signature, tx_hash)
Note: Production XRPL implementations should use canonical binary serialization per XRPL documentation.
Threshold ECDSA
Charm provides three production-ready threshold ECDSA implementations for MPC-based signing. All support secp256k1 (Bitcoin, XRPL) and other elliptic curves.
GG18 (2-of-3 threshold signing):
from charm.toolbox.ecgroup import ECGroup
from charm.toolbox.eccurve import secp256k1
from charm.schemes.threshold import GG18
group = ECGroup(secp256k1)
gg18 = GG18(group, threshold=2, num_parties=3)
# Distributed key generation
key_shares, public_key = gg18.keygen()
# Sign with 2 of 3 parties (interactive, 4 rounds)
message = b"Bitcoin transaction hash"
signature = gg18.sign(key_shares[:2], message)
assert gg18.verify(public_key, message, signature)
CGGMP21 with presigning (UC-secure, identifiable aborts):
from charm.schemes.threshold import CGGMP21
cggmp = CGGMP21(group, threshold=2, num_parties=3)
key_shares, public_key = cggmp.keygen()
# Opti
