aevum-verify 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,52 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+ .venv/
7
+ *.egg-info/
8
+
9
+ # Build
10
+ dist/
11
+ build/
12
+ site/
13
+
14
+ # Tools
15
+ .mypy_cache/
16
+ .ruff_cache/
17
+ .pytest_cache/
18
+ .hypothesis/
19
+ .cache/
20
+
21
+ # IDE
22
+ .vscode/
23
+ .idea/
24
+ *.swp
25
+ *.swo
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # Verify scripts (run locally, never commit)
32
+ verify_*.py
33
+ scripts/verify_*.py
34
+
35
+ # Aevum development — never commit (Phase 0+)
36
+ aevum_principles.key
37
+ signed_principles_draft.yaml
38
+ tools/sign_principles.py
39
+
40
+ # Private keys — never commit
41
+ *.key
42
+ *.pem
43
+
44
+ # OpenSSF Scorecard output (Phase 0+)
45
+ results.sarif
46
+ verify_phase3.py
47
+ verify_phase7.py
48
+ verify_phase8.py
49
+ verify_phase*.py
50
+
51
+ # Maintenance generated files — local only, never commit
52
+ maintenance/generated/
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: aevum-verify
3
+ Version: 0.8.0
4
+ Summary: Aevum — standalone sigchain verifier.
5
+ Project-URL: Homepage, https://aevum.build
6
+ Project-URL: Repository, https://github.com/aevum-labs/aevum
7
+ License: Apache-2.0
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Typing :: Typed
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: aevum-core
17
+ Provides-Extra: dev
18
+ Requires-Dist: mypy>=1.10; extra == 'dev'
19
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
20
+ Requires-Dist: pytest>=8.0; extra == 'dev'
21
+ Requires-Dist: ruff>=0.9; extra == 'dev'
22
+ Provides-Extra: pqc
23
+ Requires-Dist: liboqs-python>=0.14.0; extra == 'pqc'
File without changes
@@ -0,0 +1,75 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ [project]
3
+ name = "aevum-verify"
4
+ version = "0.8.0"
5
+ description = "Aevum — standalone sigchain verifier."
6
+ readme = "README.md"
7
+ requires-python = ">=3.11"
8
+ license = { text = "Apache-2.0" }
9
+ classifiers = [
10
+ "Development Status :: 4 - Beta",
11
+ "Intended Audience :: Developers",
12
+ "License :: OSI Approved :: Apache Software License",
13
+ "Programming Language :: Python :: 3.11",
14
+ "Programming Language :: Python :: 3.12",
15
+ "Programming Language :: Python :: 3.13",
16
+ "Typing :: Typed",
17
+ ]
18
+ dependencies = [
19
+ "aevum-core",
20
+ ]
21
+
22
+ [project.optional-dependencies]
23
+ pqc = [
24
+ "liboqs-python>=0.14.0",
25
+ ]
26
+ dev = [
27
+ "pytest>=8.0",
28
+ "pytest-asyncio>=0.23",
29
+ "mypy>=1.10",
30
+ "ruff>=0.9",
31
+ ]
32
+
33
+ [project.scripts]
34
+ aevum-verify = "aevum.verify.__main__:main"
35
+
36
+ [project.urls]
37
+ Homepage = "https://aevum.build"
38
+ Repository = "https://github.com/aevum-labs/aevum"
39
+
40
+ [build-system]
41
+ requires = ["hatchling"]
42
+ build-backend = "hatchling.build"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/aevum"]
46
+
47
+ [tool.uv.sources]
48
+ aevum-core = { workspace = true }
49
+
50
+ [tool.pytest.ini_options]
51
+ testpaths = ["tests"]
52
+ asyncio_mode = "auto"
53
+ addopts = "--tb=short"
54
+ pythonpath = ["src", "tests"]
55
+
56
+ [tool.mypy]
57
+ strict = true
58
+ python_version = "3.11"
59
+ mypy_path = "src"
60
+ ignore_missing_imports = true
61
+
62
+ [[tool.mypy.overrides]]
63
+ module = "oqs"
64
+ ignore_missing_imports = true
65
+
66
+ [tool.ruff]
67
+ line-length = 130
68
+ target-version = "py311"
69
+
70
+ [tool.ruff.lint]
71
+ select = ["E", "F", "UP", "B", "SIM", "I", "ANN"]
72
+ ignore = ["ANN401"]
73
+
74
+ [tool.ruff.lint.per-file-ignores]
75
+ "tests/**" = ["ANN"]
@@ -0,0 +1,20 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ from aevum.verify._core import (
3
+ VerifyResult,
4
+ dump_chain,
5
+ event_from_dict,
6
+ event_to_dict,
7
+ load_chain,
8
+ verify_chain,
9
+ verify_entry,
10
+ )
11
+
12
+ __all__ = [
13
+ "VerifyResult",
14
+ "verify_entry",
15
+ "verify_chain",
16
+ "load_chain",
17
+ "dump_chain",
18
+ "event_to_dict",
19
+ "event_from_dict",
20
+ ]
@@ -0,0 +1,94 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """
3
+ aevum-verify — standalone sigchain verifier CLI.
4
+
5
+ Usage:
6
+ aevum-verify CHAIN_FILE --ed25519-pub HEX [--mldsa65-pub HEX]
7
+
8
+ CHAIN_FILE Path to a JSON file containing a list of serialised chain entries.
9
+ --ed25519-pub Pinned Ed25519 public key as 64-char hex, or @/path/to/file for
10
+ raw 32-byte binary.
11
+ --mldsa65-pub Pinned ML-DSA-65 public key as hex or @filepath; required for
12
+ hybrid (ed25519+ml-dsa-65) chains.
13
+
14
+ Exit codes:
15
+ 0 VERIFIED — all entries intact.
16
+ 1 FAILED — chain tampered, signature invalid, or trust-anchor mismatch.
17
+ 2 Usage error (bad arguments or unreadable file).
18
+ """
19
+ from __future__ import annotations
20
+
21
+ import argparse
22
+ import sys
23
+ from pathlib import Path
24
+
25
+ from aevum.verify._core import load_chain, verify_chain
26
+
27
+
28
+ def _load_key(value: str) -> bytes:
29
+ """Load a key from a hex string or @filepath (raw binary)."""
30
+ if value.startswith("@"):
31
+ return Path(value[1:]).read_bytes()
32
+ return bytes.fromhex(value)
33
+
34
+
35
+ def main() -> None:
36
+ parser = argparse.ArgumentParser(
37
+ prog="aevum-verify",
38
+ description="Verify an Aevum sigchain export against pinned public keys.",
39
+ formatter_class=argparse.RawDescriptionHelpFormatter,
40
+ epilog=__doc__,
41
+ )
42
+ parser.add_argument("chain_file", metavar="CHAIN_FILE", help="path to JSON chain file")
43
+ parser.add_argument(
44
+ "--ed25519-pub",
45
+ required=True,
46
+ metavar="HEX",
47
+ help="pinned Ed25519 public key (64-char hex or @filepath)",
48
+ )
49
+ parser.add_argument(
50
+ "--mldsa65-pub",
51
+ default=None,
52
+ metavar="HEX",
53
+ help="pinned ML-DSA-65 public key (hex or @filepath); required for hybrid chains",
54
+ )
55
+ args = parser.parse_args()
56
+
57
+ try:
58
+ ed25519_pub = _load_key(args.ed25519_pub)
59
+ except Exception as exc:
60
+ print(f"ERROR: invalid --ed25519-pub: {exc}", file=sys.stderr)
61
+ sys.exit(2)
62
+
63
+ mldsa65_pub: bytes | None = None
64
+ if args.mldsa65_pub:
65
+ try:
66
+ mldsa65_pub = _load_key(args.mldsa65_pub)
67
+ except Exception as exc:
68
+ print(f"ERROR: invalid --mldsa65-pub: {exc}", file=sys.stderr)
69
+ sys.exit(2)
70
+
71
+ try:
72
+ chain_path = Path(args.chain_file)
73
+ entries = load_chain(chain_path)
74
+ except Exception as exc:
75
+ print(f"ERROR: could not load chain file: {exc}", file=sys.stderr)
76
+ sys.exit(2)
77
+
78
+ result = verify_chain(entries, ed25519_pub=ed25519_pub, mldsa65_pub=mldsa65_pub)
79
+
80
+ if result.ok:
81
+ print(f"VERIFIED — {len(entries)} entries intact")
82
+ sys.exit(0)
83
+ else:
84
+ idx = result.failing_index
85
+ reason = result.reason
86
+ if idx is not None:
87
+ print(f"FAILED — entry {idx}: {reason}", file=sys.stderr)
88
+ else:
89
+ print(f"FAILED — {reason}", file=sys.stderr)
90
+ sys.exit(1)
91
+
92
+
93
+ if __name__ == "__main__":
94
+ main()