{
	"version": "1.4.10",
	"models": [
		{
			"name": "first",
			"reason": "A substituted verification key accepts an attacker signature without revealing Alice's key.",
			"expected": {
				"1": "c0a1",
				"2": "c0a1"
			},
			"boxes": [
				"first.vp: A Signed Challenge"
			]
		},
		{
			"name": "first-guarded",
			"reason": "The trusted signing key and checked signature bind Bob's challenge to Alice.",
			"expected": {
				"1": "c0a0",
				"2": "c0a0"
			},
			"base": "first",
			"edits": [
				{
					"old": "Alice -> Bob: pk, proof",
					"new": "Alice -> Bob: [pk], proof",
					"count": 1
				}
			]
		},
		{
			"name": "first-unchecked",
			"reason": "Bob uses the delivered signature without requiring successful verification.",
			"expected": {
				"1": "c0a1",
				"2": "c0a1"
			},
			"base": "first-guarded",
			"edits": [
				{
					"old": "SIGNVERIF(pk, challenge, proof)?",
					"new": "SIGNVERIF(pk, challenge, proof)",
					"count": 1
				}
			]
		},
		{
			"name": "simple",
			"reason": "Unauthenticated Diffie-Hellman permits key substitution, disclosure and divergence.",
			"expected": {
				"1": "c1c1a1e1",
				"2": "c1c1a1e1"
			},
			"boxes": [
				"Simple Protocol",
				"Example: Queries"
			]
		},
		{
			"name": "simple-passive",
			"reason": "Only the transmitted ciphertext is public; a passive attacker cannot substitute the keys.",
			"expected": {
				"1": "c1c0a0e0",
				"2": "c1c0a0e0"
			},
			"base": "simple",
			"edits": [
				{
					"old": "attacker[active]",
					"new": "attacker[passive]",
					"count": 1
				}
			]
		},
		{
			"name": "freshness",
			"reason": "The used static hash is not fresh; the used generated-value hash is fresh.",
			"expected": {
				"1": "f1f0",
				"2": "f1f0"
			},
			"boxes": [
				"Example Freshness Query"
			]
		},
		{
			"name": "unlinkability",
			"reason": "The hidden seed stays unknown, while a leaked common origin and repeated public key link the other pairs.",
			"expected": {
				"1": "u0u1u1",
				"2": "u0u1u1"
			},
			"boxes": [
				"Example Unlinkability Query"
			]
		},
		{
			"name": "accepted-key",
			"reason": "A discarded key can be attacker-known; the precondition excludes a run that fails verification before sending.",
			"expected": {
				"1": "c1c0",
				"2": "c1c0"
			},
			"boxes": [
				"Secrecy of an Accepted Key"
			]
		},
		{
			"name": "challenge-response",
			"reason": "Unchecked verification permits replacement, and a second session permits replay of the independent attestation.",
			"expected": {
				"1": "a1a0",
				"2": "a1a1"
			},
			"boxes": [
				"Challenge-Response Protocol"
			]
		},
		{
			"name": "threshold",
			"reason": "Authenticated coordinator messages prevent collecting partials for an attacker-selected message.",
			"expected": {
				"1": "c0c0a0",
				"2": "c0c0a0"
			},
			"boxes": [
				"threshold.vp"
			]
		},
		{
			"name": "nonce-reuse",
			"reason": "The reused pair reveals its plaintexts, while the different-nonce plaintext remains protected.",
			"expected": {
				"1": "c1c1c0",
				"2": "c1c1c0"
			},
			"boxes": [
				"nonce-reuse.vp"
			]
		},
		{
			"name": "nonce-forgery",
			"reason": "Two distinct ciphertexts under one key and nonce permit a forged ciphertext.",
			"expected": {
				"1": "a1",
				"2": "a1"
			},
			"boxes": [
				"nonce-forgery.vp"
			]
		},
		{
			"name": "harvest",
			"reason": "Only the annotated ciphertext loses confidentiality in phase 2.",
			"expected": {
				"1": "c0c1",
				"2": "c0c1"
			},
			"boxes": [
				"harvest.vp"
			]
		},
		{
			"name": "precondition",
			"reason": "The second session supplies an accepted replay that still reaches the onward send.",
			"expected": {
				"1": "a0",
				"2": "a1"
			},
			"boxes": [
				"Query Options Example",
				"Query Options Example (Cont.)"
			]
		},
		{
			"name": "challenge-checked",
			"reason": "Checking a signature does not establish trust in an unguarded verification key.",
			"expected": {
				"1": "a1a0",
				"2": "a1a1"
			},
			"base": "challenge-response",
			"edits": [
				{
					"old": "SIGNVERIF(gs, nonce, proof)",
					"new": "SIGNVERIF(gs, nonce, proof)?",
					"count": 1
				}
			]
		},
		{
			"name": "challenge-guarded",
			"reason": "The challenge proof is protected, but the attestation can still be replayed to another server run.",
			"expected": {
				"1": "a0a0",
				"2": "a0a1"
			},
			"base": "challenge-checked",
			"edits": [
				{
					"old": "Server -> Client: gs, proof",
					"new": "Server -> Client: [gs], proof",
					"count": 1
				}
			]
		},
		{
			"name": "signal",
			"reason": "Authenticated identities and checked prekeys protect the three messages under later identity-key disclosure.",
			"expected": {
				"1": "c0a0c0a0c0a0",
				"2": "c0a0c0a0c0a0"
			},
			"boxes": [
				"Signal: Initializing Alice",
				"Signal: Initializing Bob",
				"Signal: Alice Initiates Session with Bob",
				"Signal: Alice Encrypts Message 1 to Bob",
				"Signal: Bob Derives Shared Master Secret",
				"Signal: Bob Decrypts Alice's Message 1",
				"Signal: Bob Encrypts Message 2 to Alice",
				"Signal: Alice Decrypts Message 2",
				"Signal: Alice Encrypts Message 3 to Bob",
				"Signal: Bob Decrypts Message 3",
				"Signal: Long-Term Private Key Leakage in Subsequent Phase",
				"Signal: Message Queries"
			]
		},
		{
			"name": "signal-unchecked",
			"reason": "A second run reaches shared identity-key leaks that disclose the first message of the attacked run.",
			"expected": {
				"1": "c0a0c0a0c0a0",
				"2": "c1a0c0a0c0a0"
			},
			"base": "signal",
			"edits": [
				{
					"old": "SIGNVERIF(gblongterm, gbs, gbssig)?",
					"new": "SIGNVERIF(gblongterm, gbs, gbssig)",
					"count": 1
				}
			]
		},
		{
			"name": "signal-unguarded",
			"reason": "Substituted Bob keys disclose Alice's first message and permit forging Bob's reply to obtain her third.",
			"expected": {
				"1": "c1a0c0a1c1a0",
				"2": "c1a0c0a1c1a0"
			},
			"base": "signal-unchecked",
			"edits": [
				{
					"old": "[gblongterm]",
					"new": "gblongterm",
					"count": 1
				}
			]
		},
		{
			"name": "scuttlebutt",
			"reason": "Two ciphertext-position substitutions break application authentication; two sessions also separate the named master secrets.",
			"expected": {
				"1": "c0c0c0c0a0a0a0a1a1e0",
				"2": "c0c0c0c0a0a0a0a1a1e1"
			},
			"boxes": [
				"Declaring New Principals: Alice and Bob",
				"Scuttlebutt: Alice and Bob Exchange Ephemeral Public Keys",
				"Scuttlebutt: Alice Generates Session Secrets",
				"Scuttlebutt: Bob Generates Session Secrets",
				"Scuttlebutt: Bob Signs Session Transcript",
				"Scuttlebutt: Alice Encrypts and Sends Message to Bob",
				"Scuttlebutt: Bob Receives and Decrypts Message from Alice",
				"Scuttlebutt: Bob Encrypts and Sends Message to Alice",
				"Scuttlebutt: Confidentiality, Authentication and Equivalence Queries"
			]
		},
		{
			"name": "scuttlebutt-unguarded",
			"reason": "The private network identifier still blocks an attacker-selected hello key.",
			"expected": {
				"1": "c0c0c0c0a0a0a0a1a1e0",
				"2": "c0c0c0c0a0a0a0a1a1e1"
			},
			"base": "scuttlebutt",
			"edits": [
				{
					"old": "[longTermBPub]",
					"new": "longTermBPub",
					"count": 1
				}
			]
		},
		{
			"name": "scuttlebutt-public",
			"reason": "A public network identifier permits a full forged exchange with Bob and disclosure of his reply.",
			"expected": {
				"1": "c1c0c1c0a1a1a0a1a1e1",
				"2": "c1c0c1c0a1a1a0a1a1e1"
			},
			"base": "scuttlebutt",
			"edits": [
				{
					"old": "knows private n\n",
					"new": "knows public n\n",
					"count": 2
				}
			]
		},
		{
			"name": "scuttlebutt-public-unguarded",
			"reason": "Removing Bob's key guard adds no failure to the public-identifier variant.",
			"expected": {
				"1": "c1c0c1c0a1a1a0a1a1e1",
				"2": "c1c0c1c0a1a1a0a1a1e1"
			},
			"base": "scuttlebutt-public",
			"edits": [
				{
					"old": "[longTermBPub]",
					"new": "longTermBPub",
					"count": 1
				}
			]
		},
		{
			"name": "scuttlebutt-leak",
			"reason": "The later identity-key leak additionally reveals Alice's public key but neither application plaintext.",
			"expected": {
				"1": "c0c0c0c1a0a0a0a1a1e0",
				"2": "c0c0c0c1a0a0a0a1a1e1"
			},
			"base": "scuttlebutt",
			"edits": [
				{
					"old": "queries[",
					"new": "phase[1]\nprincipal Alice[\n\tleaks longTermA\n]\n\nqueries[",
					"count": 1
				}
			]
		},
		{
			"name": "scuttlebutt-early-leak",
			"reason": "With a private network identifier, the earlier identity-key disclosure leaves the same verdicts.",
			"expected": {
				"1": "c0c0c0c1a0a0a0a1a1e0",
				"2": "c0c0c0c1a0a0a0a1a1e1"
			},
			"base": "scuttlebutt-leak",
			"edits": [
				{
					"old": "phase[1]",
					"new": "",
					"count": 1
				}
			]
		},
		{
			"name": "pqxdh",
			"reason": "A cross-role key substitution exposes the hybrid secret when another run reaches the shared classical-key leak.",
			"expected": {
				"1": "c0a0",
				"2": "c1a0"
			},
			"boxes": [
				"PQXDH: Alice's Identity",
				"PQXDH: Bob Publishes His Pre-Keys",
				"PQXDH: Alice Initiates",
				"PQXDH: Bob Responds",
				"Leaking Every Diffie--Hellman Private Value",
				"PQXDH: Queries"
			]
		},
		{
			"name": "pqxdh-separated",
			"reason": "Distinct signed key-role tags prevent the classical key from replacing the KEM key.",
			"expected": {
				"1": "c0a0",
				"2": "c0a0"
			},
			"base": "pqxdh",
			"edits": [
				{
					"old": "knows public info",
					"new": "knows public info, ec_tag, kem_tag",
					"count": 1
				},
				{
					"old": "SIGN(blongterm, gbs)",
					"new": "SIGN(blongterm, CONCAT(ec_tag, gbs))",
					"count": 1
				},
				{
					"old": "SIGN(blongterm, ekb)",
					"new": "SIGN(blongterm, CONCAT(kem_tag, ekb))",
					"count": 1
				},
				{
					"old": "SIGNVERIF(gblongterm, gbs, gbssig)",
					"new": "SIGNVERIF(gblongterm, CONCAT(ec_tag, gbs), gbssig)",
					"count": 1
				},
				{
					"old": "SIGNVERIF(gblongterm, ekb, ekbsig)",
					"new": "SIGNVERIF(gblongterm, CONCAT(kem_tag, ekb), ekbsig)",
					"count": 1
				}
			]
		},
		{
			"name": "x3dh-future",
			"reason": "Later classical-key disclosure reconstructs the recorded message key without changing the earlier delivery.",
			"expected": {
				"1": "c1a0",
				"2": "c1a0"
			},
			"base": "pqxdh-separated",
			"edits": [
				{
					"old": ", dkb",
					"new": "",
					"count": 1
				},
				{
					"old": "ekb = PUBKEY(dkb)",
					"new": "",
					"count": 1
				},
				{
					"old": "ekbsig = SIGN(blongterm, CONCAT(kem_tag, ekb))",
					"new": "",
					"count": 1
				},
				{
					"old": ", ekb, ekbsig",
					"new": "",
					"count": 1
				},
				{
					"old": "kvalid = SIGNVERIF(gblongterm, CONCAT(kem_tag, ekb), ekbsig)?",
					"new": "",
					"count": 1
				},
				{
					"old": "ss, ct = KEM_ENCAP(ekb, r)",
					"new": "",
					"count": 1
				},
				{
					"old": ", ss)",
					"new": ")",
					"count": 1
				},
				{
					"old": ", bss)",
					"new": ")",
					"count": 1
				},
				{
					"old": ", ct,",
					"new": ",",
					"count": 1
				},
				{
					"old": "bss = KEM_DECAP(dkb, ct)",
					"new": "",
					"count": 1
				}
			]
		},
		{
			"name": "pqxdh-weak",
			"reason": "The phase-scoped public-key weakening reproduces the corresponding classical-key leak experiment.",
			"expected": {
				"1": "c0a0",
				"2": "c0a0"
			},
			"base": "pqxdh-separated",
			"edits": [
				{
					"old": "principal Alice[leaks alongterm, ae1]\nprincipal Bob[leaks blongterm, bs, bo]",
					"new": "",
					"count": 1
				},
				{
					"old": "PUBKEY(alongterm)",
					"new": "PUBKEY[weak from phase 1](alongterm)",
					"count": 1
				},
				{
					"old": "PUBKEY(blongterm)",
					"new": "PUBKEY[weak from phase 1](blongterm)",
					"count": 1
				},
				{
					"old": "PUBKEY(bs)",
					"new": "PUBKEY[weak from phase 1](bs)",
					"count": 1
				},
				{
					"old": "PUBKEY(bo)",
					"new": "PUBKEY[weak from phase 1](bo)",
					"count": 1
				},
				{
					"old": "PUBKEY(ae1)",
					"new": "PUBKEY[weak from phase 1](ae1)",
					"count": 1
				}
			]
		},
		{
			"name": "x3dh-weak",
			"reason": "The phase-scoped public-key weakening reproduces the corresponding classical-key leak experiment.",
			"expected": {
				"1": "c1a0",
				"2": "c1a0"
			},
			"base": "x3dh-future",
			"edits": [
				{
					"old": "principal Alice[leaks alongterm, ae1]\nprincipal Bob[leaks blongterm, bs, bo]",
					"new": "",
					"count": 1
				},
				{
					"old": "PUBKEY(alongterm)",
					"new": "PUBKEY[weak from phase 1](alongterm)",
					"count": 1
				},
				{
					"old": "PUBKEY(blongterm)",
					"new": "PUBKEY[weak from phase 1](blongterm)",
					"count": 1
				},
				{
					"old": "PUBKEY(bs)",
					"new": "PUBKEY[weak from phase 1](bs)",
					"count": 1
				},
				{
					"old": "PUBKEY(bo)",
					"new": "PUBKEY[weak from phase 1](bo)",
					"count": 1
				},
				{
					"old": "PUBKEY(ae1)",
					"new": "PUBKEY[weak from phase 1](ae1)",
					"count": 1
				}
			]
		},
		{
			"name": "pqxdh-kem-leak",
			"reason": "The undisclosed Diffie-Hellman component protects the message after KEM-key disclosure.",
			"expected": {
				"1": "c0a0",
				"2": "c0a0"
			},
			"base": "pqxdh-separated",
			"edits": [
				{
					"old": "principal Alice[leaks alongterm, ae1]\nprincipal Bob[leaks blongterm, bs, bo]",
					"new": "principal Bob[leaks dkb]",
					"count": 1
				}
			]
		},
		{
			"name": "pqxdh-both-leak",
			"reason": "Disclosing both components reveals the recorded message but cannot forge the earlier delivery.",
			"expected": {
				"1": "c1a0",
				"2": "c1a0"
			},
			"base": "pqxdh-separated",
			"edits": [
				{
					"old": "principal Alice[leaks alongterm, ae1]\nprincipal Bob[leaks blongterm, bs, bo]",
					"new": "principal Alice[leaks alongterm, ae1]\nprincipal Bob[leaks blongterm, bs, bo]\nprincipal Bob[leaks dkb]",
					"count": 1
				}
			]
		},
		{
			"name": "scenarios",
			"standalone": true,
			"expected": {
				"1": "c1a1a0",
				"2": "c1a1a0"
			},
			"reason": "Lowe's attack spans an honest and a corrupt peer configuration."
		}
	]
}
