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.0.tar.gz (19.3 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.0-py2.py3-none-any.whl (22.6 kB view details)

Uploaded Python 2Python 3

File details

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

File metadata

  • Download URL: pymacaroons2-2.0.0.tar.gz
  • Upload date:
  • Size: 19.3 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.0.tar.gz
Algorithm Hash digest
SHA256 0f69cc4a37a240adfa5806c76a881a45a4a5c78a46fe5c32739315e0dd646ba3
MD5 f63b9e2777dd416f65661bb26a0f5a3d
BLAKE2b-256 67ac8c3e2a926a9ce617629b00cf1f8a57b76f34c78743dd5dcf56642ad95b65

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pymacaroons2-2.0.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 22.6 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.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 677911f112b87b36fa1a3f5d3c1a1482236e91dbd203811c345e220e88b88a69
MD5 6e367b9da76c555d25cdc3558ce1c063
BLAKE2b-256 6ecda76b2a50e0b5b70471932a9556a099a4c28be91895a52f8d8bfa8120586c

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