"""Test 1: does cryptography's into-API (CipherContext.update_into) accept an immutable bytes object as the output buffer, despite bytes being read-only? Python's buffer protocol will hand out a buffer descriptor for bytes (pyo3 requests PyBUF_FULL_RO), so the only thing stopping the write is an explicit readonly check in cryptography's Rust binding. This script finds out, and verifies correctness against the normal bytes-returning update() call. """ from cryptography.hazmat.primitives.ciphers import Cipher from cryptography.hazmat.primitives.ciphers.algorithms import ChaCha20 KEY = bytes(range(32)) NONCE = bytes(16) DATA = b"The quick brown fox jumps over the lazy dog" def fresh_encryptor(): return Cipher(ChaCha20(KEY, NONCE), mode=None).encryptor() def main(): expected = fresh_encryptor().update(DATA) # control: writable bytearray must work buf = bytearray(len(DATA)) n = fresh_encryptor().update_into(DATA, buf) assert bytes(buf) == expected and n == len(DATA) print(f"control bytearray : ok ({n} bytes written)") # the hack: immutable bytes as the output buffer. # Fresh object: refcount 1, zero-filled, cached hash not yet computed, # so no other code can observe the pre-mutation state. out = bytes(len(DATA)) print(f"before bytes({len(DATA)}) : {out[:16].hex()}...") try: n = fresh_encryptor().update_into(DATA, out) except Exception as e: # noqa: BLE001 -- probing behavior, any error is the answer print(f"bytes-hack : REJECTED {type(e).__name__}: {e}") return print(f"bytes-hack : ACCEPTED ({n} bytes written)") print(f"after bytes({len(DATA)}) : {out[:16].hex()}...") print(f"mutated in place : {out != bytes(len(DATA))}") print(f"matches update() result : {out == expected}") # and via an explicit memoryview (readonly flag should propagate) try: fresh_encryptor().update_into(DATA, memoryview(bytes(len(DATA)))) except Exception as e: # noqa: BLE001 -- probing behavior, any error is the answer print(f"memoryview(bytes) : REJECTED {type(e).__name__}: {e}") else: print("memoryview(bytes) : ACCEPTED") if __name__ == "__main__": main()