Constants renamed and values extracted from C code rather than function call at runtime. Documentation update.
This commit is contained in:
20
README.md
20
README.md
@@ -42,8 +42,8 @@ assert pt == msg
|
|||||||
|
|
||||||
Common parameters and returns (applies to all items below):
|
Common parameters and returns (applies to all items below):
|
||||||
|
|
||||||
- key: bytes of length a.KEYBYTES
|
- key: bytes of length ciph.KEYBYTES
|
||||||
- nonce: bytes of length a.NPUBBYTES (must be unique per (key, message))
|
- nonce: bytes of length ciph.NONCEBYTES (must be unique per message)
|
||||||
- message/ct: plain text or ciphertext
|
- message/ct: plain text or ciphertext
|
||||||
- ad: optional associated data (authenticated, not encrypted)
|
- ad: optional associated data (authenticated, not encrypted)
|
||||||
- into: optional output buffer (see below)
|
- into: optional output buffer (see below)
|
||||||
@@ -95,10 +95,10 @@ Useful for creating pseudo random bytes as rapidly as possible. Reuse of the sam
|
|||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
||||||
Constants (per module): KEYBYTES, NPUBBYTES, ABYTES_MIN, ABYTES_MAX, RATE, ALIGNMENT
|
Constants (per module): KEYBYTES, NONCEBYTES, MACBYTES, MACBYTES_LONG, RATE, ALIGNMENT
|
||||||
|
|
||||||
- random_key() -> bytearray (length KEYBYTES)
|
- random_key() -> bytearray (length KEYBYTES)
|
||||||
- random_nonce() -> bytearray (length NPUBBYTES)
|
- random_nonce() -> bytearray (length NONCEBYTES)
|
||||||
- nonce_increment(nonce)
|
- nonce_increment(nonce)
|
||||||
- wipe(buffer)
|
- wipe(buffer)
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ Constants (per module): KEYBYTES, NPUBBYTES, ABYTES_MIN, ABYTES_MAX, RATE, ALIGN
|
|||||||
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:
|
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:
|
||||||
```python
|
```python
|
||||||
from pyaegis import aegis256x4 as ciph
|
from pyaegis import aegis256x4 as ciph
|
||||||
key, nonce = ciph.random_key(), bytes(ciph.NPUBBYTES)
|
key, nonce = ciph.random_key(), bytes(ciph.NONCEBYTES)
|
||||||
|
|
||||||
mac = ciph.mac(key, nonce, b"message", maclen=32)
|
mac = ciph.mac(key, nonce, b"message", maclen=32)
|
||||||
print(mac)
|
print(mac)
|
||||||
@@ -151,12 +151,12 @@ Class-based interface for incremental updates is an alternative to the one-shot
|
|||||||
from pyaegis import aegis256x4 as ciph
|
from pyaegis import aegis256x4 as ciph
|
||||||
key, nonce = ciph.random_key(), ciph.random_nonce()
|
key, nonce = ciph.random_key(), ciph.random_nonce()
|
||||||
|
|
||||||
enc = a.Encryptor(key, nonce, ad=b"header")
|
enc = ciph.Encryptor(key, nonce, ad=b"header")
|
||||||
c1 = enc.update(b"chunk1")
|
c1 = enc.update(b"chunk1")
|
||||||
c2 = enc.update(b"chunk2")
|
c2 = enc.update(b"chunk2")
|
||||||
mac = enc.final(maclen=16)
|
mac = enc.final(maclen=16)
|
||||||
|
|
||||||
dec = a.Decryptor(key, nonce, ad=b"header")
|
dec = ciph.Decryptor(key, nonce, ad=b"header")
|
||||||
p1 = dec.update(c1)
|
p1 = dec.update(c1)
|
||||||
p2 = dec.update(c2)
|
p2 = dec.update(c2)
|
||||||
dec.final(mac) # raises ValueError on failure
|
dec.final(mac) # raises ValueError on failure
|
||||||
@@ -173,7 +173,7 @@ message = bytearray(30 * b"Attack at dawn! ")
|
|||||||
key = b"sixteenbyte key!" # 16 bytes secret key for aegis128* algorithms
|
key = b"sixteenbyte key!" # 16 bytes secret key for aegis128* algorithms
|
||||||
nonce = ciph.random_nonce()
|
nonce = ciph.random_nonce()
|
||||||
framebytes = 80 # In real applications 1 MiB or more is practical
|
framebytes = 80 # In real applications 1 MiB or more is practical
|
||||||
maclen = ciph.ABYTES_MIN # 16
|
maclen = ciph.MACBYTES # 16
|
||||||
|
|
||||||
with open("encrypted.bin", "wb") as f:
|
with open("encrypted.bin", "wb") as f:
|
||||||
f.write(nonce) # Public initial nonce sent with the ciphertext
|
f.write(nonce) # Public initial nonce sent with the ciphertext
|
||||||
@@ -191,10 +191,10 @@ from pyaegis import aegis128x4 as ciph
|
|||||||
# Decryption needs same values as encryption
|
# Decryption needs same values as encryption
|
||||||
key = b"sixteenbyte key!"
|
key = b"sixteenbyte key!"
|
||||||
framebytes = 80
|
framebytes = 80
|
||||||
maclen = ciph.ABYTES_MIN
|
maclen = ciph.MACBYTES
|
||||||
|
|
||||||
with open("encrypted.bin", "rb") as f:
|
with open("encrypted.bin", "rb") as f:
|
||||||
nonce = bytearray(f.read(ciph.NPUBBYTES))
|
nonce = bytearray(f.read(ciph.NONCEBYTES))
|
||||||
while True:
|
while True:
|
||||||
frame = f.read(framebytes)
|
frame = f.read(framebytes)
|
||||||
if not frame:
|
if not frame:
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ from ._loader import ffi
|
|||||||
from ._loader import lib as _lib
|
from ._loader import lib as _lib
|
||||||
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
||||||
|
|
||||||
# Constants exposed as functions in C; mirror them as integers at module import time
|
KEYBYTES = 16 #: Key size in bytes (varies by algorithm)
|
||||||
KEYBYTES = _lib.aegis128l_keybytes()
|
NONCEBYTES = 16 #: Nonce size in bytes (varies by algorithm)
|
||||||
NPUBBYTES = _lib.aegis128l_npubbytes()
|
MACBYTES = 16 #: Normal MAC size (always 16)
|
||||||
ABYTES_MIN = _lib.aegis128l_abytes_min()
|
MACBYTES_LONG = 32 #: Long MAC size (always 32)
|
||||||
ABYTES_MAX = _lib.aegis128l_abytes_max()
|
ALIGNMENT = 64 #: Required alignment for internal structures
|
||||||
TAILBYTES_MAX = _lib.aegis128l_tailbytes_max()
|
RATE = 64 #: Byte chunk size in internal processing
|
||||||
ALIGNMENT = 32
|
|
||||||
RATE = 32
|
|
||||||
|
|
||||||
|
|
||||||
def random_key() -> bytearray:
|
def random_key() -> bytearray:
|
||||||
"""Generate a random key using cryptographically secure random bytes."""
|
"""
|
||||||
|
Generate a random key using cryptographically secure random bytes.
|
||||||
|
|
||||||
|
It is recommended to wipe() the key after no longer needed to keep it secret.
|
||||||
|
"""
|
||||||
return bytearray(secrets.token_bytes(KEYBYTES))
|
return bytearray(secrets.token_bytes(KEYBYTES))
|
||||||
|
|
||||||
|
|
||||||
def random_nonce() -> bytearray:
|
def random_nonce() -> bytearray:
|
||||||
"""Generate a random nonce using cryptographically secure random bytes."""
|
"""Generate a random nonce using cryptographically secure random bytes."""
|
||||||
return bytearray(secrets.token_bytes(NPUBBYTES))
|
return bytearray(secrets.token_bytes(NONCEBYTES))
|
||||||
|
|
||||||
|
|
||||||
def _ptr(buf):
|
def _ptr(buf):
|
||||||
@@ -39,7 +41,7 @@ def encrypt_detached(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
ct_into: Buffer | None = None,
|
ct_into: Buffer | None = None,
|
||||||
mac_into: Buffer | None = None,
|
mac_into: Buffer | None = None,
|
||||||
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
||||||
@@ -47,7 +49,7 @@ def encrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -65,8 +67,8 @@ def encrypt_detached(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
|
|
||||||
if ct_into is None:
|
if ct_into is None:
|
||||||
c = bytearray(len(message))
|
c = bytearray(len(message))
|
||||||
@@ -115,7 +117,7 @@ def decrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
mac: The MAC to verify.
|
mac: The MAC to verify.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
@@ -130,8 +132,8 @@ def decrypt_detached(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
maclen = len(mac)
|
maclen = len(mac)
|
||||||
if maclen not in (16, 32):
|
if maclen not in (16, 32):
|
||||||
raise TypeError("mac length must be 16 or 32")
|
raise TypeError("mac length must be 16 or 32")
|
||||||
@@ -164,14 +166,14 @@ def encrypt(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -188,8 +190,8 @@ def encrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message) + maclen)
|
out = bytearray(len(message) + maclen)
|
||||||
else:
|
else:
|
||||||
@@ -220,14 +222,14 @@ def decrypt(
|
|||||||
ct: Buffer,
|
ct: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Decrypt ciphertext with appended MAC and associated data.
|
f"""Decrypt ciphertext with appended MAC and associated data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext with MAC to decrypt.
|
ct: The ciphertext with MAC to decrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -244,8 +246,8 @@ def decrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if len(ct) < maclen:
|
if len(ct) < maclen:
|
||||||
raise TypeError("ciphertext too short for tag")
|
raise TypeError("ciphertext too short for tag")
|
||||||
expected_out = len(ct) - maclen
|
expected_out = len(ct) - maclen
|
||||||
@@ -284,7 +286,7 @@ def stream(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}, uses zeroes for nonce if None).
|
nonce: Nonce ({NONCEBYTES=}, uses zeroes for nonce if None).
|
||||||
length: Number of bytes to generate (required if into is None).
|
length: Number of bytes to generate (required if into is None).
|
||||||
into: Buffer to write stream into (default: bytearray created).
|
into: Buffer to write stream into (default: bytearray created).
|
||||||
|
|
||||||
@@ -296,8 +298,8 @@ def stream(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if nonce is not None and len(nonce) != NPUBBYTES:
|
if nonce is not None and len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
if length is None:
|
if length is None:
|
||||||
raise TypeError("provide either into or length")
|
raise TypeError("provide either into or length")
|
||||||
@@ -326,7 +328,7 @@ def encrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
into: Buffer to write ciphertext into (default: bytearray created).
|
into: Buffer to write ciphertext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -338,8 +340,8 @@ def encrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message))
|
out = bytearray(len(message))
|
||||||
else:
|
else:
|
||||||
@@ -367,7 +369,7 @@ def decrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
into: Buffer to write plaintext into (default: bytearray created).
|
into: Buffer to write plaintext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -379,8 +381,8 @@ def decrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(ct))
|
out = bytearray(len(ct))
|
||||||
else:
|
else:
|
||||||
@@ -402,14 +404,14 @@ def mac(
|
|||||||
key: Buffer,
|
key: Buffer,
|
||||||
nonce: Buffer,
|
nonce: Buffer,
|
||||||
data: Buffer,
|
data: Buffer,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Compute a MAC for the given data in one shot.
|
f"""Compute a MAC for the given data in one shot.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=})
|
key: Key ({KEYBYTES=})
|
||||||
nonce: Nonce ({NPUBBYTES=})
|
nonce: Nonce ({NONCEBYTES=})
|
||||||
data: Data to MAC
|
data: Data to MAC
|
||||||
maclen: MAC length (16 or 32, default 16)
|
maclen: MAC length (16 or 32, default 16)
|
||||||
into: Buffer to write MAC into (default: bytearray created)
|
into: Buffer to write MAC into (default: bytearray created)
|
||||||
@@ -445,7 +447,7 @@ class Mac:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
TypeError: If key or nonce lengths are invalid.
|
TypeError: If key or nonce lengths are invalid.
|
||||||
@@ -459,8 +461,8 @@ class Mac:
|
|||||||
# Normal init path
|
# Normal init path
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
_lib.aegis128l_mac_init(self._st, _ptr(key), _ptr(nonce))
|
_lib.aegis128l_mac_init(self._st, _ptr(key), _ptr(nonce))
|
||||||
|
|
||||||
def __deepcopy__(self) -> "Mac":
|
def __deepcopy__(self) -> "Mac":
|
||||||
@@ -490,7 +492,7 @@ class Mac:
|
|||||||
|
|
||||||
def final(
|
def final(
|
||||||
self,
|
self,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize and return the MAC tag.
|
"""Finalize and return the MAC tag.
|
||||||
@@ -558,7 +560,7 @@ class Encryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data to bind to the encryption (optional).
|
ad: Associated data to bind to the encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -566,8 +568,8 @@ class Encryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis128l_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis128l_state", ALIGNMENT)
|
||||||
_lib.aegis128l_state_init(
|
_lib.aegis128l_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -639,7 +641,7 @@ class Encryptor:
|
|||||||
return out if into is None else memoryview(out)[:w] # type: ignore
|
return out if into is None else memoryview(out)[:w] # type: ignore
|
||||||
|
|
||||||
def final(
|
def final(
|
||||||
self, into: Buffer | None = None, maclen: int = ABYTES_MIN
|
self, into: Buffer | None = None, maclen: int = MACBYTES
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize encryption, writing any remaining bytes and the tag.
|
"""Finalize encryption, writing any remaining bytes and the tag.
|
||||||
|
|
||||||
@@ -692,7 +694,7 @@ class Decryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data used during encryption (optional).
|
ad: Associated data used during encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -700,8 +702,8 @@ class Decryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis128l_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis128l_state", ALIGNMENT)
|
||||||
_lib.aegis128l_state_init(
|
_lib.aegis128l_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -796,10 +798,9 @@ def new_mac_state():
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
# constants
|
# constants
|
||||||
"KEYBYTES",
|
"KEYBYTES",
|
||||||
"NPUBBYTES",
|
"NONCEBYTES",
|
||||||
"ABYTES_MIN",
|
"MACBYTES",
|
||||||
"ABYTES_MAX",
|
"MACBYTES_LONG",
|
||||||
"TAILBYTES_MAX",
|
|
||||||
"ALIGNMENT",
|
"ALIGNMENT",
|
||||||
"RATE",
|
"RATE",
|
||||||
# utility functions
|
# utility functions
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ from ._loader import ffi
|
|||||||
from ._loader import lib as _lib
|
from ._loader import lib as _lib
|
||||||
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
||||||
|
|
||||||
# Constants exposed as functions in C; mirror them as integers at module import time
|
KEYBYTES = 16 #: Key size in bytes (varies by algorithm)
|
||||||
KEYBYTES = _lib.aegis128x2_keybytes()
|
NONCEBYTES = 16 #: Nonce size in bytes (varies by algorithm)
|
||||||
NPUBBYTES = _lib.aegis128x2_npubbytes()
|
MACBYTES = 16 #: Normal MAC size (always 16)
|
||||||
ABYTES_MIN = _lib.aegis128x2_abytes_min()
|
MACBYTES_LONG = 32 #: Long MAC size (always 32)
|
||||||
ABYTES_MAX = _lib.aegis128x2_abytes_max()
|
ALIGNMENT = 64 #: Required alignment for internal structures
|
||||||
TAILBYTES_MAX = _lib.aegis128x2_tailbytes_max()
|
RATE = 64 #: Byte chunk size in internal processing
|
||||||
ALIGNMENT = 64
|
|
||||||
RATE = 64
|
|
||||||
|
|
||||||
|
|
||||||
def random_key() -> bytearray:
|
def random_key() -> bytearray:
|
||||||
"""Generate a random key using cryptographically secure random bytes."""
|
"""
|
||||||
|
Generate a random key using cryptographically secure random bytes.
|
||||||
|
|
||||||
|
It is recommended to wipe() the key after no longer needed to keep it secret.
|
||||||
|
"""
|
||||||
return bytearray(secrets.token_bytes(KEYBYTES))
|
return bytearray(secrets.token_bytes(KEYBYTES))
|
||||||
|
|
||||||
|
|
||||||
def random_nonce() -> bytearray:
|
def random_nonce() -> bytearray:
|
||||||
"""Generate a random nonce using cryptographically secure random bytes."""
|
"""Generate a random nonce using cryptographically secure random bytes."""
|
||||||
return bytearray(secrets.token_bytes(NPUBBYTES))
|
return bytearray(secrets.token_bytes(NONCEBYTES))
|
||||||
|
|
||||||
|
|
||||||
def _ptr(buf):
|
def _ptr(buf):
|
||||||
@@ -39,7 +41,7 @@ def encrypt_detached(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
ct_into: Buffer | None = None,
|
ct_into: Buffer | None = None,
|
||||||
mac_into: Buffer | None = None,
|
mac_into: Buffer | None = None,
|
||||||
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
||||||
@@ -47,7 +49,7 @@ def encrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -65,8 +67,8 @@ def encrypt_detached(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
|
|
||||||
if ct_into is None:
|
if ct_into is None:
|
||||||
c = bytearray(len(message))
|
c = bytearray(len(message))
|
||||||
@@ -115,7 +117,7 @@ def decrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
mac: The MAC to verify.
|
mac: The MAC to verify.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
@@ -130,8 +132,8 @@ def decrypt_detached(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
maclen = len(mac)
|
maclen = len(mac)
|
||||||
if maclen not in (16, 32):
|
if maclen not in (16, 32):
|
||||||
raise TypeError("mac length must be 16 or 32")
|
raise TypeError("mac length must be 16 or 32")
|
||||||
@@ -164,14 +166,14 @@ def encrypt(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -188,8 +190,8 @@ def encrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message) + maclen)
|
out = bytearray(len(message) + maclen)
|
||||||
else:
|
else:
|
||||||
@@ -220,14 +222,14 @@ def decrypt(
|
|||||||
ct: Buffer,
|
ct: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Decrypt ciphertext with appended MAC and associated data.
|
f"""Decrypt ciphertext with appended MAC and associated data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext with MAC to decrypt.
|
ct: The ciphertext with MAC to decrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -244,8 +246,8 @@ def decrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if len(ct) < maclen:
|
if len(ct) < maclen:
|
||||||
raise TypeError("ciphertext too short for tag")
|
raise TypeError("ciphertext too short for tag")
|
||||||
expected_out = len(ct) - maclen
|
expected_out = len(ct) - maclen
|
||||||
@@ -284,7 +286,7 @@ def stream(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}, uses zeroes for nonce if None).
|
nonce: Nonce ({NONCEBYTES=}, uses zeroes for nonce if None).
|
||||||
length: Number of bytes to generate (required if into is None).
|
length: Number of bytes to generate (required if into is None).
|
||||||
into: Buffer to write stream into (default: bytearray created).
|
into: Buffer to write stream into (default: bytearray created).
|
||||||
|
|
||||||
@@ -296,8 +298,8 @@ def stream(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if nonce is not None and len(nonce) != NPUBBYTES:
|
if nonce is not None and len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
if length is None:
|
if length is None:
|
||||||
raise TypeError("provide either into or length")
|
raise TypeError("provide either into or length")
|
||||||
@@ -326,7 +328,7 @@ def encrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
into: Buffer to write ciphertext into (default: bytearray created).
|
into: Buffer to write ciphertext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -338,8 +340,8 @@ def encrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message))
|
out = bytearray(len(message))
|
||||||
else:
|
else:
|
||||||
@@ -367,7 +369,7 @@ def decrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
into: Buffer to write plaintext into (default: bytearray created).
|
into: Buffer to write plaintext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -379,8 +381,8 @@ def decrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(ct))
|
out = bytearray(len(ct))
|
||||||
else:
|
else:
|
||||||
@@ -402,14 +404,14 @@ def mac(
|
|||||||
key: Buffer,
|
key: Buffer,
|
||||||
nonce: Buffer,
|
nonce: Buffer,
|
||||||
data: Buffer,
|
data: Buffer,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Compute a MAC for the given data in one shot.
|
f"""Compute a MAC for the given data in one shot.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=})
|
key: Key ({KEYBYTES=})
|
||||||
nonce: Nonce ({NPUBBYTES=})
|
nonce: Nonce ({NONCEBYTES=})
|
||||||
data: Data to MAC
|
data: Data to MAC
|
||||||
maclen: MAC length (16 or 32, default 16)
|
maclen: MAC length (16 or 32, default 16)
|
||||||
into: Buffer to write MAC into (default: bytearray created)
|
into: Buffer to write MAC into (default: bytearray created)
|
||||||
@@ -445,7 +447,7 @@ class Mac:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
TypeError: If key or nonce lengths are invalid.
|
TypeError: If key or nonce lengths are invalid.
|
||||||
@@ -459,8 +461,8 @@ class Mac:
|
|||||||
# Normal init path
|
# Normal init path
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
_lib.aegis128x2_mac_init(self._st, _ptr(key), _ptr(nonce))
|
_lib.aegis128x2_mac_init(self._st, _ptr(key), _ptr(nonce))
|
||||||
|
|
||||||
def __deepcopy__(self) -> "Mac":
|
def __deepcopy__(self) -> "Mac":
|
||||||
@@ -490,7 +492,7 @@ class Mac:
|
|||||||
|
|
||||||
def final(
|
def final(
|
||||||
self,
|
self,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize and return the MAC tag.
|
"""Finalize and return the MAC tag.
|
||||||
@@ -558,7 +560,7 @@ class Encryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data to bind to the encryption (optional).
|
ad: Associated data to bind to the encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -566,8 +568,8 @@ class Encryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis128x2_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis128x2_state", ALIGNMENT)
|
||||||
_lib.aegis128x2_state_init(
|
_lib.aegis128x2_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -639,7 +641,7 @@ class Encryptor:
|
|||||||
return out if into is None else memoryview(out)[:w] # type: ignore
|
return out if into is None else memoryview(out)[:w] # type: ignore
|
||||||
|
|
||||||
def final(
|
def final(
|
||||||
self, into: Buffer | None = None, maclen: int = ABYTES_MIN
|
self, into: Buffer | None = None, maclen: int = MACBYTES
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize encryption, writing any remaining bytes and the tag.
|
"""Finalize encryption, writing any remaining bytes and the tag.
|
||||||
|
|
||||||
@@ -692,7 +694,7 @@ class Decryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data used during encryption (optional).
|
ad: Associated data used during encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -700,8 +702,8 @@ class Decryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis128x2_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis128x2_state", ALIGNMENT)
|
||||||
_lib.aegis128x2_state_init(
|
_lib.aegis128x2_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -796,10 +798,9 @@ def new_mac_state():
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
# constants
|
# constants
|
||||||
"KEYBYTES",
|
"KEYBYTES",
|
||||||
"NPUBBYTES",
|
"NONCEBYTES",
|
||||||
"ABYTES_MIN",
|
"MACBYTES",
|
||||||
"ABYTES_MAX",
|
"MACBYTES_LONG",
|
||||||
"TAILBYTES_MAX",
|
|
||||||
"ALIGNMENT",
|
"ALIGNMENT",
|
||||||
"RATE",
|
"RATE",
|
||||||
# utility functions
|
# utility functions
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ from ._loader import ffi
|
|||||||
from ._loader import lib as _lib
|
from ._loader import lib as _lib
|
||||||
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
||||||
|
|
||||||
# Constants exposed as functions in C; mirror them as integers at module import time
|
KEYBYTES = 16 #: Key size in bytes (varies by algorithm)
|
||||||
KEYBYTES = _lib.aegis128x4_keybytes()
|
NONCEBYTES = 16 #: Nonce size in bytes (varies by algorithm)
|
||||||
NPUBBYTES = _lib.aegis128x4_npubbytes()
|
MACBYTES = 16 #: Normal MAC size (always 16)
|
||||||
ABYTES_MIN = _lib.aegis128x4_abytes_min()
|
MACBYTES_LONG = 32 #: Long MAC size (always 32)
|
||||||
ABYTES_MAX = _lib.aegis128x4_abytes_max()
|
ALIGNMENT = 64 #: Required alignment for internal structures
|
||||||
TAILBYTES_MAX = _lib.aegis128x4_tailbytes_max()
|
RATE = 64 #: Byte chunk size in internal processing
|
||||||
ALIGNMENT = 64
|
|
||||||
RATE = 128
|
|
||||||
|
|
||||||
|
|
||||||
def random_key() -> bytearray:
|
def random_key() -> bytearray:
|
||||||
"""Generate a random key using cryptographically secure random bytes."""
|
"""
|
||||||
|
Generate a random key using cryptographically secure random bytes.
|
||||||
|
|
||||||
|
It is recommended to wipe() the key after no longer needed to keep it secret.
|
||||||
|
"""
|
||||||
return bytearray(secrets.token_bytes(KEYBYTES))
|
return bytearray(secrets.token_bytes(KEYBYTES))
|
||||||
|
|
||||||
|
|
||||||
def random_nonce() -> bytearray:
|
def random_nonce() -> bytearray:
|
||||||
"""Generate a random nonce using cryptographically secure random bytes."""
|
"""Generate a random nonce using cryptographically secure random bytes."""
|
||||||
return bytearray(secrets.token_bytes(NPUBBYTES))
|
return bytearray(secrets.token_bytes(NONCEBYTES))
|
||||||
|
|
||||||
|
|
||||||
def _ptr(buf):
|
def _ptr(buf):
|
||||||
@@ -39,7 +41,7 @@ def encrypt_detached(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
ct_into: Buffer | None = None,
|
ct_into: Buffer | None = None,
|
||||||
mac_into: Buffer | None = None,
|
mac_into: Buffer | None = None,
|
||||||
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
||||||
@@ -47,7 +49,7 @@ def encrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -65,8 +67,8 @@ def encrypt_detached(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
|
|
||||||
if ct_into is None:
|
if ct_into is None:
|
||||||
c = bytearray(len(message))
|
c = bytearray(len(message))
|
||||||
@@ -115,7 +117,7 @@ def decrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
mac: The MAC to verify.
|
mac: The MAC to verify.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
@@ -130,8 +132,8 @@ def decrypt_detached(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
maclen = len(mac)
|
maclen = len(mac)
|
||||||
if maclen not in (16, 32):
|
if maclen not in (16, 32):
|
||||||
raise TypeError("mac length must be 16 or 32")
|
raise TypeError("mac length must be 16 or 32")
|
||||||
@@ -164,14 +166,14 @@ def encrypt(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -188,8 +190,8 @@ def encrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message) + maclen)
|
out = bytearray(len(message) + maclen)
|
||||||
else:
|
else:
|
||||||
@@ -220,14 +222,14 @@ def decrypt(
|
|||||||
ct: Buffer,
|
ct: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Decrypt ciphertext with appended MAC and associated data.
|
f"""Decrypt ciphertext with appended MAC and associated data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext with MAC to decrypt.
|
ct: The ciphertext with MAC to decrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -244,8 +246,8 @@ def decrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if len(ct) < maclen:
|
if len(ct) < maclen:
|
||||||
raise TypeError("ciphertext too short for tag")
|
raise TypeError("ciphertext too short for tag")
|
||||||
expected_out = len(ct) - maclen
|
expected_out = len(ct) - maclen
|
||||||
@@ -284,7 +286,7 @@ def stream(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}, uses zeroes for nonce if None).
|
nonce: Nonce ({NONCEBYTES=}, uses zeroes for nonce if None).
|
||||||
length: Number of bytes to generate (required if into is None).
|
length: Number of bytes to generate (required if into is None).
|
||||||
into: Buffer to write stream into (default: bytearray created).
|
into: Buffer to write stream into (default: bytearray created).
|
||||||
|
|
||||||
@@ -296,8 +298,8 @@ def stream(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if nonce is not None and len(nonce) != NPUBBYTES:
|
if nonce is not None and len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
if length is None:
|
if length is None:
|
||||||
raise TypeError("provide either into or length")
|
raise TypeError("provide either into or length")
|
||||||
@@ -326,7 +328,7 @@ def encrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
into: Buffer to write ciphertext into (default: bytearray created).
|
into: Buffer to write ciphertext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -338,8 +340,8 @@ def encrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message))
|
out = bytearray(len(message))
|
||||||
else:
|
else:
|
||||||
@@ -367,7 +369,7 @@ def decrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
into: Buffer to write plaintext into (default: bytearray created).
|
into: Buffer to write plaintext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -379,8 +381,8 @@ def decrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(ct))
|
out = bytearray(len(ct))
|
||||||
else:
|
else:
|
||||||
@@ -402,14 +404,14 @@ def mac(
|
|||||||
key: Buffer,
|
key: Buffer,
|
||||||
nonce: Buffer,
|
nonce: Buffer,
|
||||||
data: Buffer,
|
data: Buffer,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Compute a MAC for the given data in one shot.
|
f"""Compute a MAC for the given data in one shot.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=})
|
key: Key ({KEYBYTES=})
|
||||||
nonce: Nonce ({NPUBBYTES=})
|
nonce: Nonce ({NONCEBYTES=})
|
||||||
data: Data to MAC
|
data: Data to MAC
|
||||||
maclen: MAC length (16 or 32, default 16)
|
maclen: MAC length (16 or 32, default 16)
|
||||||
into: Buffer to write MAC into (default: bytearray created)
|
into: Buffer to write MAC into (default: bytearray created)
|
||||||
@@ -445,7 +447,7 @@ class Mac:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
TypeError: If key or nonce lengths are invalid.
|
TypeError: If key or nonce lengths are invalid.
|
||||||
@@ -459,8 +461,8 @@ class Mac:
|
|||||||
# Normal init path
|
# Normal init path
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
_lib.aegis128x4_mac_init(self._st, _ptr(key), _ptr(nonce))
|
_lib.aegis128x4_mac_init(self._st, _ptr(key), _ptr(nonce))
|
||||||
|
|
||||||
def __deepcopy__(self) -> "Mac":
|
def __deepcopy__(self) -> "Mac":
|
||||||
@@ -490,7 +492,7 @@ class Mac:
|
|||||||
|
|
||||||
def final(
|
def final(
|
||||||
self,
|
self,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize and return the MAC tag.
|
"""Finalize and return the MAC tag.
|
||||||
@@ -558,7 +560,7 @@ class Encryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data to bind to the encryption (optional).
|
ad: Associated data to bind to the encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -566,8 +568,8 @@ class Encryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis128x4_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis128x4_state", ALIGNMENT)
|
||||||
_lib.aegis128x4_state_init(
|
_lib.aegis128x4_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -639,7 +641,7 @@ class Encryptor:
|
|||||||
return out if into is None else memoryview(out)[:w] # type: ignore
|
return out if into is None else memoryview(out)[:w] # type: ignore
|
||||||
|
|
||||||
def final(
|
def final(
|
||||||
self, into: Buffer | None = None, maclen: int = ABYTES_MIN
|
self, into: Buffer | None = None, maclen: int = MACBYTES
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize encryption, writing any remaining bytes and the tag.
|
"""Finalize encryption, writing any remaining bytes and the tag.
|
||||||
|
|
||||||
@@ -692,7 +694,7 @@ class Decryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data used during encryption (optional).
|
ad: Associated data used during encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -700,8 +702,8 @@ class Decryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis128x4_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis128x4_state", ALIGNMENT)
|
||||||
_lib.aegis128x4_state_init(
|
_lib.aegis128x4_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -796,10 +798,9 @@ def new_mac_state():
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
# constants
|
# constants
|
||||||
"KEYBYTES",
|
"KEYBYTES",
|
||||||
"NPUBBYTES",
|
"NONCEBYTES",
|
||||||
"ABYTES_MIN",
|
"MACBYTES",
|
||||||
"ABYTES_MAX",
|
"MACBYTES_LONG",
|
||||||
"TAILBYTES_MAX",
|
|
||||||
"ALIGNMENT",
|
"ALIGNMENT",
|
||||||
"RATE",
|
"RATE",
|
||||||
# utility functions
|
# utility functions
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ from ._loader import ffi
|
|||||||
from ._loader import lib as _lib
|
from ._loader import lib as _lib
|
||||||
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
||||||
|
|
||||||
# Constants exposed as functions in C; mirror them as integers at module import time
|
KEYBYTES = 32 #: Key size in bytes (varies by algorithm)
|
||||||
KEYBYTES = _lib.aegis256_keybytes()
|
NONCEBYTES = 32 #: Nonce size in bytes (varies by algorithm)
|
||||||
NPUBBYTES = _lib.aegis256_npubbytes()
|
MACBYTES = 16 #: Normal MAC size (always 16)
|
||||||
ABYTES_MIN = _lib.aegis256_abytes_min()
|
MACBYTES_LONG = 32 #: Long MAC size (always 32)
|
||||||
ABYTES_MAX = _lib.aegis256_abytes_max()
|
ALIGNMENT = 64 #: Required alignment for internal structures
|
||||||
TAILBYTES_MAX = _lib.aegis256_tailbytes_max()
|
RATE = 64 #: Byte chunk size in internal processing
|
||||||
ALIGNMENT = 16
|
|
||||||
RATE = 16
|
|
||||||
|
|
||||||
|
|
||||||
def random_key() -> bytearray:
|
def random_key() -> bytearray:
|
||||||
"""Generate a random key using cryptographically secure random bytes."""
|
"""
|
||||||
|
Generate a random key using cryptographically secure random bytes.
|
||||||
|
|
||||||
|
It is recommended to wipe() the key after no longer needed to keep it secret.
|
||||||
|
"""
|
||||||
return bytearray(secrets.token_bytes(KEYBYTES))
|
return bytearray(secrets.token_bytes(KEYBYTES))
|
||||||
|
|
||||||
|
|
||||||
def random_nonce() -> bytearray:
|
def random_nonce() -> bytearray:
|
||||||
"""Generate a random nonce using cryptographically secure random bytes."""
|
"""Generate a random nonce using cryptographically secure random bytes."""
|
||||||
return bytearray(secrets.token_bytes(NPUBBYTES))
|
return bytearray(secrets.token_bytes(NONCEBYTES))
|
||||||
|
|
||||||
|
|
||||||
def _ptr(buf):
|
def _ptr(buf):
|
||||||
@@ -39,7 +41,7 @@ def encrypt_detached(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
ct_into: Buffer | None = None,
|
ct_into: Buffer | None = None,
|
||||||
mac_into: Buffer | None = None,
|
mac_into: Buffer | None = None,
|
||||||
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
||||||
@@ -47,7 +49,7 @@ def encrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -65,8 +67,8 @@ def encrypt_detached(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
|
|
||||||
if ct_into is None:
|
if ct_into is None:
|
||||||
c = bytearray(len(message))
|
c = bytearray(len(message))
|
||||||
@@ -115,7 +117,7 @@ def decrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
mac: The MAC to verify.
|
mac: The MAC to verify.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
@@ -130,8 +132,8 @@ def decrypt_detached(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
maclen = len(mac)
|
maclen = len(mac)
|
||||||
if maclen not in (16, 32):
|
if maclen not in (16, 32):
|
||||||
raise TypeError("mac length must be 16 or 32")
|
raise TypeError("mac length must be 16 or 32")
|
||||||
@@ -164,14 +166,14 @@ def encrypt(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -188,8 +190,8 @@ def encrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message) + maclen)
|
out = bytearray(len(message) + maclen)
|
||||||
else:
|
else:
|
||||||
@@ -220,14 +222,14 @@ def decrypt(
|
|||||||
ct: Buffer,
|
ct: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Decrypt ciphertext with appended MAC and associated data.
|
f"""Decrypt ciphertext with appended MAC and associated data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext with MAC to decrypt.
|
ct: The ciphertext with MAC to decrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -244,8 +246,8 @@ def decrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if len(ct) < maclen:
|
if len(ct) < maclen:
|
||||||
raise TypeError("ciphertext too short for tag")
|
raise TypeError("ciphertext too short for tag")
|
||||||
expected_out = len(ct) - maclen
|
expected_out = len(ct) - maclen
|
||||||
@@ -284,7 +286,7 @@ def stream(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}, uses zeroes for nonce if None).
|
nonce: Nonce ({NONCEBYTES=}, uses zeroes for nonce if None).
|
||||||
length: Number of bytes to generate (required if into is None).
|
length: Number of bytes to generate (required if into is None).
|
||||||
into: Buffer to write stream into (default: bytearray created).
|
into: Buffer to write stream into (default: bytearray created).
|
||||||
|
|
||||||
@@ -296,8 +298,8 @@ def stream(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if nonce is not None and len(nonce) != NPUBBYTES:
|
if nonce is not None and len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
if length is None:
|
if length is None:
|
||||||
raise TypeError("provide either into or length")
|
raise TypeError("provide either into or length")
|
||||||
@@ -326,7 +328,7 @@ def encrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
into: Buffer to write ciphertext into (default: bytearray created).
|
into: Buffer to write ciphertext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -338,8 +340,8 @@ def encrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message))
|
out = bytearray(len(message))
|
||||||
else:
|
else:
|
||||||
@@ -367,7 +369,7 @@ def decrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
into: Buffer to write plaintext into (default: bytearray created).
|
into: Buffer to write plaintext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -379,8 +381,8 @@ def decrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(ct))
|
out = bytearray(len(ct))
|
||||||
else:
|
else:
|
||||||
@@ -402,14 +404,14 @@ def mac(
|
|||||||
key: Buffer,
|
key: Buffer,
|
||||||
nonce: Buffer,
|
nonce: Buffer,
|
||||||
data: Buffer,
|
data: Buffer,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Compute a MAC for the given data in one shot.
|
f"""Compute a MAC for the given data in one shot.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=})
|
key: Key ({KEYBYTES=})
|
||||||
nonce: Nonce ({NPUBBYTES=})
|
nonce: Nonce ({NONCEBYTES=})
|
||||||
data: Data to MAC
|
data: Data to MAC
|
||||||
maclen: MAC length (16 or 32, default 16)
|
maclen: MAC length (16 or 32, default 16)
|
||||||
into: Buffer to write MAC into (default: bytearray created)
|
into: Buffer to write MAC into (default: bytearray created)
|
||||||
@@ -445,7 +447,7 @@ class Mac:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
TypeError: If key or nonce lengths are invalid.
|
TypeError: If key or nonce lengths are invalid.
|
||||||
@@ -459,8 +461,8 @@ class Mac:
|
|||||||
# Normal init path
|
# Normal init path
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
_lib.aegis256_mac_init(self._st, _ptr(key), _ptr(nonce))
|
_lib.aegis256_mac_init(self._st, _ptr(key), _ptr(nonce))
|
||||||
|
|
||||||
def __deepcopy__(self) -> "Mac":
|
def __deepcopy__(self) -> "Mac":
|
||||||
@@ -490,7 +492,7 @@ class Mac:
|
|||||||
|
|
||||||
def final(
|
def final(
|
||||||
self,
|
self,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize and return the MAC tag.
|
"""Finalize and return the MAC tag.
|
||||||
@@ -558,7 +560,7 @@ class Encryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data to bind to the encryption (optional).
|
ad: Associated data to bind to the encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -566,8 +568,8 @@ class Encryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis256_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis256_state", ALIGNMENT)
|
||||||
_lib.aegis256_state_init(
|
_lib.aegis256_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -639,7 +641,7 @@ class Encryptor:
|
|||||||
return out if into is None else memoryview(out)[:w] # type: ignore
|
return out if into is None else memoryview(out)[:w] # type: ignore
|
||||||
|
|
||||||
def final(
|
def final(
|
||||||
self, into: Buffer | None = None, maclen: int = ABYTES_MIN
|
self, into: Buffer | None = None, maclen: int = MACBYTES
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize encryption, writing any remaining bytes and the tag.
|
"""Finalize encryption, writing any remaining bytes and the tag.
|
||||||
|
|
||||||
@@ -692,7 +694,7 @@ class Decryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data used during encryption (optional).
|
ad: Associated data used during encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -700,8 +702,8 @@ class Decryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis256_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis256_state", ALIGNMENT)
|
||||||
_lib.aegis256_state_init(
|
_lib.aegis256_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -796,10 +798,9 @@ def new_mac_state():
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
# constants
|
# constants
|
||||||
"KEYBYTES",
|
"KEYBYTES",
|
||||||
"NPUBBYTES",
|
"NONCEBYTES",
|
||||||
"ABYTES_MIN",
|
"MACBYTES",
|
||||||
"ABYTES_MAX",
|
"MACBYTES_LONG",
|
||||||
"TAILBYTES_MAX",
|
|
||||||
"ALIGNMENT",
|
"ALIGNMENT",
|
||||||
"RATE",
|
"RATE",
|
||||||
# utility functions
|
# utility functions
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ from ._loader import ffi
|
|||||||
from ._loader import lib as _lib
|
from ._loader import lib as _lib
|
||||||
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
||||||
|
|
||||||
# Constants exposed as functions in C; mirror them as integers at module import time
|
KEYBYTES = 32 #: Key size in bytes (varies by algorithm)
|
||||||
KEYBYTES = _lib.aegis256x2_keybytes()
|
NONCEBYTES = 32 #: Nonce size in bytes (varies by algorithm)
|
||||||
NPUBBYTES = _lib.aegis256x2_npubbytes()
|
MACBYTES = 16 #: Normal MAC size (always 16)
|
||||||
ABYTES_MIN = _lib.aegis256x2_abytes_min()
|
MACBYTES_LONG = 32 #: Long MAC size (always 32)
|
||||||
ABYTES_MAX = _lib.aegis256x2_abytes_max()
|
ALIGNMENT = 64 #: Required alignment for internal structures
|
||||||
TAILBYTES_MAX = _lib.aegis256x2_tailbytes_max()
|
RATE = 64 #: Byte chunk size in internal processing
|
||||||
ALIGNMENT = 32
|
|
||||||
RATE = 32
|
|
||||||
|
|
||||||
|
|
||||||
def random_key() -> bytearray:
|
def random_key() -> bytearray:
|
||||||
"""Generate a random key using cryptographically secure random bytes."""
|
"""
|
||||||
|
Generate a random key using cryptographically secure random bytes.
|
||||||
|
|
||||||
|
It is recommended to wipe() the key after no longer needed to keep it secret.
|
||||||
|
"""
|
||||||
return bytearray(secrets.token_bytes(KEYBYTES))
|
return bytearray(secrets.token_bytes(KEYBYTES))
|
||||||
|
|
||||||
|
|
||||||
def random_nonce() -> bytearray:
|
def random_nonce() -> bytearray:
|
||||||
"""Generate a random nonce using cryptographically secure random bytes."""
|
"""Generate a random nonce using cryptographically secure random bytes."""
|
||||||
return bytearray(secrets.token_bytes(NPUBBYTES))
|
return bytearray(secrets.token_bytes(NONCEBYTES))
|
||||||
|
|
||||||
|
|
||||||
def _ptr(buf):
|
def _ptr(buf):
|
||||||
@@ -39,7 +41,7 @@ def encrypt_detached(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
ct_into: Buffer | None = None,
|
ct_into: Buffer | None = None,
|
||||||
mac_into: Buffer | None = None,
|
mac_into: Buffer | None = None,
|
||||||
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
||||||
@@ -47,7 +49,7 @@ def encrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -65,8 +67,8 @@ def encrypt_detached(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
|
|
||||||
if ct_into is None:
|
if ct_into is None:
|
||||||
c = bytearray(len(message))
|
c = bytearray(len(message))
|
||||||
@@ -115,7 +117,7 @@ def decrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
mac: The MAC to verify.
|
mac: The MAC to verify.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
@@ -130,8 +132,8 @@ def decrypt_detached(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
maclen = len(mac)
|
maclen = len(mac)
|
||||||
if maclen not in (16, 32):
|
if maclen not in (16, 32):
|
||||||
raise TypeError("mac length must be 16 or 32")
|
raise TypeError("mac length must be 16 or 32")
|
||||||
@@ -164,14 +166,14 @@ def encrypt(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -188,8 +190,8 @@ def encrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message) + maclen)
|
out = bytearray(len(message) + maclen)
|
||||||
else:
|
else:
|
||||||
@@ -220,14 +222,14 @@ def decrypt(
|
|||||||
ct: Buffer,
|
ct: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Decrypt ciphertext with appended MAC and associated data.
|
f"""Decrypt ciphertext with appended MAC and associated data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext with MAC to decrypt.
|
ct: The ciphertext with MAC to decrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -244,8 +246,8 @@ def decrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if len(ct) < maclen:
|
if len(ct) < maclen:
|
||||||
raise TypeError("ciphertext too short for tag")
|
raise TypeError("ciphertext too short for tag")
|
||||||
expected_out = len(ct) - maclen
|
expected_out = len(ct) - maclen
|
||||||
@@ -284,7 +286,7 @@ def stream(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}, uses zeroes for nonce if None).
|
nonce: Nonce ({NONCEBYTES=}, uses zeroes for nonce if None).
|
||||||
length: Number of bytes to generate (required if into is None).
|
length: Number of bytes to generate (required if into is None).
|
||||||
into: Buffer to write stream into (default: bytearray created).
|
into: Buffer to write stream into (default: bytearray created).
|
||||||
|
|
||||||
@@ -296,8 +298,8 @@ def stream(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if nonce is not None and len(nonce) != NPUBBYTES:
|
if nonce is not None and len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
if length is None:
|
if length is None:
|
||||||
raise TypeError("provide either into or length")
|
raise TypeError("provide either into or length")
|
||||||
@@ -326,7 +328,7 @@ def encrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
into: Buffer to write ciphertext into (default: bytearray created).
|
into: Buffer to write ciphertext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -338,8 +340,8 @@ def encrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message))
|
out = bytearray(len(message))
|
||||||
else:
|
else:
|
||||||
@@ -367,7 +369,7 @@ def decrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
into: Buffer to write plaintext into (default: bytearray created).
|
into: Buffer to write plaintext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -379,8 +381,8 @@ def decrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(ct))
|
out = bytearray(len(ct))
|
||||||
else:
|
else:
|
||||||
@@ -402,14 +404,14 @@ def mac(
|
|||||||
key: Buffer,
|
key: Buffer,
|
||||||
nonce: Buffer,
|
nonce: Buffer,
|
||||||
data: Buffer,
|
data: Buffer,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Compute a MAC for the given data in one shot.
|
f"""Compute a MAC for the given data in one shot.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=})
|
key: Key ({KEYBYTES=})
|
||||||
nonce: Nonce ({NPUBBYTES=})
|
nonce: Nonce ({NONCEBYTES=})
|
||||||
data: Data to MAC
|
data: Data to MAC
|
||||||
maclen: MAC length (16 or 32, default 16)
|
maclen: MAC length (16 or 32, default 16)
|
||||||
into: Buffer to write MAC into (default: bytearray created)
|
into: Buffer to write MAC into (default: bytearray created)
|
||||||
@@ -445,7 +447,7 @@ class Mac:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
TypeError: If key or nonce lengths are invalid.
|
TypeError: If key or nonce lengths are invalid.
|
||||||
@@ -459,8 +461,8 @@ class Mac:
|
|||||||
# Normal init path
|
# Normal init path
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
_lib.aegis256x2_mac_init(self._st, _ptr(key), _ptr(nonce))
|
_lib.aegis256x2_mac_init(self._st, _ptr(key), _ptr(nonce))
|
||||||
|
|
||||||
def __deepcopy__(self) -> "Mac":
|
def __deepcopy__(self) -> "Mac":
|
||||||
@@ -490,7 +492,7 @@ class Mac:
|
|||||||
|
|
||||||
def final(
|
def final(
|
||||||
self,
|
self,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize and return the MAC tag.
|
"""Finalize and return the MAC tag.
|
||||||
@@ -558,7 +560,7 @@ class Encryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data to bind to the encryption (optional).
|
ad: Associated data to bind to the encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -566,8 +568,8 @@ class Encryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis256x2_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis256x2_state", ALIGNMENT)
|
||||||
_lib.aegis256x2_state_init(
|
_lib.aegis256x2_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -639,7 +641,7 @@ class Encryptor:
|
|||||||
return out if into is None else memoryview(out)[:w] # type: ignore
|
return out if into is None else memoryview(out)[:w] # type: ignore
|
||||||
|
|
||||||
def final(
|
def final(
|
||||||
self, into: Buffer | None = None, maclen: int = ABYTES_MIN
|
self, into: Buffer | None = None, maclen: int = MACBYTES
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize encryption, writing any remaining bytes and the tag.
|
"""Finalize encryption, writing any remaining bytes and the tag.
|
||||||
|
|
||||||
@@ -692,7 +694,7 @@ class Decryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data used during encryption (optional).
|
ad: Associated data used during encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -700,8 +702,8 @@ class Decryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis256x2_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis256x2_state", ALIGNMENT)
|
||||||
_lib.aegis256x2_state_init(
|
_lib.aegis256x2_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -796,10 +798,9 @@ def new_mac_state():
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
# constants
|
# constants
|
||||||
"KEYBYTES",
|
"KEYBYTES",
|
||||||
"NPUBBYTES",
|
"NONCEBYTES",
|
||||||
"ABYTES_MIN",
|
"MACBYTES",
|
||||||
"ABYTES_MAX",
|
"MACBYTES_LONG",
|
||||||
"TAILBYTES_MAX",
|
|
||||||
"ALIGNMENT",
|
"ALIGNMENT",
|
||||||
"RATE",
|
"RATE",
|
||||||
# utility functions
|
# utility functions
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ from ._loader import ffi
|
|||||||
from ._loader import lib as _lib
|
from ._loader import lib as _lib
|
||||||
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
from .util import Buffer, new_aligned_struct, nonce_increment, wipe
|
||||||
|
|
||||||
# Constants exposed as functions in C; mirror them as integers at module import time
|
KEYBYTES = 32 #: Key size in bytes (varies by algorithm)
|
||||||
KEYBYTES = _lib.aegis256x4_keybytes()
|
NONCEBYTES = 32 #: Nonce size in bytes (varies by algorithm)
|
||||||
NPUBBYTES = _lib.aegis256x4_npubbytes()
|
MACBYTES = 16 #: Normal MAC size (always 16)
|
||||||
ABYTES_MIN = _lib.aegis256x4_abytes_min()
|
MACBYTES_LONG = 32 #: Long MAC size (always 32)
|
||||||
ABYTES_MAX = _lib.aegis256x4_abytes_max()
|
ALIGNMENT = 64 #: Required alignment for internal structures
|
||||||
TAILBYTES_MAX = _lib.aegis256x4_tailbytes_max()
|
RATE = 64 #: Byte chunk size in internal processing
|
||||||
ALIGNMENT = 64
|
|
||||||
RATE = 64
|
|
||||||
|
|
||||||
|
|
||||||
def random_key() -> bytearray:
|
def random_key() -> bytearray:
|
||||||
"""Generate a random key using cryptographically secure random bytes."""
|
"""
|
||||||
|
Generate a random key using cryptographically secure random bytes.
|
||||||
|
|
||||||
|
It is recommended to wipe() the key after no longer needed to keep it secret.
|
||||||
|
"""
|
||||||
return bytearray(secrets.token_bytes(KEYBYTES))
|
return bytearray(secrets.token_bytes(KEYBYTES))
|
||||||
|
|
||||||
|
|
||||||
def random_nonce() -> bytearray:
|
def random_nonce() -> bytearray:
|
||||||
"""Generate a random nonce using cryptographically secure random bytes."""
|
"""Generate a random nonce using cryptographically secure random bytes."""
|
||||||
return bytearray(secrets.token_bytes(NPUBBYTES))
|
return bytearray(secrets.token_bytes(NONCEBYTES))
|
||||||
|
|
||||||
|
|
||||||
def _ptr(buf):
|
def _ptr(buf):
|
||||||
@@ -39,7 +41,7 @@ def encrypt_detached(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
ct_into: Buffer | None = None,
|
ct_into: Buffer | None = None,
|
||||||
mac_into: Buffer | None = None,
|
mac_into: Buffer | None = None,
|
||||||
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
) -> tuple[bytearray | memoryview, bytearray | memoryview]:
|
||||||
@@ -47,7 +49,7 @@ def encrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -65,8 +67,8 @@ def encrypt_detached(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
|
|
||||||
if ct_into is None:
|
if ct_into is None:
|
||||||
c = bytearray(len(message))
|
c = bytearray(len(message))
|
||||||
@@ -115,7 +117,7 @@ def decrypt_detached(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
mac: The MAC to verify.
|
mac: The MAC to verify.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
@@ -130,8 +132,8 @@ def decrypt_detached(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
maclen = len(mac)
|
maclen = len(mac)
|
||||||
if maclen not in (16, 32):
|
if maclen not in (16, 32):
|
||||||
raise TypeError("mac length must be 16 or 32")
|
raise TypeError("mac length must be 16 or 32")
|
||||||
@@ -164,14 +166,14 @@ def encrypt(
|
|||||||
message: Buffer,
|
message: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
f"""Encrypt message with associated data, returning ciphertext with appended MAC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -188,8 +190,8 @@ def encrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message) + maclen)
|
out = bytearray(len(message) + maclen)
|
||||||
else:
|
else:
|
||||||
@@ -220,14 +222,14 @@ def decrypt(
|
|||||||
ct: Buffer,
|
ct: Buffer,
|
||||||
ad: Buffer | None = None,
|
ad: Buffer | None = None,
|
||||||
*,
|
*,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Decrypt ciphertext with appended MAC and associated data.
|
f"""Decrypt ciphertext with appended MAC and associated data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext with MAC to decrypt.
|
ct: The ciphertext with MAC to decrypt.
|
||||||
ad: Associated data (optional).
|
ad: Associated data (optional).
|
||||||
maclen: MAC length (16 or 32, default 16).
|
maclen: MAC length (16 or 32, default 16).
|
||||||
@@ -244,8 +246,8 @@ def decrypt(
|
|||||||
raise TypeError("maclen must be 16 or 32")
|
raise TypeError("maclen must be 16 or 32")
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if len(ct) < maclen:
|
if len(ct) < maclen:
|
||||||
raise TypeError("ciphertext too short for tag")
|
raise TypeError("ciphertext too short for tag")
|
||||||
expected_out = len(ct) - maclen
|
expected_out = len(ct) - maclen
|
||||||
@@ -284,7 +286,7 @@ def stream(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}, uses zeroes for nonce if None).
|
nonce: Nonce ({NONCEBYTES=}, uses zeroes for nonce if None).
|
||||||
length: Number of bytes to generate (required if into is None).
|
length: Number of bytes to generate (required if into is None).
|
||||||
into: Buffer to write stream into (default: bytearray created).
|
into: Buffer to write stream into (default: bytearray created).
|
||||||
|
|
||||||
@@ -296,8 +298,8 @@ def stream(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if nonce is not None and len(nonce) != NPUBBYTES:
|
if nonce is not None and len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
if length is None:
|
if length is None:
|
||||||
raise TypeError("provide either into or length")
|
raise TypeError("provide either into or length")
|
||||||
@@ -326,7 +328,7 @@ def encrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
message: The plaintext message to encrypt.
|
message: The plaintext message to encrypt.
|
||||||
into: Buffer to write ciphertext into (default: bytearray created).
|
into: Buffer to write ciphertext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -338,8 +340,8 @@ def encrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(message))
|
out = bytearray(len(message))
|
||||||
else:
|
else:
|
||||||
@@ -367,7 +369,7 @@ def decrypt_unauthenticated(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ct: The ciphertext to decrypt.
|
ct: The ciphertext to decrypt.
|
||||||
into: Buffer to write plaintext into (default: bytearray created).
|
into: Buffer to write plaintext into (default: bytearray created).
|
||||||
|
|
||||||
@@ -379,8 +381,8 @@ def decrypt_unauthenticated(
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
if into is None:
|
if into is None:
|
||||||
out = bytearray(len(ct))
|
out = bytearray(len(ct))
|
||||||
else:
|
else:
|
||||||
@@ -402,14 +404,14 @@ def mac(
|
|||||||
key: Buffer,
|
key: Buffer,
|
||||||
nonce: Buffer,
|
nonce: Buffer,
|
||||||
data: Buffer,
|
data: Buffer,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
f"""Compute a MAC for the given data in one shot.
|
f"""Compute a MAC for the given data in one shot.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=})
|
key: Key ({KEYBYTES=})
|
||||||
nonce: Nonce ({NPUBBYTES=})
|
nonce: Nonce ({NONCEBYTES=})
|
||||||
data: Data to MAC
|
data: Data to MAC
|
||||||
maclen: MAC length (16 or 32, default 16)
|
maclen: MAC length (16 or 32, default 16)
|
||||||
into: Buffer to write MAC into (default: bytearray created)
|
into: Buffer to write MAC into (default: bytearray created)
|
||||||
@@ -445,7 +447,7 @@ class Mac:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
TypeError: If key or nonce lengths are invalid.
|
TypeError: If key or nonce lengths are invalid.
|
||||||
@@ -459,8 +461,8 @@ class Mac:
|
|||||||
# Normal init path
|
# Normal init path
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
_lib.aegis256x4_mac_init(self._st, _ptr(key), _ptr(nonce))
|
_lib.aegis256x4_mac_init(self._st, _ptr(key), _ptr(nonce))
|
||||||
|
|
||||||
def __deepcopy__(self) -> "Mac":
|
def __deepcopy__(self) -> "Mac":
|
||||||
@@ -490,7 +492,7 @@ class Mac:
|
|||||||
|
|
||||||
def final(
|
def final(
|
||||||
self,
|
self,
|
||||||
maclen: int = ABYTES_MIN,
|
maclen: int = MACBYTES,
|
||||||
into: Buffer | None = None,
|
into: Buffer | None = None,
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize and return the MAC tag.
|
"""Finalize and return the MAC tag.
|
||||||
@@ -558,7 +560,7 @@ class Encryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data to bind to the encryption (optional).
|
ad: Associated data to bind to the encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -566,8 +568,8 @@ class Encryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis256x4_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis256x4_state", ALIGNMENT)
|
||||||
_lib.aegis256x4_state_init(
|
_lib.aegis256x4_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -639,7 +641,7 @@ class Encryptor:
|
|||||||
return out if into is None else memoryview(out)[:w] # type: ignore
|
return out if into is None else memoryview(out)[:w] # type: ignore
|
||||||
|
|
||||||
def final(
|
def final(
|
||||||
self, into: Buffer | None = None, maclen: int = ABYTES_MIN
|
self, into: Buffer | None = None, maclen: int = MACBYTES
|
||||||
) -> bytearray | memoryview:
|
) -> bytearray | memoryview:
|
||||||
"""Finalize encryption, writing any remaining bytes and the tag.
|
"""Finalize encryption, writing any remaining bytes and the tag.
|
||||||
|
|
||||||
@@ -692,7 +694,7 @@ class Decryptor:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: Key ({KEYBYTES=}).
|
key: Key ({KEYBYTES=}).
|
||||||
nonce: Nonce ({NPUBBYTES=}).
|
nonce: Nonce ({NONCEBYTES=}).
|
||||||
ad: Associated data used during encryption (optional).
|
ad: Associated data used during encryption (optional).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -700,8 +702,8 @@ class Decryptor:
|
|||||||
"""
|
"""
|
||||||
if len(key) != KEYBYTES:
|
if len(key) != KEYBYTES:
|
||||||
raise TypeError(f"key length must be {KEYBYTES}")
|
raise TypeError(f"key length must be {KEYBYTES}")
|
||||||
if len(nonce) != NPUBBYTES:
|
if len(nonce) != NONCEBYTES:
|
||||||
raise TypeError(f"nonce length must be {NPUBBYTES}")
|
raise TypeError(f"nonce length must be {NONCEBYTES}")
|
||||||
st, owner = new_aligned_struct("aegis256x4_state", ALIGNMENT)
|
st, owner = new_aligned_struct("aegis256x4_state", ALIGNMENT)
|
||||||
_lib.aegis256x4_state_init(
|
_lib.aegis256x4_state_init(
|
||||||
st,
|
st,
|
||||||
@@ -796,10 +798,9 @@ def new_mac_state():
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
# constants
|
# constants
|
||||||
"KEYBYTES",
|
"KEYBYTES",
|
||||||
"NPUBBYTES",
|
"NONCEBYTES",
|
||||||
"ABYTES_MIN",
|
"MACBYTES",
|
||||||
"ABYTES_MAX",
|
"MACBYTES_LONG",
|
||||||
"TAILBYTES_MAX",
|
|
||||||
"ALIGNMENT",
|
"ALIGNMENT",
|
||||||
"RATE",
|
"RATE",
|
||||||
# utility functions
|
# utility functions
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Python benchmark matching src/test/benchmark.zig for all supported Aegis algorithms.
|
Python benchmark matching src/test/benchmark.zig for all supported Aegis algorithms.
|
||||||
|
|
||||||
It performs two benchmarks with the same parameters as the Zig version:
|
It performs two benchmarks with the same parameters as the Zig version:
|
||||||
- AEGIS encrypt (attached tag, maclen = ABYTES_MIN)
|
- AEGIS encrypt (attached tag, maclen = MACBYTES)
|
||||||
- AEGIS MAC (clone state pattern)
|
- AEGIS MAC (clone state pattern)
|
||||||
|
|
||||||
Output format and throughput units mirror the Zig benchmark (Mb/s).
|
Output format and throughput units mirror the Zig benchmark (Mb/s).
|
||||||
@@ -31,12 +31,12 @@ def _random_bytes(n: int) -> bytes:
|
|||||||
return os.urandom(n)
|
return os.urandom(n)
|
||||||
|
|
||||||
|
|
||||||
def bench_encrypt(alg_name: str, a) -> None:
|
def bench_encrypt(alg_name: str, ciph) -> None:
|
||||||
key = _random_bytes(a.KEYBYTES)
|
key = _random_bytes(ciph.KEYBYTES)
|
||||||
nonce = _random_bytes(a.NPUBBYTES)
|
nonce = _random_bytes(ciph.NONCEBYTES)
|
||||||
|
|
||||||
# Single buffer, as in Zig: c_out == m buffer, with tag appended
|
# Single buffer, as in Zig: c_out == m buffer, with tag appended
|
||||||
maclen = a.ABYTES_MIN
|
maclen = ciph.MACBYTES
|
||||||
buf = bytearray(MSG_LEN + maclen)
|
buf = bytearray(MSG_LEN + maclen)
|
||||||
# Initialize buffer with random data
|
# Initialize buffer with random data
|
||||||
buf[:] = _random_bytes(len(buf))
|
buf[:] = _random_bytes(len(buf))
|
||||||
@@ -45,7 +45,7 @@ def bench_encrypt(alg_name: str, a) -> None:
|
|||||||
|
|
||||||
t0 = time.perf_counter()
|
t0 = time.perf_counter()
|
||||||
for _ in range(ITERATIONS):
|
for _ in range(ITERATIONS):
|
||||||
a.encrypt(key, nonce, mview, None, maclen=maclen, into=buf)
|
ciph.encrypt(key, nonce, mview, None, maclen=maclen, into=buf)
|
||||||
t1 = time.perf_counter()
|
t1 = time.perf_counter()
|
||||||
|
|
||||||
# Prevent any unrealistic optimization assumptions
|
# Prevent any unrealistic optimization assumptions
|
||||||
@@ -59,21 +59,21 @@ def bench_encrypt(alg_name: str, a) -> None:
|
|||||||
print(f"{alg_name}\t{throughput_mbps:10.2f} Mb/s")
|
print(f"{alg_name}\t{throughput_mbps:10.2f} Mb/s")
|
||||||
|
|
||||||
|
|
||||||
def bench_mac(alg_name: str, a) -> None:
|
def bench_mac(alg_name: str, ciph) -> None:
|
||||||
key = _random_bytes(a.KEYBYTES)
|
key = _random_bytes(ciph.KEYBYTES)
|
||||||
nonce = _random_bytes(a.NPUBBYTES)
|
nonce = _random_bytes(ciph.NONCEBYTES)
|
||||||
|
|
||||||
buf = bytearray(MSG_LEN)
|
buf = bytearray(MSG_LEN)
|
||||||
buf[:] = _random_bytes(len(buf))
|
buf[:] = _random_bytes(len(buf))
|
||||||
|
|
||||||
mac0 = a.Mac(key, nonce)
|
mac0 = ciph.Mac(key, nonce)
|
||||||
mac_out = bytearray(a.ABYTES_MAX)
|
mac_out = bytearray(ciph.MACBYTES_LONG)
|
||||||
|
|
||||||
t0 = time.perf_counter()
|
t0 = time.perf_counter()
|
||||||
for _ in range(ITERATIONS):
|
for _ in range(ITERATIONS):
|
||||||
mac = mac0.clone()
|
mac = mac0.clone()
|
||||||
mac.update(buf)
|
mac.update(buf)
|
||||||
mac.final(maclen=a.ABYTES_MAX, into=mac_out)
|
mac.final(maclen=ciph.MACBYTES_LONG, into=mac_out)
|
||||||
t1 = time.perf_counter()
|
t1 = time.perf_counter()
|
||||||
|
|
||||||
_ = mac_out[0]
|
_ = mac_out[0]
|
||||||
|
|||||||
@@ -103,21 +103,44 @@ def generate_cdef(include_dir: pathlib.Path) -> str:
|
|||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
def extract_constants(common_h_path: pathlib.Path) -> Tuple[int, int]:
|
def extract_constants(
|
||||||
content = common_h_path.read_text(encoding="utf-8")
|
common_h_path: pathlib.Path, header_path: pathlib.Path
|
||||||
|
) -> Dict[str, int]:
|
||||||
|
"""Extract constants from common.h (ALIGNMENT, RATE) and main header (KEYBYTES, NPUBBYTES, ABYTES_*)."""
|
||||||
|
constants = {}
|
||||||
|
|
||||||
align_match = re.search(r"^\s*#define\s+ALIGNMENT\s+(\d+)", content, re.MULTILINE)
|
# Extract from common.h
|
||||||
rate_match = re.search(r"^\s*#define\s+RATE\s+(\d+)", content, re.MULTILINE)
|
common_content = common_h_path.read_text(encoding="utf-8")
|
||||||
|
align_match = re.search(
|
||||||
|
r"^\s*#define\s+ALIGNMENT\s+(\d+)", common_content, re.MULTILINE
|
||||||
|
)
|
||||||
|
rate_match = re.search(r"^\s*#define\s+RATE\s+(\d+)", common_content, re.MULTILINE)
|
||||||
|
|
||||||
if not align_match or not rate_match:
|
if not align_match or not rate_match:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Could not extract ALIGNMENT and/or RATE from {common_h_path}"
|
f"Could not extract ALIGNMENT and/or RATE from {common_h_path}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return int(align_match.group(1)), int(rate_match.group(1))
|
constants["ALIGNMENT"] = int(align_match.group(1))
|
||||||
|
constants["RATE"] = int(rate_match.group(1))
|
||||||
|
|
||||||
|
# Extract from main header
|
||||||
|
header_content = header_path.read_text(encoding="utf-8")
|
||||||
|
variant = header_path.stem # e.g., "aegis256x4"
|
||||||
|
|
||||||
|
for const_name in ["KEYBYTES", "NPUBBYTES", "ABYTES_MIN", "ABYTES_MAX"]:
|
||||||
|
pattern = rf"^\s*#define\s+{variant}_{const_name}\s+(\d+)"
|
||||||
|
match = re.search(pattern, header_content, re.MULTILINE)
|
||||||
|
if not match:
|
||||||
|
raise ValueError(f"Could not extract {const_name} from {header_path}")
|
||||||
|
constants[const_name] = int(match.group(1))
|
||||||
|
|
||||||
|
return constants
|
||||||
|
|
||||||
|
|
||||||
def extract_all_constants(libaegis_src_dir: pathlib.Path) -> Dict[str, Tuple[int, int]]:
|
def extract_all_constants(
|
||||||
|
libaegis_src_dir: pathlib.Path, include_dir: pathlib.Path
|
||||||
|
) -> Dict[str, Dict[str, int]]:
|
||||||
variants = [
|
variants = [
|
||||||
"aegis128l",
|
"aegis128l",
|
||||||
"aegis128x2",
|
"aegis128x2",
|
||||||
@@ -130,13 +153,18 @@ def extract_all_constants(libaegis_src_dir: pathlib.Path) -> Dict[str, Tuple[int
|
|||||||
|
|
||||||
for variant in variants:
|
for variant in variants:
|
||||||
common_h = libaegis_src_dir / variant / f"{variant}_common.h"
|
common_h = libaegis_src_dir / variant / f"{variant}_common.h"
|
||||||
|
header_h = include_dir / f"{variant}.h"
|
||||||
|
|
||||||
if not common_h.exists():
|
if not common_h.exists():
|
||||||
print(f"Warning: {common_h} not found, skipping {variant}", file=sys.stderr)
|
print(f"Warning: {common_h} not found, skipping {variant}", file=sys.stderr)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if not header_h.exists():
|
||||||
|
print(f"Warning: {header_h} not found, skipping {variant}", file=sys.stderr)
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
alignment, rate = extract_constants(common_h)
|
constants[variant] = extract_constants(common_h, header_h)
|
||||||
constants[variant] = (alignment, rate)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error extracting constants from {variant}: {e}", file=sys.stderr)
|
print(f"Error extracting constants from {variant}: {e}", file=sys.stderr)
|
||||||
|
|
||||||
@@ -155,7 +183,8 @@ def algo_label(name: str) -> str:
|
|||||||
return "AEGIS-" + name[5:].upper()
|
return "AEGIS-" + name[5:].upper()
|
||||||
|
|
||||||
|
|
||||||
def generate_variant(template_src: str, variant: str, alignment: int, rate: int) -> str:
|
def generate_variant(template_src: str, variant: str, constants: Dict[str, int]) -> str:
|
||||||
|
"""Generate a variant module from the template with substituted constants."""
|
||||||
s = template_src.replace("aegis256x4", variant).replace(
|
s = template_src.replace("aegis256x4", variant).replace(
|
||||||
"AEGIS-256X4", algo_label(variant)
|
"AEGIS-256X4", algo_label(variant)
|
||||||
)
|
)
|
||||||
@@ -165,15 +194,34 @@ def generate_variant(template_src: str, variant: str, alignment: int, rate: int)
|
|||||||
"# All modules are generated from aegis256x4.py by tools/generate.py!",
|
"# All modules are generated from aegis256x4.py by tools/generate.py!",
|
||||||
s,
|
s,
|
||||||
)
|
)
|
||||||
s = replace_constant(ALIGNMENT_RE, s, alignment)
|
s = replace_constant(ALIGNMENT_RE, s, constants["ALIGNMENT"])
|
||||||
s = replace_constant(RATE_RE, s, rate)
|
s = replace_constant(RATE_RE, s, constants["RATE"])
|
||||||
|
|
||||||
|
# Replace the constant assignments
|
||||||
|
s = re.sub(r"KEYBYTES = \d+", f"KEYBYTES = {constants['KEYBYTES']}", s)
|
||||||
|
s = re.sub(
|
||||||
|
r"NONCEBYTES = \d+",
|
||||||
|
f"NONCEBYTES = {constants['NPUBBYTES']}",
|
||||||
|
s,
|
||||||
|
)
|
||||||
|
s = re.sub(
|
||||||
|
r"MACBYTES = \d+",
|
||||||
|
f"MACBYTES = {constants['ABYTES_MIN']}",
|
||||||
|
s,
|
||||||
|
)
|
||||||
|
s = re.sub(
|
||||||
|
r"MACBYTES_LONG = \d+",
|
||||||
|
f"MACBYTES_LONG = {constants['ABYTES_MAX']}",
|
||||||
|
s,
|
||||||
|
)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def generate_python_modules(
|
def generate_python_modules(
|
||||||
template_path: pathlib.Path,
|
template_path: pathlib.Path,
|
||||||
output_dir: pathlib.Path,
|
output_dir: pathlib.Path,
|
||||||
constants: Dict[str, Tuple[int, int]],
|
constants: Dict[str, Dict[str, int]],
|
||||||
) -> Tuple[list[pathlib.Path], list[pathlib.Path]]:
|
) -> Tuple[list[pathlib.Path], list[pathlib.Path]]:
|
||||||
if not template_path.exists():
|
if not template_path.exists():
|
||||||
raise FileNotFoundError(f"Template not found: {template_path}")
|
raise FileNotFoundError(f"Template not found: {template_path}")
|
||||||
@@ -184,13 +232,37 @@ def generate_python_modules(
|
|||||||
|
|
||||||
updated = []
|
updated = []
|
||||||
unchanged = []
|
unchanged = []
|
||||||
for variant, (alignment, rate) in constants.items():
|
for variant, const_dict in constants.items():
|
||||||
dst = output_dir / f"{variant}.py"
|
dst = output_dir / f"{variant}.py"
|
||||||
if variant == "aegis256x4":
|
if variant == "aegis256x4":
|
||||||
new_content = replace_constant(ALIGNMENT_RE, template_src, alignment)
|
# Update template in place with its own constants
|
||||||
new_content = replace_constant(RATE_RE, new_content, rate)
|
new_content = replace_constant(
|
||||||
|
ALIGNMENT_RE, template_src, const_dict["ALIGNMENT"]
|
||||||
|
)
|
||||||
|
new_content = replace_constant(RATE_RE, new_content, const_dict["RATE"])
|
||||||
|
# Replace the constant assignments for the template itself
|
||||||
|
new_content = re.sub(
|
||||||
|
r"KEYBYTES = \d+",
|
||||||
|
f"KEYBYTES = {const_dict['KEYBYTES']}",
|
||||||
|
new_content,
|
||||||
|
)
|
||||||
|
new_content = re.sub(
|
||||||
|
r"NONCEBYTES = \d+",
|
||||||
|
f"NONCEBYTES = {const_dict['NPUBBYTES']}",
|
||||||
|
new_content,
|
||||||
|
)
|
||||||
|
new_content = re.sub(
|
||||||
|
r"MACBYTES = \d+",
|
||||||
|
f"MACBYTES = {const_dict['ABYTES_MIN']}",
|
||||||
|
new_content,
|
||||||
|
)
|
||||||
|
new_content = re.sub(
|
||||||
|
r"MACBYTES_LONG = \d+",
|
||||||
|
f"MACBYTES_LONG = {const_dict['ABYTES_MAX']}",
|
||||||
|
new_content,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
new_content = generate_variant(template_src, variant, alignment, rate)
|
new_content = generate_variant(template_src, variant, const_dict)
|
||||||
|
|
||||||
if dst.exists() and dst.read_text(encoding="utf-8") == new_content:
|
if dst.exists() and dst.read_text(encoding="utf-8") == new_content:
|
||||||
unchanged.append(dst)
|
unchanged.append(dst)
|
||||||
@@ -216,7 +288,7 @@ def main() -> int:
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
print("Step 1: Extracting constants from C sources...", file=sys.stderr)
|
print("Step 1: Extracting constants from C sources...", file=sys.stderr)
|
||||||
constants = extract_all_constants(libaegis_src_dir)
|
constants = extract_all_constants(libaegis_src_dir, include_dir)
|
||||||
if not constants:
|
if not constants:
|
||||||
print("Error: No constants extracted", file=sys.stderr)
|
print("Error: No constants extracted", file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
@@ -243,7 +315,9 @@ def main() -> int:
|
|||||||
if unchanged:
|
if unchanged:
|
||||||
print(
|
print(
|
||||||
" - No changes to",
|
" - No changes to",
|
||||||
f"{len(unchanged)} modules" if len(unchanged) > 1 else unchanged[0],
|
f"{len(unchanged)} modules"
|
||||||
|
if len(unchanged) > 1
|
||||||
|
else unchanged[0].name,
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user