Skip to main content

AEGIS Cipher Python Binding

PyPI version

Safe Python bindings for the AEGIS family of very fast authenticated encryption algorithms via libaegis. The module runs without compilation required on Windows, Mac and Linux (has precompiled wheels). For other platforms compilation is performed at install time.

AEGIS enables extremely fast Encryption, MAC and CSPRNG - many times faster than AES, ChaCha20 or traditional random number generators. Authenticated Encryption with Additional Data is supported with the MAC derived from the cipher state at the end, making it different from other AEADs like AES-GCM and ChaCha20-Poly1305. The whole internal state thus depends on the prior data, and it is neither Encrypt-Then-Mac nor Mac-The-Encrypt scheme when both features are used together.

Install

pip install aeg

Or add to your project using UV:

uv add aeg

Quick start

Normal authenticated encryption using the AEGIS-128X4 algorithm:

from aeg import aegis128x4 as ciph

key = ciph.random_key()      # Secret key (stored securely)
nonce = ciph.random_nonce()  # Public nonce (recreated for each message)
msg = b"hello"

ct = ciph.encrypt(key, nonce, msg)
pt = ciph.decrypt(key, nonce, ct)   # Raises ValueError if anything was tampered with
assert pt == msg

Variants

All submodules expose the same API; pick one for your needs. The 256 bit variants offer maximal security and use larger key and nonce, while the 128 bit variants run slightly faster and use smaller key and nonce while still providing strong security. The MAC length does not depend on the variant. Note that the x2 and x4 variants are typically the fastest (depending on CPU) by utilizing SIMD multi-lane processing for the highest throughput.

Variant Key/Nonce Bytes Notes
aegis128l 16
aegis128x2 16 Fastest on Intel Core
aegis128x4 16 Fastest on AMD and Xeon
aegis256 32
aegis256x2 32 Fast on Intel Core
aegis256x4 32 Fast on AMD and Xeon

Instead of importing the submodules, you can obtain one by its name string:

import aeg

ciph = aeg.cipher("AEGIS-128X2")   # Also accepts "aegis128x2" and other forms

API overview

Common parameters and returns (applies to all items below):

  • key: bytes of length ciph.KEYBYTES
  • nonce: bytes of length ciph.NONCEBYTES (must be unique per message)
  • message/ct: plain text or ciphertext
  • ad: optional associated data (authenticated, not encrypted)
  • into: optional output buffer (see below)
  • maclen: MAC tag length 16 or 32 bytes (default 16)

Only the first few can be positional arguments that are always provided in this order. All arguments can be passed as kwargs. The inputs can be any Buffer (e.g. bytes, bytearray, memoryview).

Most functions return a buffer of bytes. By default a bytearray of the correct size is returned. An existing buffer can be provided by into argument, in which case the bytes of it that were written to are returned as a memoryview.

One-shot AEAD

Encrypt and decrypt messages with built-in authentication:

  • encrypt(key, nonce, message, ad=None, maclen=16, into=None) -> ct_with_mac
  • decrypt(key, nonce, ct_with_mac, ad=None, maclen=16, into=None) -> plaintext

The MAC tag is handled separately of ciphertext:

  • encrypt_detached(key, nonce, message, ad=None, maclen=16, ct_into=None, mac_into=None) -> (ct, mac)
  • decrypt_detached(key, nonce, ct, mac, ad=None, into=None) -> plaintext

Incremental AEAD

Stateful classes that can be used for processing the data in separate chunks:

  • Encryptor(key, nonce, ad=None, maclen=16)
    • update(message[, into]) -> ciphertext_chunk
    • final([into]) -> mac_tag
  • Decryptor(key, nonce, ad=None, maclen=16)
    • update(ct_chunk[, into]) -> plaintext_chunk
    • final(mac) -> raises ValueError on failure

The object releases its state and becomes unusable after final has been called.

Message Authentication Code

No encryption, but prevents changes to the data without the correct key.

  • mac(key, nonce, data, maclen=16, into=None) -> mac bytes
  • Mac(key, nonce, maclen=16)
    • update(data)
    • final([into]) -> mac bytes
    • verify(mac) -> raises ValueError on failure
    • digest() -> mac bytes
    • hexdigest() -> mac str
    • reset()
    • clone() -> Mac

The Mac class follows the Python hashlib API for compatibility with code expecting hash objects. After calling final(), digest(), or hexdigest(), the Mac object becomes unusable for further update() operations. However, digest() and hexdigest() cache their results and can be called multiple times. Use reset() to clear the state and start over, or clone() to create a copy before finalizing.

Keystream generation

Useful for creating pseudo random bytes as rapidly as possible. Reuse of the same (key, nonce) creates identical output.

  • stream(key, nonce=None, length=None, into=None) -> randombytes
  • stream_xor(key, nonce, data, into=None) -> data XOR keystream (unauthenticated; encrypts and decrypts)

Miscellaneous

Constants (per module): NAME, KEYBYTES, NONCEBYTES, MACBYTES, MACBYTES_LONG, RATE, ALIGNMENT

  • random_key() -> bytearray (length KEYBYTES)
  • random_nonce() -> bytearray (length NONCEBYTES)
  • nonce_increment(nonce)
  • wipe(buffer)

Random Generator (CSPRNG)

Seeded once from the OS, then a cryptographically secure AEGIS keystream with thread local key/nonce making it thread safe. random_key() and random_nonce() draw from it. The into variant can directly fill Numpy integer arrays and other structures that support Buffer API, making it far faster than any alternatives (e.g. Numpy's own random module).

  • random().bytes(n) -> bytearray
  • random().into(buffer) -> None

Random-access encrypted files (aeg.raf)

pread/pwrite-style access to files split into independently encrypted chunks, with optional Merkle tree integrity. Storage is pluggable: a file path, io.BytesIO, aeg.raf.FileStorage / BytesIOStorage / StreamStorage, or a custom Storage.

  • raf.create(path_or_storage, key, cipher, chunk_size=65536, merkle=False) / raf.open(...)
  • f.read(size, offset), f.pread(size, offset), f.write(data, offset), f.pwrite(data, offset)
  • f.seek/tell/truncate/sync/close, context manager support
  • f.merkle_rebuild(), f.merkle_verify(), f.root_hash, f.verify_root(expected)
  • raf.probe(storage) -> RafInfo, raf.derive_master_key(key, context)

Exceptions

  • Authentication failures raise ValueError.
  • Invalid sizes/types raise TypeError.
  • Unexpected errors from libaegis raise RuntimeError.

Examples

Authentication only

A cryptographically secure keyed hash is produced. The example uses all zeroes for the nonce to always produce the same hash for the same key:

from aeg import aegis256x4 as ciph
key, nonce = ciph.random_key(), bytes(ciph.NONCEBYTES)

mac = ciph.mac(key, nonce, b"message", maclen=32)
print(mac.hex())

# Alternative class-based API
a = ciph.Mac(key, nonce, maclen=32)
a.update(b"message")
print(a.hexdigest())

# Verification
b = ciph.Mac(key, nonce, maclen=32)
b.update(b"message")
b.update(b"Mallory Says Hello!")
b.verify(mac)  # Raises ValueError

Detached mode encryption and decryption

Keeping the ciphertext, mac and ad separate. The ad represents a file header that needs to be tamper proofed.

from aeg import aegis256x4 as ciph
key, nonce = ciph.random_key(), ciph.random_nonce()

ct, mac = ciph.encrypt_detached(key, nonce, b"secret", ad=b"header")
pt = ciph.decrypt_detached(key, nonce, ct, mac, ad=b"header")
print(ct, mac, pt)

ciph.wipe(key)  # Zero out sensitive buffers after use (recommended)
ciph.wipe(pt)

Incremental updates

Class-based interface for incremental updates is an alternative to the one-shot functions. Not to be confused with separately verified ciphertext frames (see the next example).

from aeg import aegis256x4 as ciph
key, nonce = ciph.random_key(), ciph.random_nonce()

enc = ciph.Encryptor(key, nonce, ad=b"header", maclen=16)
c1 = enc.update(b"chunk1")
c2 = enc.update(b"chunk2")
mac = enc.final()

dec = ciph.Decryptor(key, nonce, ad=b"header", maclen=16)
p1 = dec.update(c1)
p2 = dec.update(c2)
dec.final(mac)               # raises ValueError on failure

Large data AEAD encryption/decryption

It is often practical to split larger messages into frames that can be individually decrypted and verified. Because every frame needs a different key, we employ the nonce_increment utility function to produce sequential nonces for each frame. As for the AEGIS algorithm, each frame is a completely independent invocation. The program will each time produce a completely different random-looking encrypted.bin file.

# Encryption settings
from aeg import aegis128x4 as ciph
key = b"sixteenbyte key!"  # 16 bytes secret key for aegis128* algorithms
framebytes = 80  # In real applications 1 MiB or more is practical
maclen = ciph.MACBYTES  # 16

message = bytearray(30 * b"Attack at dawn! ")
with open("encrypted.bin", "wb") as f:
    # Public initial nonce sent with the ciphertext
    nonce = ciph.random_nonce()
    f.write(nonce)
    while message:
        chunk = message[:framebytes - maclen]
        del message[:len(chunk)]
        ct = ciph.encrypt(key, nonce, chunk, maclen=maclen)
        ciph.nonce_increment(nonce)
        f.write(ct)
# Decryption needs same values as encryption
from aeg import aegis128x4 as ciph
key = b"sixteenbyte key!"
framebytes = 80
maclen = ciph.MACBYTES

with open("encrypted.bin", "rb") as f:
    nonce = bytearray(f.read(ciph.NONCEBYTES))
    while True:
        frame = f.read(framebytes)
        if not frame:
            break
        pt = ciph.decrypt(key, nonce, frame, maclen=maclen)
        ciph.nonce_increment(nonce)
        print(pt)

Random generator

The stream generator is much faster than any traditional random number generator, cryptographically secure and seekable. Use random_key() for unpredictable output.

from aeg import aegis128x4 as ciph

key = b"SeedForReplay001"  # A non-random deterministic seed (16 bytes)
nonce = bytearray(ciph.NONCEBYTES)  # All-zeroes nonce

# Generate multiple blocks of pseudorandom data
for i in range(5):
    rand = ciph.stream(key, nonce, 10)
    print(f"Block {int.from_bytes(nonce, "little")}: {rand.hex()}")
    ciph.nonce_increment(nonce)

Note: this is seekable by converting the block number to nonce with idx.to_bytes(ciph.NONCEBYTES, "little"), given some fixed block size (e.g. 1 MiB).

Preallocated output buffers (into=)

For advanced use cases, the output buffer can be supplied with into kwarg. Any type of writable buffer with a sufficient number of bytes can be used. This includes bytearrays, memoryviews, mmap files, numpy arrays etc.

A TypeError is raised if the buffer is too small. For convenience, the functions return a memoryview showing only the bytes actually written.

For sensitive data, aeg.securebuf.SecureBuffer provides memory locked against swapping and excluded from core dumps, wiped on close:

from aeg.securebuf import SecureBuffer
with SecureBuffer(1024) as buf:
    pt = ciph.decrypt(key, nonce, ct, into=buf)

Foreign arrays can be used. This example fills a Numpy array with random integers.

import numpy as np
from aeg import aegis128x4 as ciph
key, nonce = ciph.random_key(), ciph.random_nonce()

arr = np.empty(10, dtype=np.uint64)  # Uninitialised integer array
ciph.stream(key, nonce, into=arr)    # Fill with random bytes
print(arr)

In-place operations are supported when the input and the output point to the same location in memory. When using attached MAC tag, the input buffer needs to be sliced to correct length:

from aeg import aegis256x4 as ciph
key, nonce = ciph.random_key(), ciph.random_nonce()
buf = memoryview(bytearray(1000))  # memoryview[:len] is still in the same buffer (no copy)
buf[:7] = b"message"

# Each function returns a memoryview capped to correct length
ct = ciph.encrypt(key, nonce, buf[:7], into=buf)
pt = ciph.decrypt(key, nonce, ct, into=buf)

print(bytes(pt))

Detached mode can use same size input and output (no MAC added to ciphertext). Detached encryption instead of into takes ct_into and mac_into separately and returns memoryviews to both.

Performance

Runtime CPU feature detection selects optimized code paths (AES-NI, ARM Crypto, AVX2/AVX-512). Multi-lane variants (x2/x4) offer higher throughput on suitable CPUs.

Benchmarks using the included benchmark module, run on Intel i7-14700, linux, single core (the software is not multithreaded). Note that the results are in megabits per second, not bytes. The CPU lacks AVX-512 that makes the X4 variants faster on processors supporting it (most AMD, Xeon).

uv run -m aeg.benchmark
AEGIS-256        103166.24 Mb/s
AEGIS-256X2      184225.50 Mb/s
AEGIS-256X4      194018.26 Mb/s
AEGIS-128L       161551.73 Mb/s
AEGIS-128X2      281987.80 Mb/s
AEGIS-128X4      217997.37 Mb/s
AEGIS-128L MAC   188886.40 Mb/s
AEGIS-128X2 MAC  306457.97 Mb/s
AEGIS-128X4 MAC  299576.59 Mb/s
AEGIS-256 MAC    100914.04 Mb/s
AEGIS-256X2 MAC  190208.20 Mb/s
AEGIS-256X4 MAC  315919.87 Mb/s

The Python library performance is similar to that of the C library:

./libaegis/zig-out/bin/benchmark
AEGIS-256        107820.86 Mb/s
AEGIS-256X2      205025.57 Mb/s
AEGIS-256X4      223361.81 Mb/s
AEGIS-128L       187530.77 Mb/s
AEGIS-128X2      354003.14 Mb/s
AEGIS-128X4      218596.59 Mb/s
AEGIS-128L MAC   224276.49 Mb/s
AEGIS-128X2 MAC  417741.65 Mb/s
AEGIS-128X4 MAC  410454.05 Mb/s
AEGIS-256 MAC    116776.62 Mb/s
AEGIS-256X2 MAC  224150.04 Mb/s
AEGIS-256X4 MAC  392088.05 Mb/s

Alternatives

There is also a package named pyaegis on PyPI that is unrelated to this module, but that also binds to the libaegis C library. There are also a number of modules named aegis from different packages not at all related to the encryption algorithm.

Metadata

Release files for aeg 0.10.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aeg 0.10.6
File Size Uploaded
aeg-0.10.6.tar.gz 688.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for aeg 0.10.6
File
aeg-0.10.6-cp315-cp315t-win_amd64.whl CPython 3.15 CPython 3.15 free-threading Windows x86-64 Details
aeg-0.10.6-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.15 CPython 3.15 free-threading Linux glibc 2.17+ x86-64 Details
aeg-0.10.6-cp315-cp315t-macosx_11_0_arm64.whl CPython 3.15 CPython 3.15 free-threading macOS 11.0+ ARM64 Details
aeg-0.10.6-cp314-cp314t-win_amd64.whl CPython 3.14 CPython 3.14 free-threading Windows x86-64 Details
aeg-0.10.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64 Details
aeg-0.10.6-cp314-cp314t-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64 Details
aeg-0.10.6-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
aeg-0.10.6-cp312-abi3-manylinux_2_36_x86_64.whl CPython 3.12 abi3 Linux glibc 2.36+ x86-64 Details
aeg-0.10.6-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details

Total release size: 3.7 MB

Release files / aeg-0.10.6.tar.gz

Download URL aeg-0.10.6.tar.gz
Size 688.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a62e60ecf99226cb94469fccc91e7dd2e364f75f65c3188e386526cbc51437cb
BLAKE2b-256 checksum
How to use checksums
32371daf16851613d6354c52475c4c55b8f3c6c541cb1a647a795061e42224b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp315-cp315t-win_amd64.whl

Download URL aeg-0.10.6-cp315-cp315t-win_amd64.whl
Size 283.9 kB
Tags CPython 3.15 CPython 3.15 free-threading Windows x86-64
SHA-256 checksum
How to use checksums
07686c1fb90acf9bd0e961aa81e7dbf0cc76f3cc5070b27de466a77f577748fa
BLAKE2b-256 checksum
How to use checksums
400f43d2504dcde2ad15620f99a58b074e8b2b586f877d575725a3361fb326d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL aeg-0.10.6-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 511.1 kB
Tags CPython 3.15 CPython 3.15 free-threading Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
cce57b786ea0db537805fb389ad3b87924c640fd0004106a59b9b706bf846391
BLAKE2b-256 checksum
How to use checksums
9efbff54ced881635297ff68317030c2f7edaec3015bddb31250139a5ab49af6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp315-cp315t-macosx_11_0_arm64.whl

Download URL aeg-0.10.6-cp315-cp315t-macosx_11_0_arm64.whl
Size 211.5 kB
Tags CPython 3.15 CPython 3.15 free-threading macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a081f9890a7c793fe37fce072f470c1c4bc46db6e474e25c1a676f28e07e3a59
BLAKE2b-256 checksum
How to use checksums
f8cb31ea92fc4ef4e207e92d6f83e224a488f122e62c77e132b098a7dfcfc522
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp314-cp314t-win_amd64.whl

Download URL aeg-0.10.6-cp314-cp314t-win_amd64.whl
Size 284.9 kB
Tags CPython 3.14 CPython 3.14 free-threading Windows x86-64
SHA-256 checksum
How to use checksums
f67bdbf586a97dfcd521e80a5c836963f119c8a2335684dd5567082dc9183632
BLAKE2b-256 checksum
How to use checksums
1dc537e05748ba6a679967480a98af81dcb39c2fe5a86ad8d0126d98f355d4bc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL aeg-0.10.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 511.0 kB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
2baac6b146326ba5ae6aa0dc5e9701899d30346e995d053eb4c383d0ee6025fb
BLAKE2b-256 checksum
How to use checksums
c9b8ef67be5bd19a43a314009d1abdbf57242db28b8c208852167afe5a356229
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp314-cp314t-macosx_11_0_arm64.whl

Download URL aeg-0.10.6-cp314-cp314t-macosx_11_0_arm64.whl
Size 211.5 kB
Tags CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d2c4d6a9d6d197048579cec8573955e86b7a0748372c0856567d706cc4a35eaf
BLAKE2b-256 checksum
How to use checksums
6b311e0d1e85ad6857487bfff4254af45687ba9cd03637be396470313557bb43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp312-abi3-win_amd64.whl

Download URL aeg-0.10.6-cp312-abi3-win_amd64.whl
Size 283.2 kB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
ed180ce82d0761df03d05e9d80b1abf5c9bcba5f3a1b48975003951c84431733
BLAKE2b-256 checksum
How to use checksums
dc92be1c292ab10ad4aa7e078d87033d7448e8148c1e1902a9dedfee51822d08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp312-abi3-manylinux_2_36_x86_64.whl

Download URL aeg-0.10.6-cp312-abi3-manylinux_2_36_x86_64.whl
Size 544.7 kB
Tags CPython 3.12 Linux glibc 2.36+ x86-64 abi3
SHA-256 checksum
How to use checksums
f36b283e0dd03389206b7a146f65cf9a8093c077cb0365907e48ebe8bfba16f8
BLAKE2b-256 checksum
How to use checksums
388b424121545e263fb9a56934ec135f9672bcd80481ce5cd459ef9b834ef3aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / aeg-0.10.6-cp312-abi3-macosx_11_0_arm64.whl

Download URL aeg-0.10.6-cp312-abi3-macosx_11_0_arm64.whl
Size 210.9 kB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
981dea2723879ff6a953c0baebff980afed8261afb4ece79dd0243234df3db92
BLAKE2b-256 checksum
How to use checksums
5cbc939f3e43546677d6dc41e64f06c9abb082d7d7ad964bf8efe88993f49fb3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

0.10.6 This release

10 release files

0.9.0

16 release files

0.4.3

18 release files

0.4.2

5 release files

0.4.1

16 release files

0.4.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page