packages feed

wireform-parquet-0.1.0.0: scripts/parquet_encrypted_footer_interop.py

#!/usr/bin/env python3
"""Authenticate all official encrypted-file footers against Arrow C++.

The reference reads every physical value, definition/repetition level, index,
and bloom filter. The native check covers FOOTERS ONLY; a passing result does
not claim native encrypted-column or encrypted-index support. Fixture keys are
public test data. External key material is resolved by Arrow's local mock KMS.
"""

import argparse
import hashlib
import json
from pathlib import Path
import shutil
import subprocess
import tempfile

import pyarrow as pa


def digest(path):
    return hashlib.sha256(path.read_bytes()).hexdigest()


def execute(command, *, success=True):
    result = subprocess.run(list(map(str, command)), capture_output=True, text=True, timeout=60)
    if success != (result.returncode == 0):
        raise AssertionError(f"unexpected exit {result.returncode}: {command[0]}: {result.stderr}")
    return result


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--reference", type=Path, required=True)
    parser.add_argument("--reader", type=Path, required=True)
    parser.add_argument("--corpus", type=Path, required=True)
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()
    reference, reader = args.reference.resolve(), args.reader.resolve()
    root = args.corpus.resolve() / "data"
    fixtures = sorted(root.rglob("*.parquet.encrypted"))
    if len(fixtures) < 14:
        raise AssertionError(f"incomplete encrypted corpus: {len(fixtures)} fixtures, expected at least 14")
    results = []
    args.output.parent.mkdir(parents=True, exist_ok=True)
    oracle_dir = args.output.with_suffix(".reference")
    oracle_dir.mkdir(parents=True, exist_ok=True)
    with tempfile.TemporaryDirectory(prefix="wireform-encrypted-footers-") as tmp:
        for fixture in fixtures:
            name = fixture.relative_to(root)
            decoded = execute([reference, fixture]).stdout
            output = oracle_dir / Path(str(name) + ".jsonl")
            output.parent.mkdir(parents=True, exist_ok=True)
            output.write_text(decoded)
            header, *columns = map(json.loads, decoded.splitlines())
            assert len(columns) == header["rowGroups"] * header["columns"], name
            for column in columns:
                assert len(column["definitions"]) == len(column["repetitions"]) == column["events"], name
                assert len(column["values"]) == column["present"], name
            key = header["publicFixtureFooterKeyHex"]
            prefix = "746573746572" if header["prefixRequired"] else header["storedPrefixHex"]

            def native(path=fixture, test_key=key, test_prefix=prefix, success=True):
                return execute([reader, "--authenticate-footer", path, test_key, test_prefix], success=success)

            metadata = json.loads(native().stdout)
            assert metadata["rows"] == header["rows"], name
            assert metadata["rowGroups"] == header["rowGroups"], name
            assert metadata["columns"] == [header["columns"]] * header["rowGroups"], name
            native(test_key="00" * len(bytes.fromhex(key)), success=False)
            native(test_prefix="6f74686572", success=False)
            native(test_prefix="-", success=not header["prefixRequired"])
            tampered = bytearray(fixture.read_bytes())
            tampered[-9] ^= 1
            changed = Path(tmp) / name
            changed.parent.mkdir(parents=True, exist_ok=True)
            changed.write_bytes(tampered)
            sidecar = fixture.with_name("_KEY_MATERIAL_FOR_" + fixture.name + ".json")
            if sidecar.exists():
                shutil.copy2(sidecar, changed.with_name(sidecar.name))
            native(path=changed, success=False)
            execute([reference, changed], success=False)
            results.append({
                "fixture": str(name), "sha256": digest(fixture),
                "rows": header["rows"], "rowGroups": header["rowGroups"], "columns": header["columns"],
                "nativeFooterMatchesReference": True, "tamperedFooterRejectedByBoth": True,
                "wrongKeyRejected": True, "wrongPrefixRejected": True,
                "omittedPrefixRequired": header["prefixRequired"],
                "referenceColumnIndexes": sum(c["columnIndex"] for c in columns),
                "referenceOffsetIndexes": sum(c["offsetPages"] > 0 for c in columns),
                "referenceBlooms": sum(c["bloomBytes"] > 0 for c in columns),
                "referenceOutputSHA256": digest(output),
            })
            print(f"PASS footer {name}", flush=True)
    args.output.write_text(json.dumps({
        "scope": "Native footer authentication only; C++ independently reads complete files",
        "fullNativeEncryptedReadsValidated": False, "pyarrowVersion": pa.__version__,
        "referenceBinarySHA256": digest(reference), "readerBinarySHA256": digest(reader),
        "referenceSourceSHA256": digest(Path(__file__).with_name("parquet_encrypted_reference.cc")),
        "fixtures": results,
    }, indent=2) + "\n")
    print(f"All {len(results)} encrypted footers authenticated; native encrypted-column reads remain unvalidated")


if __name__ == "__main__":
    main()