(backend, wycheproof)
| 191 | "mldsa_87_sign_seed_test.json", |
| 192 | ) |
| 193 | def test_mldsa_external_mu(backend, wycheproof): |
| 194 | # Only some sign vectors carry a precomputed mu ("External Mu"), so we |
| 195 | # filter out the ones that don't. The ones that do include the "Internal" |
| 196 | # cases that NIST provides as bare mu values with no message or context; |
| 197 | # those are skipped by the signing tests above (we don't expose |
| 198 | # Sign_internal) but exercise the precomputed-mu verification interface |
| 199 | # here. We only test cases with a valid signature -- rejection of bad |
| 200 | # signatures is covered by the verify tests. |
| 201 | if "mu" not in wycheproof.testcase or not wycheproof.valid: |
| 202 | return |
| 203 | |
| 204 | public_key_class = _MLDSA_PUBLIC_KEYS[wycheproof.testfiledata["algorithm"]] |
| 205 | pub_raw = binascii.unhexlify(wycheproof.testgroup["publicKey"]) |
| 206 | pub = public_key_class.from_public_bytes(pub_raw) |
| 207 | mu = binascii.unhexlify(wycheproof.testcase["mu"]) |
| 208 | sig = binascii.unhexlify(wycheproof.testcase["sig"]) |
| 209 | |
| 210 | # The signature verifies through the precomputed-mu interface. |
| 211 | pub.verify_mu(sig, mu) |
| 212 | # And must not verify against a different mu. |
| 213 | with pytest.raises(InvalidSignature): |
| 214 | pub.verify_mu(bytes(sig), bytes([mu[0] ^ 0x01]) + mu[1:]) |
| 215 | |
| 216 | # When the message (and optional context) are also provided, the mu we |
| 217 | # derive must match the one in the vector, and the signature is an |
| 218 | # ordinary ML-DSA signature over that message. |
| 219 | if "msg" in wycheproof.testcase: |
| 220 | msg = binascii.unhexlify(wycheproof.testcase["msg"]) |
| 221 | ctx = binascii.unhexlify(wycheproof.testcase.get("ctx", "")) |
| 222 | assert _compute_mu(pub_raw, msg, ctx) == mu |
| 223 | pub.verify(sig, msg, ctx) |
| 224 | |
| 225 | |
| 226 | @pytest.mark.supported( |
nothing calls this directly
no test coverage detected