release: freeze Nexus One AI 1.0.0-rc1
This commit is contained in:
1 parent
63acefd890
commit
4f1419ca93
152 files changed
+9445
-828
No files matched your search
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify signed Python profile membership and emit a bound verification receipt."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class VerificationError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
def canonical(value: dict) -> bytes:
|
||||
return (json.dumps(value, sort_keys=True, separators=(",", ":")) + "\n").encode()
|
||||
|
||||
|
||||
def sha256(data: bytes) -> str:
|
||||
return hashlib.sha256(data).hexdigest()
|
||||
|
||||
|
||||
def verify(manifest: dict, envelope: dict, trust: dict, public_key: Path,
|
||||
environment: str, verified_at: str, verifier_build_sha256: str) -> dict:
|
||||
body = canonical(manifest)
|
||||
manifest_digest = sha256(body)
|
||||
if manifest.get("namespace") != "offline-workstation/python-runtime-profiles":
|
||||
raise VerificationError("NAMESPACE_INVALID")
|
||||
if envelope.get("schema") != "com.cezen.nexus-one.signature-envelope.v1" \
|
||||
or envelope.get("algorithm") != "ed25519":
|
||||
raise VerificationError("ENVELOPE_INVALID")
|
||||
if envelope.get("manifest_digest") != f"sha256:{manifest_digest}":
|
||||
raise VerificationError("MANIFEST_DIGEST_MISMATCH")
|
||||
if envelope.get("policy_version") != trust.get("policy_version"):
|
||||
raise VerificationError("POLICY_VERSION_MISMATCH")
|
||||
keys = [item for item in trust.get("keys", []) if item.get("key_id") == envelope.get("key_id")]
|
||||
if len(keys) != 1:
|
||||
raise VerificationError("KEY_UNKNOWN_OR_AMBIGUOUS")
|
||||
key = keys[0]
|
||||
required = {"algorithm": "ed25519", "purpose": "profile-membership", "status": "active",
|
||||
"environment": environment}
|
||||
if any(key.get(name) != value for name, value in required.items()):
|
||||
raise VerificationError("KEY_POLICY_REJECTED")
|
||||
der = subprocess.run(
|
||||
["openssl", "pkey", "-pubin", "-in", str(public_key), "-outform", "DER"],
|
||||
check=True, capture_output=True,
|
||||
).stdout
|
||||
fingerprint = sha256(der)
|
||||
if fingerprint != key.get("public_key_sha256"):
|
||||
raise VerificationError("KEY_FINGERPRINT_MISMATCH")
|
||||
try:
|
||||
signature = base64.b64decode(envelope.get("signature", ""), validate=True)
|
||||
except ValueError as error:
|
||||
raise VerificationError("SIGNATURE_ENCODING_INVALID") from error
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
body_path = Path(directory) / "manifest.canonical.json"
|
||||
signature_path = Path(directory) / "signature.bin"
|
||||
body_path.write_bytes(body)
|
||||
signature_path.write_bytes(signature)
|
||||
result = subprocess.run([
|
||||
"openssl", "pkeyutl", "-verify", "-pubin", "-inkey", str(public_key),
|
||||
"-rawin", "-in", str(body_path), "-sigfile", str(signature_path),
|
||||
], capture_output=True)
|
||||
if result.returncode != 0:
|
||||
raise VerificationError("SIGNATURE_INVALID")
|
||||
return {
|
||||
"schema": "com.cezen.nexus-one.profile-membership-verification-receipt.v1",
|
||||
"environment": environment,
|
||||
"result": "verified",
|
||||
"manifest_sha256": manifest_digest,
|
||||
"envelope_sha256": sha256(canonical(envelope)),
|
||||
"key_id": envelope["key_id"],
|
||||
"key_fingerprint_sha256": fingerprint,
|
||||
"trust_snapshot_sha256": sha256(canonical(trust)),
|
||||
"policy_version": trust["policy_version"],
|
||||
"namespace": manifest["namespace"],
|
||||
"profiles": sorted(manifest["profiles"]),
|
||||
"verified_at": verified_at,
|
||||
"verifier_build_sha256": verifier_build_sha256,
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--manifest", type=Path, required=True)
|
||||
parser.add_argument("--envelope", type=Path, required=True)
|
||||
parser.add_argument("--trust-snapshot", type=Path, required=True)
|
||||
parser.add_argument("--public-key", type=Path, required=True)
|
||||
parser.add_argument("--environment", choices=("production", "test"), required=True)
|
||||
parser.add_argument("--verified-at", required=True)
|
||||
args = parser.parse_args()
|
||||
script_digest = sha256(Path(__file__).read_bytes())
|
||||
try:
|
||||
receipt = verify(
|
||||
json.loads(args.manifest.read_text()), json.loads(args.envelope.read_text()),
|
||||
json.loads(args.trust_snapshot.read_text()), args.public_key,
|
||||
args.environment, args.verified_at, script_digest,
|
||||
)
|
||||
except (VerificationError, subprocess.CalledProcessError, json.JSONDecodeError) as error:
|
||||
print(json.dumps({"result": "rejected", "code": str(error)}, sort_keys=True))
|
||||
return 1
|
||||
print(json.dumps(receipt, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user