Metadata-Version: 2.4
Name: parmana-verifier
Version: 0.1.0
Summary: Offline verifier for Parmana Execution Trust Records (Python).
License: Apache-2.0
Project-URL: Repository, https://github.com/pavancharak/parmana-verifier
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: cryptography>=42
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"

# parmana-verifier (Python)

Check whether a Parmana Execution Trust Record was signed by a key you trust, using only the record and a trust file. No network access, no account, no Parmana server needed.

This is the Python counterpart of the Node verifier in the repository root. It checks the same things in the same order, and it returns the same result shape and exit codes. Its results match the Node verifier on every test vector and on records generated by each implementation.

## What it checks, and what it does not

**Checked**

- The record hash (`trustRecordHash`) against the canonical record fields.
- The Ed25519 signature, over the legacy message, from a key in your trust file.
- Ed25519 signatures in a hybrid `signatures` array, and the whole-record (schema version 3) message.
- Trust rules: the key's fingerprint, its validity window, and the `compromised` flag.
- The `hybridRequiredFrom` cutover, when the trust file sets one.

**Not checked: ML-DSA-65 (`dilithium3`) signatures.** The `cryptography` package does not provide ML-DSA. A record with a `dilithium3` entry is reported as invalid, so this verifier never accepts a hybrid record on its Ed25519 part alone. To check the ML-DSA-65 part, use the Node verifier (`@parmana/verifier`) on Node 24 or later with OpenSSL 3.5 or later.

**Other differences from the Node verifier**

- A timestamp without a time zone offset is rejected. Node reads it in the local time zone, so this verifier gives the same answer on every machine.
- Integers beyond 2^53 are rounded the way JavaScript rounds them when it parses JSON. Use records written by Parmana, which never contain such integers.

## Install

Requires Python 3.11 or later (tested on 3.11, 3.12 and 3.13). The only dependency is `cryptography` (version 42 or later). It is not yet published to PyPI, so install from a clone of this repository:

```sh
cd python
pip install -e .
```

For the tests, install the `test` extra as well: `pip install -e ".[test]"`.

## Command line

```sh
parmana-verify <proof.json> <trust.json>
parmana-verify key-fingerprint <public-key.pem>
```

- `verify` prints one line of JSON and exits `0` when the record is valid, `1` when it is invalid, and `2` for a usage or read error.
- `key-fingerprint` prints the `sha256:...` value to pin in a trust file.

The output has the same fields as the Node CLI: `valid`, `coverage`, `errors` and `checks`.

## Python API

```python
import json
from parmana_verifier import parse_trust_policy, verify_execution_trust_record

record = json.load(open("proof.json"))
policy = parse_trust_policy(json.load(open("trust.json")))

result = verify_execution_trust_record(record, policy.keys, policy.hybrid_required_from)
print(result["valid"], result["errors"])
```

## Trust file

The trust file lists each key you accept, pinned by its fingerprint. See the [main README](../README.md#installation-and-usage) for the format. The verifier never fetches keys.

## Tests

```sh
cd python
pip install -e ".[test]"
pytest
```

The tests run the shared test vectors in `../test/vectors`, check the canonical serialization against JavaScript's number and string formatting, and generate Ed25519 records at test time to cover the trust rules and the CLI.
