"""Check synthetic signature vectors using independently written orchestration."""
import hashlib
import json
import pathlib
import rfc8785
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
from cryptography.hazmat.primitives.asymmetric.mldsa import MLDSA44PrivateKey, MLDSA44PublicKey

PREFIX = 'ed25519-ml-dsa-44:'
DATA = pathlib.Path('data')
checks = []


def check(label, passes):
    checks.append({'label': label, 'pass': bool(passes)})


def hybrid(sig, payload, key):
    if not sig.startswith(PREFIX) or not key.startswith(PREFIX):
        return False
    try:
        s, k = bytes.fromhex(sig[len(PREFIX):]), bytes.fromhex(key[len(PREFIX):])
        if len(s) != 2484 or len(k) != 1344:
            return False
        Ed25519PublicKey.from_public_bytes(k[:32]).verify(s[:64], payload)
        MLDSA44PublicKey.from_public_bytes(k[32:]).verify(s[64:], payload)
        return True
    except (ValueError, InvalidSignature):
        return False


def payload(entry):
    return rfc8785.dumps({k:v for k,v in entry.items() if k != 'sig'})


def load(name):
    return json.loads((DATA/f'{name}-vectors.json').read_text())


vectors = load('signature')
for i, c in enumerate(vectors['cases']):
    seed = bytes.fromhex(c['secret_key'])  # Published synthetic test seeds, never the operator key.
    check(f'seed-shape-{i}', len(seed) == 64)
    ed = Ed25519PrivateKey.from_private_bytes(seed[:32])
    ml = MLDSA44PrivateKey.from_seed_bytes(seed[32:])
    key = PREFIX + (ed.public_key().public_bytes_raw() + ml.public_key().public_bytes_raw()).hex()
    check(f'derived-key-{i}', key == c['public_key'])
    message = payload(c['object'])
    check(f'payload-{i}', message.decode() == c['payload'])
    listed = bytes.fromhex(c['sig'][len(PREFIX):])
    check(f'deterministic-ed-{i}', ed.sign(message) == listed[:64])
    check(f'listed-signature-{i}', hybrid(c['sig'],message,key))
    fresh = PREFIX + (ed.sign(message) + ml.sign(message)).hex()
    check(f'fresh-signature-{i}', hybrid(fresh,message,key))
    # Confirm that a nonempty context cannot verify the empty-context signature.
    try:
        ml.public_key().verify(listed[64:],message,b'independent-control')
        rejected = False
    except InvalidSignature:
        rejected = True
    check(f'context-negative-control-{i}', rejected)
for i,c in enumerate(vectors['invalid']):
    check(f'invalid-signature-{i}', not hybrid(c['sig'],payload(c['object']),c['public_key']))

ids = load('id')
known = {c['operator_id']:c['public_key'] for c in ids['operators']}
for i,c in enumerate(ids['entries']):
    entry = c['entry']
    key = entry['key'] if entry['type'] == 'key' else known[entry['operator']] if 'operator' in entry else ids['operators'][0]['public_key']
    check(f'entry-signature-{i}',hybrid(entry['sig'],payload(entry),key))
    if entry['type'] == 'key_rotation':
        unsigned = {k:entry[k] for k in ['type','operator','key']}
        check('new-key-rotation-consent',hybrid(entry['key_sig'],rfc8785.dumps(unsigned),entry['key']))
        check('rotation-preserves-first-id',entry['operator'] != 'op:'+hashlib.sha256(entry['key'].encode()).hexdigest())
for i,c in enumerate(load('log')['leaf_examples']):
    entry = c['signed_entry']; key = entry['key'] if entry['type'] == 'key' else known[c['leaf']['operator']]
    check(f'log-entry-signature-{i}',hybrid(entry['sig'],payload(entry),key))
report = {'checks':len(checks),'passed':sum(c['pass'] for c in checks),'failures':[c for c in checks if not c['pass']], 'scope':'Independent control logic using cryptography 50.0.2 for the same signature primitives; no independent implementation of Ed25519 or ML-DSA itself.'}
pathlib.Path('results/hybrid-audit.json').write_text(json.dumps(report,indent=2)+'\n')
print(json.dumps(report))
raise SystemExit(1 if report['failures'] else 0)
