Initial commit
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
"""Demonstration script for aegis.aegis256x4
|
||||
|
||||
Covers:
|
||||
- encrypt_detached / decrypt_detached
|
||||
- encrypt / decrypt (attached tag)
|
||||
- stream_into
|
||||
- encrypt_unauthenticated_into / decrypt_unauthenticated_into
|
||||
- MAC (mac_init/update/final/verify)
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
from aegis import aegis256x4 as a
|
||||
|
||||
|
||||
def hx(b, limit: int | None = None) -> str:
|
||||
data = bytes(b)
|
||||
if limit is not None:
|
||||
data = data[:limit]
|
||||
return data.hex()
|
||||
|
||||
|
||||
def demo():
|
||||
print("KEYBYTES:", a.KEYBYTES, "NPUBBYTES:", a.NPUBBYTES)
|
||||
|
||||
key = b"K" * a.KEYBYTES
|
||||
nonce = b"N" * a.NPUBBYTES
|
||||
message = b"hello world"
|
||||
associated_data = b"header"
|
||||
|
||||
# Detached encrypt/decrypt
|
||||
ciphertext, mac = a.encrypt_detached(
|
||||
nonce, key, message, associated_data, maclen=16
|
||||
)
|
||||
plaintext = a.decrypt_detached(nonce, key, ciphertext, mac, associated_data)
|
||||
print(
|
||||
"detached enc: c=",
|
||||
hx(ciphertext),
|
||||
" mac=",
|
||||
hx(mac),
|
||||
" dec_ok=",
|
||||
plaintext == message,
|
||||
)
|
||||
|
||||
# Attached encrypt/decrypt
|
||||
ciphertext_with_tag = a.encrypt(nonce, key, message, associated_data, maclen=32)
|
||||
plaintext2 = a.decrypt(nonce, key, ciphertext_with_tag, associated_data, maclen=32)
|
||||
print(
|
||||
"attached enc: ct=", hx(ciphertext_with_tag), " dec_ok=", plaintext2 == message
|
||||
)
|
||||
|
||||
# Stream generation (None nonce allowed) -> deterministic for a given key
|
||||
stream = bytearray(64)
|
||||
a.stream(None, key, into=stream)
|
||||
print("stream (first 16 bytes):", hx(stream, 16))
|
||||
|
||||
# Unauthenticated mode round-trip (INSECURE; compatibility only)
|
||||
c2 = bytearray(len(message))
|
||||
a.encrypt_unauthenticated(message, nonce, key, into=c2)
|
||||
m2 = bytearray(len(message))
|
||||
a.decrypt_unauthenticated(c2, nonce, key, into=m2)
|
||||
print("unauth round-trip ok:", bytes(m2) == message)
|
||||
|
||||
# MAC: compute then verify
|
||||
mac_state = a.Mac(nonce, key)
|
||||
mac_state.update(message)
|
||||
mac32 = mac_state.final(32)
|
||||
|
||||
mac_verify_state = a.Mac(nonce, key)
|
||||
mac_verify_state.update(message)
|
||||
try:
|
||||
mac_verify_state.verify(mac32)
|
||||
print("mac verify: ok", " mac=", hx(mac32))
|
||||
except ValueError:
|
||||
print("mac verify: failed")
|
||||
|
||||
# Benchmark: unauthenticated encryption of 1 GiB as a single operation
|
||||
total_bytes = 1 << 30 # 1 GiB
|
||||
|
||||
def bench_unauth_single(total: int):
|
||||
src = bytearray(total)
|
||||
dst = bytearray(total)
|
||||
t0 = time.perf_counter()
|
||||
a.encrypt_unauthenticated(src, nonce, key, into=dst)
|
||||
t1 = time.perf_counter()
|
||||
secs = t1 - t0
|
||||
gib = total / float(1 << 30)
|
||||
gbps = gib / secs if secs > 0 else float("inf")
|
||||
print(
|
||||
f"unauth 1GiB bench (single call): size={gib:.3f} GiB, time={secs:.3f} s, throughput={gbps:.2f} GiB/s"
|
||||
)
|
||||
|
||||
bench_unauth_single(total_bytes)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo()
|
||||
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Python benchmark matching src/test/benchmark.zig for all supported Aegis algorithms.
|
||||
|
||||
It performs two benchmarks with the same parameters as the Zig version:
|
||||
- AEGIS encrypt (attached tag, maclen = ABYTES_MIN)
|
||||
- AEGIS MAC (clone state pattern)
|
||||
|
||||
Output format and throughput units mirror the Zig benchmark (Mb/s).
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from aegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
|
||||
MSG_LEN = 16384000 # 16 MiB
|
||||
ITERATIONS = 100
|
||||
|
||||
ALGORITHMS = [
|
||||
("AEGIS-128L", aegis128l),
|
||||
("AEGIS-128X2", aegis128x2),
|
||||
("AEGIS-128X4", aegis128x4),
|
||||
("AEGIS-256", aegis256),
|
||||
("AEGIS-256X2", aegis256x2),
|
||||
("AEGIS-256X4", aegis256x4),
|
||||
]
|
||||
|
||||
|
||||
def _random_bytes(n: int) -> bytes:
|
||||
return os.urandom(n)
|
||||
|
||||
|
||||
def bench_encrypt(alg_name: str, a) -> None:
|
||||
key = _random_bytes(a.KEYBYTES)
|
||||
nonce = _random_bytes(a.NPUBBYTES)
|
||||
|
||||
# Single buffer, as in Zig: c_out == m buffer, with tag appended
|
||||
maclen = a.ABYTES_MIN
|
||||
buf = bytearray(MSG_LEN + maclen)
|
||||
# Initialize buffer with random data
|
||||
buf[:] = _random_bytes(len(buf))
|
||||
|
||||
mview = memoryview(buf)[:MSG_LEN]
|
||||
|
||||
t0 = time.perf_counter()
|
||||
for _ in range(ITERATIONS):
|
||||
a.encrypt(nonce, key, mview, None, maclen=maclen, into=buf)
|
||||
t1 = time.perf_counter()
|
||||
|
||||
# Prevent any unrealistic optimization assumptions
|
||||
_ = buf[0]
|
||||
|
||||
bits = MSG_LEN * ITERATIONS * 8
|
||||
elapsed_s = t1 - t0
|
||||
throughput_mbps = (
|
||||
(bits / (elapsed_s * 1_000_000)) if elapsed_s > 0 else float("inf")
|
||||
)
|
||||
print(f"{alg_name}\t{throughput_mbps:10.2f} Mb/s")
|
||||
|
||||
|
||||
def bench_mac(alg_name: str, a) -> None:
|
||||
key = _random_bytes(a.KEYBYTES)
|
||||
nonce = _random_bytes(a.NPUBBYTES)
|
||||
|
||||
buf = bytearray(MSG_LEN)
|
||||
buf[:] = _random_bytes(len(buf))
|
||||
|
||||
mac0 = a.Mac(nonce, key)
|
||||
mac_out = bytearray(a.ABYTES_MAX)
|
||||
|
||||
t0 = time.perf_counter()
|
||||
for _ in range(ITERATIONS):
|
||||
mac = mac0.clone()
|
||||
mac.update(buf)
|
||||
mac.final(maclen=a.ABYTES_MAX, into=mac_out)
|
||||
t1 = time.perf_counter()
|
||||
|
||||
_ = mac_out[0]
|
||||
|
||||
bits = MSG_LEN * ITERATIONS * 8
|
||||
elapsed_s = t1 - t0
|
||||
throughput_mbps = (
|
||||
(bits / (elapsed_s * 1_000_000)) if elapsed_s > 0 else float("inf")
|
||||
)
|
||||
print(f"{alg_name} MAC\t{throughput_mbps:10.2f} Mb/s")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# aegis_init() is called in the loader at import time already
|
||||
# Run encrypt benchmarks in order: 256, 256x2, 256x4, 128l, 128x2, 128x4
|
||||
bench_encrypt("AEGIS-256", aegis256)
|
||||
bench_encrypt("AEGIS-256X2", aegis256x2)
|
||||
bench_encrypt("AEGIS-256X4", aegis256x4)
|
||||
bench_encrypt("AEGIS-128L", aegis128l)
|
||||
bench_encrypt("AEGIS-128X2", aegis128x2)
|
||||
bench_encrypt("AEGIS-128X4", aegis128x4)
|
||||
|
||||
# Run MAC benchmarks in order: 128l, 128x2, 128x4, 256, 256x2, 256x4
|
||||
bench_mac("AEGIS-128L", aegis128l)
|
||||
bench_mac("AEGIS-128X2", aegis128x2)
|
||||
bench_mac("AEGIS-128X4", aegis128x4)
|
||||
bench_mac("AEGIS-256", aegis256)
|
||||
bench_mac("AEGIS-256X2", aegis256x2)
|
||||
bench_mac("AEGIS-256X4", aegis256x4)
|
||||
Reference in New Issue
Block a user