Skip to main content

Fast, secure Macaroon library for Python 3.8+ with optional Rust acceleration

Project description

PyMacaroons2

Fast, secure Macaroons for modern Python 3.8+

PyPI version Python 3.8+ License: MIT

Hard fork of the unmaintained pymacaroons with security fixes, performance improvements, and modern Python support.

✨ Features

  • 🔒 Security fixes - Constant-time comparison, fixed base64 bugs
  • 🚀 Optional Rust acceleration - 6-7x faster HMAC operations
  • 📦 Modern packaging - pyproject.toml, no setup.py
  • 🔄 Async support - AsyncVerifier for async/await workflows
  • 🎯 Memory optimized - __slots__ on all classes (~40% memory reduction)
  • 🐍 Python 3.8+ - Drops Python 2 support for cleaner code

📦 Installation

pip install pymacaroons2

Optional: Enable Rust acceleration

For maximum performance, install with Rust extension:

pip install pymacaroons2[rust]

Or build from source:

cd src/pymacaroons2_rs
maturin develop --release

🚀 Quick Start

Creating a Macaroon

from pymacaroons2 import Macaroon, Verifier

# Create a macaroon
m = Macaroon(
    location='https://api.example.com',
    identifier='user-12345',
    key=b'super-secret-key'
)

# Add caveats (restrictions)
m.add_first_party_caveat('action = read')
m.add_first_party_caveat('time < 2024-12-31T23:59:59Z')

# Serialize for transmission
token = m.serialize()
print(f"Token: {token}")

Verifying a Macaroon

from pymacaroons2 import Macaroon, Verifier

# Deserialize the token
m = Macaroon.deserialize(token)

# Create verifier
v = Verifier()
v.satisfy_exact('action = read')
v.satisfy_general(lambda c: c.startswith('time < '))

# Verify with the secret key
try:
    verified = v.verify(m, b'super-secret-key')
    print("✅ Macaroon verified!")
except Exception as e:
    print(f"❌ Verification failed: {e}")

Async Verification

import asyncio
from pymacaroons2 import Macaroon
from pymacaroons2.async_verifier import AsyncVerifier

async def verify_async():
    m = Macaroon(
        location='https://api.example.com',
        identifier='user-12345',
        key=b'super-secret-key'
    )

    v = AsyncVerifier()
    await v.verify_async(m, b'super-secret-key')
    print("✅ Async verification complete!")

asyncio.run(verify_async())

🔄 Migration from pymacaroons

Package rename

# Before (pymacaroons)
from pymacaroons import Macaroon, Verifier

# After (pymacaroons2)
from pymacaroons2 import Macaroon, Verifier

Breaking changes

  1. Python 3.8+ required - Python 2 and older Python 3 versions are no longer supported
  2. Package renamed - pymacaroonspymacaroons2
  3. libnacl replaced with pynacl - For third-party caveats, install pynacl

See CHANGELOG.md for complete list of changes.

⚡ Performance

With the optional Rust extension enabled:

Operation Python Rust Speedup
HMAC-SHA256 0.12s 0.02s 6.4x
Key Derivation 0.11s 0.015s 7.5x
Constant-Time Compare 0.0075s 0.005s 1.4x

Benchmarks run with 50,000 iterations on Python 3.12

📚 Documentation

Macaroon versions

from pymacaroons2 import Macaroon, MACAROON_V1, MACAROON_V2

# V1 format (default, more compatible)
m1 = Macaroon(location='...', identifier='...', key=b'...', version=MACAROON_V1)

# V2 format (more compact, binary identifiers)
m2 = Macaroon(location='...', identifier=b'\x00\x01\x02', key=b'...', version=MACAROON_V2)

Serialization formats

from pymacaroons2.serializers import JsonSerializer, BinarySerializer

# Binary (default, URL-safe base64)
token = m.serialize()

# JSON
token = m.serialize(serializer=JsonSerializer())

# Deserialize
m = Macaroon.deserialize(token)
m = Macaroon.deserialize(json_token, serializer=JsonSerializer())

Third-party caveats

# Requires: pip install pynacl

# Add third-party caveat
m.add_third_party_caveat(
    location='https://auth.example.com',
    key=b'shared-secret-with-auth-service',
    key_id='caveat-id-12345'
)

# Create discharge macaroon (at auth service)
discharge = Macaroon(
    location='https://auth.example.com',
    key=b'shared-secret-with-auth-service',
    identifier='caveat-id-12345'
)

# Bind discharge to original macaroon
bound = m.prepare_for_request(discharge)

# Verify with discharge
v = Verifier(discharge_macaroons=[bound])
v.verify(m, b'original-key')

🔐 Security

This fork addresses several security issues in the original library:

  1. Timing attack vulnerability - Now uses secrets.compare_digest() (or Rust subtle crate) for constant-time comparison
  2. Base64 decoding bug - Fixed logic error that could cause incorrect decoding
  3. Updated dependencies - Uses modern cryptography library instead of deprecated hashlib for HMAC

🛠️ Development

# Clone repository
git clone https://github.com/TazakiN/pymacaroons2.git
cd pymacaroons2

# Create virtual environment
python -m venv venv
source venv/bin/activate

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Build Rust extension (optional)
cd src/pymacaroons2_rs
maturin develop --release

📝 License

MIT License - see LICENSE for details.

Original work Copyright (c) 2014-2018 Evan Cordell
Modified work Copyright (c) 2024 Tazkia Nizami

🙏 Credits

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymacaroons2-2.0.3.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymacaroons2-2.0.3-py2.py3-none-any.whl (22.5 kB view details)

Uploaded Python 2Python 3

File details

Details for the file pymacaroons2-2.0.3.tar.gz.

File metadata

  • Download URL: pymacaroons2-2.0.3.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pymacaroons2-2.0.3.tar.gz
Algorithm Hash digest
SHA256 664163a8e816ef3697989ea088d1fbc55219cc017a70a7110aeeba60a727d3bf
MD5 414e700c6c5c43ee0a600cf86292f0fc
BLAKE2b-256 64390070836e8b4b1036837feb13213fdec63ee5b4ce5249370e85d01482a9cc

See more details on using hashes here.

File details

Details for the file pymacaroons2-2.0.3-py2.py3-none-any.whl.

File metadata

  • Download URL: pymacaroons2-2.0.3-py2.py3-none-any.whl
  • Upload date:
  • Size: 22.5 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pymacaroons2-2.0.3-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 d530c372279806d3f96d85f06d838f0ae55953eec6eac987ed66cccccf52d452
MD5 77ced665d3914f78e940313c6bdc98fe
BLAKE2b-256 35b9f7b0ea92852b4248a3ade01b687ba2211928f4e03dbff98516b8ef9585c3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page