Add RAF (random-access encrypted file) support and aeg.random CSPRNG

Implement Python bindings for the libaegis 0.10.6 RAF API:

- Thin per-variant wrappers (raf_create/open/read/write/truncate/size/
  sync/close, merkle_rebuild/verify/commitment) generated from a template
  in tools/generate.py, with errno-mapped exceptions.
- aeg.raf: high-level file-like API (Raf, create/open/probe,
  derive_master_key) with pluggable Storage backends (FileStorage,
  BytesIOStorage) and Merkle tree integrity via a MerkleHasher protocol
  (SHA256MerkleHasher default), adapted from pyaegis (MIT).
- aeg.random: CSPRNG facility. Random produces AEGIS keystream seeded
  once from the OS, exposed per cipher module as cipher.random() and
  usable as the RAF RNG (as_raf_rng) or standalone RandomSource.
- Tests: roundtrip/random-access/seek/truncate/Merkle coverage for all
  six variants, pyaegis-style API checks, and a Merkle fuzz test.
This commit is contained in:
LeoVasanko committed 2026-10-04 04:25:59 +00:00
1 parent e70c7a37d2
commit e01d84a560
14 files changed
+5374 -3

No files matched your search

+35
View File
@@ -1,6 +1,7 @@
from typing import TYPE_CHECKING, Protocol
if TYPE_CHECKING:
from .random import Random
from .util import Buffer
__all__ = ["Cipher"]
@@ -43,6 +44,8 @@ class Cipher(Protocol):
Encryptor: type[_Encryptor]
Decryptor: type[_Decryptor]
@staticmethod
def random() -> "Random": ...
@staticmethod
def random_key() -> bytearray: ...
@staticmethod
@@ -124,3 +127,35 @@ class Cipher(Protocol):
def nonce_increment(nonce: "Buffer") -> None: ...
@staticmethod
def wipe(buffer: "Buffer") -> None: ...
# random-access encrypted files (thin wrappers; see aeg.raf)
RAF_ALG_ID: int
@staticmethod
def new_raf_ctx(): ...
@staticmethod
def raf_scratch_size(chunk_size: int) -> int: ...
@staticmethod
def raf_create(key: "Buffer", ctx, io, rng, config) -> None: ...
@staticmethod
def raf_open(key: "Buffer", ctx, io, rng, config) -> None: ...
@staticmethod
def raf_read(
ctx, length: int, offset: int, *, into: "Buffer | None" = None
) -> bytearray | memoryview: ...
@staticmethod
def raf_write(ctx, data: "Buffer", offset: int) -> int: ...
@staticmethod
def raf_truncate(ctx, size: int) -> None: ...
@staticmethod
def raf_size(ctx) -> int: ...
@staticmethod
def raf_sync(ctx) -> None: ...
@staticmethod
def raf_close(ctx) -> None: ...
@staticmethod
def raf_merkle_rebuild(ctx) -> None: ...
@staticmethod
def raf_merkle_verify(ctx) -> "int | None": ...
@staticmethod
def raf_merkle_commitment(ctx, hash_len: int) -> bytes: ...