Commit Graph
17 Commits
Author SHA1 Message Date
LeoVasanko 503ce8e491 Fix FileStorage on Windows: open fd with O_BINARY, UTF-8 release logs
release / build-wheels (linux, bash) (push) Successful in 1m13s
release / build-wheels (windows, cmd) (push) Successful in 1m20s
release / build-wheels (macos, bash) (push) Successful in 1m26s
release / publish-pypi (push) Failing after 2s
os.open() on Windows defaults to O_TEXT, so the CRT translated \r\n in
binary ciphertext: writes grew, offsets shifted, reads came up short and
the RAF callbacks failed with EIO (probe/read/write depending on where
a 0x0A byte landed). Pass O_BINARY where it exists.

Also reconfigure stdout/stderr to UTF-8 in tools/release.py so the
✓/✗/⚠ summary lines don't crash on cp1252 Windows consoles.
2026-10-04 17:48:34 +00:00
LeoVasanko 9583a1f9a8 Fix cdef size_t size on Win64 (LLP64), require 64-bit builds
release / build-wheels (linux, bash) (push) Successful in 1m12s
release / build-wheels (windows, cmd) (push) Failing after 1m16s
release / build-wheels (macos, bash) (push) Successful in 1m21s
release / publish-pypi (push) Skipped
The generated cdef typedef'd size_t as unsigned long: 8 bytes on LP64
but only 4 on 64-bit Windows, where C's size_t is 8. cffi's import-time
struct layout verification then failed (aegis_raf_scratch.len: cdef
says 4, C compiler says 8). cffi pre-defines size_t/uint8_t with the
correct platform sizes, so don't typedef them.

Also hard-fail 32-bit build attempts in setup.py; 32-bit platforms are
no longer supported.
2026-10-04 17:32:52 +00:00
LeoVasanko 276b2faa0b benchmark.py: uv run shebang, executable bit, stdlib-random shadowing guard
release / build-wheels (windows, cmd) (push) Failing after 10s
release / build-wheels (linux, bash) (push) Failing after 47s
release / build-wheels (macos, bash) (push) Successful in 1m25s
release / publish-pypi (push) Skipped
Fixes CI EXE001 (shebang on non-executable file). Running the script
directly puts src/aeg on sys.path, where aeg/random.py would shadow the
stdlib random module that secrets and others import — pop it before any
imports so both direct execution and -m aeg.benchmark work.
2026-10-04 16:50:37 +00:00
LeoVasanko b4404b42e6 Fix ruff 0.16 findings; bump dependency minimums to match
release / build-wheels (windows, cmd) (push) Failing after 11s
release / build-wheels (linux, bash) (push) Failing after 10s
release / build-wheels (macos, bash) (push) Failing after 11s
release / publish-pypi (push) Skipped
- pyproject [tool.ruff.lint]: ignore RUF022/RUF023 (deliberately grouped
  __all__/__slots__), SIM117, BLE001 (blind except is intentional at
  CFFI callback boundaries)
- Legit fixes: dict/tuple instead of typing.Dict/Tuple in generate.py,
  unquoted annotations in raf.py, Self return for __enter__ methods,
  explicit check=False on subprocess.run, collapsed nested ifs, sorted
  test imports, unused-unpacked-variable in test_raises
- Bump minimum versions to the synced toolchain: cffi 2.1.1, ruff
  0.16.10, pytest 9.1.1, auditwheel 6.8.2, setuptools 84.0.0,
  setuptools-scm 10.3.4 (project deps and build-system requires)
2026-10-04 16:24:40 +00:00
LeoVasanko 1eb0b6e8c0 Add stream_xor(); deprecate encrypt/decrypt_unauthenticated
release / build-wheels (linux, bash) (push) Failing after 15s
release / build-wheels (windows, cmd) (push) Failing after 1m14s
release / build-wheels (macos, bash) (push) Failing after 18s
release / publish-pypi (push) Skipped
Following upstream libaegis 0.10.5 (874f884): the absorbing-mode
unauthenticated pair is deprecated in favor of the pure keystream XOR.
- stream_xor(key, nonce, data, into=None): same function encrypts and
  decrypts; output equals data XOR stream(key, nonce); supports in-place
  use via into (same buffer semantics as elsewhere).
- encrypt_unauthenticated/decrypt_unauthenticated kept for the old
  format but now emit DeprecationWarning; removed from README (stream_xor
  documented under Keystream generation instead).
2026-10-04 15:57:28 +00:00
LeoVasanko 9d36d3b81b random(): per-thread singleton; random_key/random_nonce use it
Each cipher module's random() now returns a thread-local Random that is
created on first use and reused thereafter. Each thread gets its own
OS-seeded generator (own key+nonce), so no locking and no cross-thread
nonce collisions. random_key() and random_nonce() draw from this CSPRNG
instead of secrets.token_bytes, making them as fast as the stream.
Changes made in the aegis256x4.py template and regenerated.
2026-10-04 15:42:02 +00:00
LeoVasanko 32954c4eba aeg.raf: StreamStorage adapter; accept io.BytesIO directly
StreamStorage wraps any seek-based file-like object using the same
lock + seek/read/write pattern as FileStorage's fallback for platforms
without pread/pwrite. create()/open() auto-wrap io.BytesIO, so in-memory
use no longer requires the explicit BytesIOStorage wrapper. The caller
keeps ownership of the stream (Raf does not close it).
2026-10-04 14:30:59 +00:00
LeoVasanko faa24cf22e Add aeg.securebuf.SecureBuffer: locked, wipe-on-close memory
mmap-backed buffer locked against swapping (mlock/VirtualLock) and
excluded from core dumps (MADV_DONTDUMP) where available, wiped on
close. Not used for return values; intended as an 'into' target (and
key input) to keep sensitive material out of the regular heap.
Adapted from quantumpipe's securebuf module.
2026-10-04 05:44:04 +00:00
LeoVasanko 972c3053d9 Require Python 3.12+; drop PyPy and 3.10/3.11 wheel builds
- requires-python >= 3.12; abi3 limited API tag cp310 -> cp312
- util.Buffer now imported directly from collections.abc (no fallback)
- release.py: ABI3 wheel covers 3.12-3.15; PyPy wheels dropped (PyPy
  has no 3.12 support yet)
2026-10-04 05:42:22 +00:00
LeoVasanko 199dfe7bd9 generate.py: run ruff format on generated files
Running generate.py standalone previously rewrote _ciphers.py with
formatting that differed from the committed (ruff-formatted) style,
creating spurious diffs. release.py already ran ruff after generation;
now generate.py does too, so both entry points leave the tree in the
same state.
2026-10-04 05:41:14 +00:00
LeoVasanko e01d84a560 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.
2026-10-04 04:25:59 +00:00
LeoVasanko e70c7a37d2 Update libaegis submodule 0.9.0 -> 0.10.6
89 upstream commits: Zig 0.16 compat, symbol namespacing, opaque state
structs, new stream_xor and random-access file APIs. Regenerated
aegis_cdef.h; Python modules unchanged. Full release build verified:
5 wheels + sdist, tests/benchmarks pass on all 10 Python versions.
2026-10-04 02:58:47 +00:00
LeoVasanko a1bfeb2434 Build updated for upstream libaegis 0.9.0 simplified API with matching changes on Python side. Set lower MacOS build target (11.0). Build abi3 version for all supported Python versions, reducing the number of wheels. Other build cleanup. 2026-01-10 20:23:37 +00:00
LeoVasanko 7e6a5bf52a Allow the cipher() function also work without prefix aegis 2026-01-04 14:25:39 +00:00
LeoVasanko 8018e68274 Add nonce_increment and wipe functions on typing. 2026-01-04 14:19:01 +00:00
LeoVasanko 67ec091bc5 Add aeg.cipher(alg) for loading modules by name in str. Added aeg.CIPHERS mapping of the nominal names to module names and Cipher for typing literals. 2025-12-31 21:38:30 +00:00
LeoVasanko bd8b183e32 Project renamed to aeg, preparing for PyPI release. 2025-12-23 18:25:03 +00:00