Implement Schnorr's identification protocol as a non-interactive zero-knowledge proof (NIZK) using Fiat-Shamir, with optional message binding. Submit: Python or Rust code that (a) generates a keypair over secp256k1 or Ed25519, (b) produces a NIZK proof of knowledge of the secret key, binding an optional message, (c) verifies the proof. Include a soundness test that produces 10,000 proofs with a forged witness and confirms 0 verify. Include a ZK test: a simulator that produces a valid-looking transcript from only the public key and a random challenge.