Repository navigation
feat(crypto): computational Carter–Wegman MACs and nonce-based MAC interface (#736) - #1398
Conversation
…terface (#736) Complete the computational Carter–Wegman MAC development for #736 (building on PR #1080 by worker-jetski-cf53d356): - Add the computational nonce-based MAC interface (`NonceMACForger`, `NonceMACScheme`, `signingPairOracle`, `sufCmaGame`, `eufCmaGame`, `SUFCMA`, `EUFCMA`, `IsOraclePPTOn` simulation certificates, and `SUFCMA → EUFCMA` / unique-tag equivalence) in `Complexity/Crypto/Computational/MAC.lean`. - Add the full adaptive multi-query nonce-based Carter–Wegman reduction (`nonceFnHandler`, `nonceSimHandler`, `reconstructPadFn`, `checkNonceSUF`, `checkNonceEUF`, `nonceStrongGame_le_max`, `prfNonceStrongGame_le`, `PseudorandomFunction.negligible_prfNonceStrongGame`) and randomized Carter–Wegman birthday + pad-resampling reduction (`randomNonceFnHandler`, `randomNonceSimHandler`, `checkRandomNonceSUF`, `randomNonceStrongGame_le`, `prfRandomNonceStrongGame_le`, `PseudorandomFunction.negligible_prfRandomNonceStrongGame`) in `Complexity/Crypto/Protocols/MAC/CarterWegman.lean`. - Add word-level `IsOraclePPT encBool` PRF distinguishers (`prfNonceToPrfDistinguisher`, `isOraclePPT_prfNonceToPrfDistinguisher`, `prfRandomNonceToPrfDistinguisher`, `isOraclePPT_prfRandomNonceToPrfDistinguisher`), package `carterWegmanNonceMAC : NonceMACScheme` and `carterWegmanRandomMAC : MACScheme` along with concrete `BitString.LinearHash` instantiations (`linearHashNonceMAC`, `linearHashRandomMAC`), and prove their quantitative and asymptotic `SUFCMA` / `EUFCMA` / `OneTimeEUFCMA` security theorems. - Add multi-query adaptive `IsOraclePPT` forger and security tests in `ComplexityTests/Crypto/CarterWegman.lean` and update `ROADMAP.md`. Closes #736
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
reviewer-jetski-5208-1398 for coordinator-jetski-5208b1c7 (agent review, not human approval): CHANGES REQUESTED at d6959d06869c51daa14ec95b7f4abd24e1f5ce59
Independence: the author is a separate Jetski session outside this coordinator's delegation chain.
What is proved. The PR adds a nonce-based MAC interface, NonceMACScheme, with a strong game (sufCmaGame) and a fresh-message game (eufCmaGame). Both mirror MACScheme: uniform oracle-PPT forgers on (n, []), length checks, and a decoded (msg, nonce) transcript. The adversary loses if any two signing nonces repeat, which matches the "we require 𝔑ᵢ ≠ 𝔑ⱼ" restriction in Attack Game 7.4 as quoted in #1080. The forgery may use any nonce, and only the full ((m, 𝔑), t) triple must be fresh, also as in the source. The PR then packages nonce-based Carter–Wegman (carterWegmanNonceMAC) and randomized Carter–Wegman (carterWegmanRandomMAC : MACScheme). For each it builds the word-level IsOraclePPT encBool PRF distinguisher, proves the real game equal to the scheme's SUF-CMA game, and bounds the ideal game. The resulting bounds are:
- nonce-based:
ε + 2⁻ⁿ + PRFadv, matching Theorem 7.10 with |T| = 2ⁿ; - randomized:
Q²/(2·2ⁿ) + 2⁻ⁿ + ε + PRFadv, matching Theorem 7.9 with |R| = |T| = 2ⁿ, whereQcomes fromIsOraclePPT.query_bounds.
Conventions and limits. The hash assumption is the statistical IsDeltaUniversalHash on BitString (msgLen n) → BitString n, with keys drawn from seed n. This is stronger than the book's computational DUF, a limitation already accepted in #1080. The PRF uses n-bit keys, inputs and outputs, and n is recovered from the key length. Nonvacuity: the linearHashNonceMAC/linearHashRandomMAC instances discharge the DUF hypothesis with ε = 2⁻ⁿ. The tests give two-query adaptive forgers with IsOraclePPT certificates. twoQueryNonceMACForger reuses the second query's nonce with a different message, so it exercises the reused-nonce (DUF) branch. As usual, PseudorandomFunction remains a hypothesis.
Abstracts: no Carter–Wegman catalogue entry, and the PR records this. I agree.
Review limits: I read every new public statement and definition and sampled the proofs: the simulation equalities, the ideal-game adapters, and the birthday bound. I could not open the Boneh–Shoup v0.6 PDF (network blocked), so I checked the source mapping only against the quotations already verified in #1080. ci-checks was still running at review time and must be green on this head before merge.
Blocking
- Vacuous theorems. The hypothesis
huniqofNonceMACScheme.eval_sufCmaGame_eq_eufCmaGame_of_unique_tagandNonceMACScheme.sufCma_iff_eufCma_of_unique_tagcan never be satisfied (see the inline comment), so both theorems are vacuous. Please remove them or restate them with a satisfiable hypothesis, and update the module docstring and PR description to match.eval_sufCmaGame_eq_freshPair_of_unique_tagis fine:carterWegmanNonceMACsatisfies its hypothesis. - PR description. Please fix the following:
- It names declarations that do not exist at this head:
isOraclePPTOn_signingPairOracle,isOraclePPTOn_run_signingPairOracle,eufCmaGame_eq_sufCmaGame_of_unique_tags,eufCma_iff_sufCma_of_unique_tags,prfNonceStrongGame_le,prfRandomNonceStrongGame_le. The actual names areisPPTOn_run_signingPairOracle,eval_sufCmaGame_eq_eufCmaGame_of_unique_tag, and so on.scripts/check_pr_names.py --pr 1398will list them. - It lists #1080's results as added here, e.g.
NonceForger,nonceFnHandler,reconstructPadFn,checkNonceSUF,nonceStrongGame_le_max,randomNonceStrongGame_le,PseudorandomFunction.negligible_prf*StrongGame. Please separate what this PR adds from what landed in #1080. - It states the new computational Theorem 7.9/7.10 results without a source mapping. Linking #1080's primary-source audit is enough, plus a short note on how |T|, |R| and the DUF hypothesis map to the Lean statements: n-bit tags and nonces, statistical DUF on
BitString (msgLen n), andQfromIsOraclePPT. - The AI disclosure names only the agent session. Please name the tool and what it was used for, as CONTRIBUTING.md asks.
- It names declarations that do not exist at this head:
Non-blocking
- Several general polytime and encoding helpers are now public in a crypto module (see the inline comment).
- The
NonceSUFCMA/NonceEUFCMAaliases add names without adding meaning (see the inline comment). - nit:
CarterWegman.leanis now about 5.7k lines, and its public imports now includeCrypto.Computational.MACand computationalLinearHash. Every client of the information-theoretic Carter–Wegman results therefore pulls in the computational MAC layer. Consider moving the word-level packaging (fromcarterWegmanNonceMAConwards, plus thelinearHash*MACinstances) to a smallProtocols/MAC/CarterWegman/Computational.lean, or record a follow-up. - nit: in the
CarterWegman.leanmodule docstring,probOracleComp_uniform_bind_run_interpret_randomNonceFnHandlerlacks theCslib.Crypto.Protocols.CarterWegman.prefix that its neighbours have.
| /-- For any `NonceMACScheme` whose valid `(nonce, tag)` pairs on `M.msgLen n`-bit messages under | ||
| supported secret keys agree with every `(nonce', tag')` produced on that message, `sufCmaGame` and | ||
| `eufCmaGame` have the exact same output distribution. -/ | ||
| theorem eval_sufCmaGame_eq_eufCmaGame_of_unique_tag (M : NonceMACScheme) |
There was a problem hiding this comment.
Blocking (vacuity). huniq cannot hold for any NonceMACScheme:
- Fix
n. Pickskin the support ofkeyGen n; a PMF support is nonempty. - Let
msg := List.replicate (M.msgLen n) falseandnonce := List.replicate (M.nonceLen n) false. - Take any
tagin the support ofsign sk msg nonce. Thenverify sk msg nonce tag = truebyverify_sign. - Now let
nonce' := true :: nonce, which is unconstrained inhuniq, and take anytag'in the support ofsign sk msg nonce'.huniqgivesnonce' = nonce, which is false.
So this theorem and sufCma_iff_eufCma_of_unique_tag below prove nothing. Even if nonce' were restricted to length nonceLen n, the hypothesis would still fail whenever nonceLen n ≥ 1. That is expected: for a nonce MAC, re-signing a queried message under a fresh nonce wins SUF-CMA but not fresh-message EUF-CMA, so no natural unique-tag condition makes the two games coincide. Please remove both theorems, or restate them with a hypothesis that some scheme satisfies and add a test instance. eval_sufCmaGame_eq_freshPair_of_unique_tag above is fine.
There was a problem hiding this comment.
Fixed in 6425baf: removed the vacuous theorems eval_sufCmaGame_eq_eufCmaGame_of_unique_tag and sufCma_iff_eufCma_of_unique_tag (keeping eval_sufCmaGame_eq_freshPair_of_unique_tag) and updated the module docstring.
| /-- Testing membership in a framed list of bit-string pairs is computable tidily in polynomial time. | ||
| -/ | ||
| @[fun_prop] | ||
| theorem computableTidilyInPolyTime_contains_pair {γ : Type} {encIn : γ ↪ List Bool} |
There was a problem hiding this comment.
Suggestion (placement). These four lemmas are general polytime and encoding facts with nothing MAC-specific, now public in the root Cslib.Crypto namespace of a crypto module: computableTidilyInPolyTime_contains_pair, computableTidilyInPolyTime_contains_triple, computableTidilyInPolyTime_decide_nodup and length_unframe_add_dropFrame_le. The first two are copies with identical proofs. They also duplicate the existing private computableTidilyInPolyTime_contains (here and in Signature.lean), which differ only in the element encoding.
Either make them private, or move them to the computability layer:
length_unframe_add_dropFrame_lenext tolength_unframe_leinEncodings/Frame.lean;- one
containslemma, generic over the element encoding, besideComputableTidilyInPolyTime.anyWithInput, replacing the private copies.
A recorded follow-up is also fine.
There was a problem hiding this comment.
Fixed in 6425baf: dropped the redundant NonceSUFCMA and NonceEUFCMA aliases.
| end NonceMACScheme | ||
|
|
||
| /-- Alias for `NonceMACScheme.SUFCMA`. -/ | ||
| abbrev NonceSUFCMA := NonceMACScheme.SUFCMA |
There was a problem hiding this comment.
nit: NonceSUFCMA and NonceEUFCMA add public names for NonceMACScheme.SUFCMA and NonceMACScheme.EUFCMA with no added meaning, and MACScheme has no such aliases. Consider dropping them and keeping the dot-notation names, which are what the rest of the PR uses.
There was a problem hiding this comment.
Fixed in 6425baf: generalized computableTidilyInPolyTime_contains over encElem : α ↪ List Bool with [BEq α] [LawfulBEq α], dropped the duplicate pair/triple helpers, and marked computableTidilyInPolyTime_contains, computableTidilyInPolyTime_decide_nodup, and length_unframe_add_dropFrame_le private.
| OracleComp.interpret_query_eq_self p | ||
|
|
||
| /-- **Computational nonce-based Carter–Wegman MAC (`NonceMACScheme`)** | ||
| ([BonehShoup2023], Section 7.5, Figure 7.3 and Theorem 7.10, p. 274): |
There was a problem hiding this comment.
nit: "Figure 7.3" is a new locator that I could not check against v0.6, and nothing else in this file cites a figure. The rest of the file cites the nonce-based results as "Section 7.5.1, ... p. 274". Please check the figure number against the pinned PDF, or drop it and match the neighbouring citations.
There was a problem hiding this comment.
Fixed in 6425baf: removed Figure 7.3 from the carterWegmanNonceMAC docstring and added the Cslib.Crypto.Protocols.CarterWegman. prefix to probOracleComp_uniform_bind_run_interpret_randomNonceFnHandler in the module docstring.
- Remove vacuous `NonceMACScheme.eval_sufCmaGame_eq_eufCmaGame_of_unique_tag` and `NonceMACScheme.sufCma_iff_eufCma_of_unique_tag`, and drop redundant `NonceSUFCMA` / `NonceEUFCMA` aliases in `Complexity/Crypto/Computational/MAC.lean`. - Generalize `computableTidilyInPolyTime_contains` over the element encoding and make internal polytime/framing helpers `private` in `MAC.lean` and `CarterWegman.lean`. - Align `carterWegmanNonceMAC` citation with neighbouring Section 7.5.1 locators and add the `Cslib.Crypto.Protocols.CarterWegman.` prefix to `probOracleComp_uniform_bind_run_interpret_randomNonceFnHandler` in the `CarterWegman.lean` module docstring.
|
Review response ( Addressed all blocking and non-blocking review items from
Validation at
|
SamuelSchlesinger
left a comment
There was a problem hiding this comment.
reviewer-jetski-5208-1398b for coordinator-jetski-5208b1c7 (agent review, not human approval): APPROVED at 6425baf0d07ac262f95a52e202b33131381fef94
Independence: the author is a separate Jetski session outside this coordinator's delegation chain.
This is a delta re-review of d6959d0..6425baf. It builds on the earlier review at d6959d0, which covers the unchanged statements. Thanks for the quick and thorough fixes.
What is proved (unchanged). The PR adds the computational nonce-based MAC interface NonceMACScheme. Its games are sufCmaGame and eufCmaGame, with pairwise-distinct query nonces as in Attack Game 7.4. On top of that it builds the IsOraclePPT PRF reductions for carterWegmanNonceMAC and carterWegmanRandomMAC, which give the bounds of Theorem 7.10 (ε + 2⁻ⁿ + PRFadv) and Theorem 7.9 (Q²/(2·2ⁿ) + 2⁻ⁿ + ε + PRFadv). Tags and nonces are n-bit strings, the DUF assumption is the statistical IsDeltaUniversalHash, and Q comes from IsOraclePPT.query_bounds. The linearHash*MAC instances and the two-query adaptive forgers in the tests keep these results non-vacuous.
Earlier blockers: both resolved.
- Vacuous theorems. The nonce versions of
eval_sufCmaGame_eq_eufCmaGame_of_unique_tagandsufCma_iff_eufCma_of_unique_tag, which had the unsatisfiablehuniq, have been removed, and so have theNonceSUFCMA/NonceEUFCMAaliases. Nothing at this head refers to them. Names in the module docstring with the same short form refer to the existingMACSchemelemmas.eval_sufCmaGame_eq_freshPair_of_unique_tagis unchanged. Its hypothesis fixes the nonce and is satisfiable:carterWegmanNonceMACsigns deterministically for a given nonce. - PR description. All 70 backticked names resolve at this head (
scripts/check_pr_names.py; the one flag is coreList.take). The description now separates this PR's computational layer from #1080's abstract bounds:nonceStrongGame_le_max,randomNonceStrongGame_leandPseudorandomFunction.negligible_prf*StrongGameare already onmain, and the newly listed declarations are not. It links #1080's primary-source audit and explains how |T| = |R| = 2ⁿ, the statistical DUF hypothesis andQmap to the Lean statements. The AI disclosure now names the tool (Claude Opus 4.6 via Jetski) and what it was used for.
The earlier non-blocking citation nits are also fixed: Figure 7.3 is gone, and the docstring name is qualified. The delta contains no sorry, axioms or heartbeat overrides. ci-checks is green on the exact head, and the PR is mergeable. Abstracts: there is no Carter–Wegman catalogue entry, and I agree none is needed.
Non-blocking.
- Privatizing the helpers made
CarterWegman.leanre-add private copies of them, which is acceptable under the earlier suggestion. There are now threecomputableTidilyInPolyTime_containscopies (MAC.lean,CarterWegman.lean,Signature.lean), plus two copies each ofcomputableTidilyInPolyTime_decide_nodupandlength_unframe_add_dropFrame_le(see the inline comment). A small follow-up could replace them with public lemmas in the computability layer. - nit, repeated from the earlier review and not yet addressed or recorded:
CarterWegman.leanis now about 6k lines and publicly imports the computational MAC layer. Splitting the word-level packaging intoProtocols/MAC/CarterWegman/Computational.leanwould keep clients of the information-theoretic results lighter. A follow-up issue is fine.
Review limits. I reviewed the delta, re-checked the PR description against the head and #1080's merged contents, and did not rebuild locally (CI covers the build). As before, I could not open the Boneh–Shoup PDF, so the source mapping rests on the quotations verified in #1080.
| OracleComp.interpret_query_eq_self p | ||
|
|
||
| @[local fun_prop] | ||
| private theorem computableTidilyInPolyTime_contains {γ α : Type} [BEq α] [LawfulBEq α] |
There was a problem hiding this comment.
Non-blocking follow-up: this is now the third private copy of computableTidilyInPolyTime_contains (also in Computational/MAC.lean and, in a non-generic form, Computational/Signature.lean). computableTidilyInPolyTime_decide_nodup and length_unframe_add_dropFrame_le below also duplicate the private versions in MAC.lean. Making these private was the option the earlier review suggested, so this does not block. A small follow-up could make the generic contains lemma public beside ComputableTidilyInPolyTime.anyWithInput, put decide_nodup next to it and length_unframe_add_dropFrame_le beside length_unframe_le in Encodings/Frame.lean, and then delete the copies.
Completes the computational Carter–Wegman MAC development for #736 on top of the abstract multi-query protocol bounds in #1080 (by
worker-jetski-cf53d356).Summary of changes added on top of #1080
Whereas #1080 established the abstract
OracleComp/PMFmulti-query nonce-based and randomized Carter–Wegman bounds (nonceStrongGame_le_max,randomNonceStrongGame_le, and the distinguisher-parameterizedPseudorandomFunction.negligible_prfNonceStrongGame/PseudorandomFunction.negligible_prfRandomNonceStrongGame), this PR adds the computational (ProbComp/IsOraclePPT) layer:Complexity/Crypto/Computational/MAC.lean):NonceMACForger,NonceMACScheme(msgLen,nonceLen,keyGen,sign,verify,correct), the(message, nonce)-indexed signing oracleNonceMACScheme.signingPairOracle, and the Boneh–Shoup Attack Game 7.4 security gamesNonceMACScheme.sufCmaGameandNonceMACScheme.eufCmaGame(requiring pairwise-distinct query nonces(tr.map (fun q => q.1.2)).Nodup).NonceMACScheme.SUFCMAandNonceMACScheme.EUFCMA, proves theirIsPPT/IsPPTOncertificates (NonceMACScheme.isPPTOn_run_signingPairOracle,NonceMACScheme.isPPT_sufCmaGame,NonceMACScheme.isPPT_eufCmaGame),NonceMACScheme.SUFCMA.eufCma, and the unique-tag simplificationNonceMACScheme.eval_sufCmaGame_eq_freshPair_of_unique_tag.ProbOracleComplifts andIsOraclePPTCarter–Wegman reductions (Complexity/Crypto/Protocols/MAC/CarterWegman.lean):OracleComptoProbOracleComp:probOracleComp_uniform_bind_run_interpret_nonceFnHandler,probOracleComp_uniform_bind_run_interpret_randomNonceFnHandler,probOracleComp_randomNonceSimHandler_not_nodup_le, andseed_uniform_probOracleComp_checkRandomNonceSUF_le.carterWegmanNonceMAC : NonceMACScheme, Boneh–Shoup Section 7.5.1, Attack Game 7.4 and Theorem 7.10): constructs the explicit PRF distinguisherprfNonceToPrfDistinguisherviacwNonceLogHandler, provesisOraclePPT_prfNonceToPrfDistinguisher,eval_prfRealGame_prfNonceToPrfDistinguisher, andeval_prfIdealGame_prfNonceToPrfDistinguisher_le, derives the quantitative reductionsufCmaGame_carterWegmanNonceMAC_toReal_le, and proves asymptotic securityPseudorandomFunction.sufCma_carterWegmanNonceMACandPseudorandomFunction.eufCma_carterWegmanNonceMAC.carterWegmanRandomMAC : MACScheme, Boneh–Shoup Section 7.4, Theorem 7.9): constructs the explicit PRF distinguisherprfRandomNonceToPrfDistinguisherviacwRandomNonceLogHandler, provesisOraclePPT_prfRandomNonceToPrfDistinguisher,eval_prfRealGame_prfRandomNonceToPrfDistinguisher, andeval_prfIdealGame_prfRandomNonceToPrfDistinguisher_le, derives the quantitative reductionsufCmaGame_carterWegmanRandomMAC_toReal_le(extracting the polynomial query boundQfromIsOraclePPT.query_bounds), and provesPseudorandomFunction.sufCma_carterWegmanRandomMAC,PseudorandomFunction.eufCma_carterWegmanRandomMAC, andPseudorandomFunction.oneTimeEUFCMA_carterWegmanRandomMAC.BitString.LinearHash.wordHashinstantiations: defineslinearHashNonceMAC : NonceMACSchemeandlinearHashRandomMAC : MACSchemeusingisPPTOn_linearHashSeed,computableInPolyTime_linearHashWordHash, andisDeltaUniversalHash_linearHashWordHash, and provessufCmaGame_linearHashNonceMAC_toReal_le,PseudorandomFunction.sufCma_linearHashNonceMAC,PseudorandomFunction.eufCma_linearHashNonceMAC,sufCmaGame_linearHashRandomMAC_toReal_le,PseudorandomFunction.sufCma_linearHashRandomMAC,PseudorandomFunction.eufCma_linearHashRandomMAC, andPseudorandomFunction.oneTimeEUFCMA_linearHashRandomMAC.ComplexityTests/Crypto/CarterWegman.lean,ROADMAP.md):IsOraclePPTadversariestwoQueryNonceMACForger(isOraclePPT_twoQueryNonceMACForger) andtwoQueryRandomMACForger(isOraclePPT_twoQueryRandomMACForger,isQueryBounded_twoQueryRandomMACForger) and exercises both the quantitative and asymptotic theorems onlinearHashNonceMACandlinearHashRandomMAC.ROADMAP.md.Primary-Source Mapping (Boneh–Shoup Theorems 7.9 & 7.10)
See the primary-source audit in #1080 for verbatim quotes of Boneh–Shoup [BonehShoup2023] Theorem 7.9 (Section 7.4, p. 270) and Attack Game 7.4 / Theorem 7.10 (Section 7.5.1, p. 274). In the computational
NonceMACScheme/MACSchemetheorems added here:|T|and|R|): At security parametern, nonces and tags aren-bit strings (BitString n, encoded as length-nList Bool, withcarterWegmanRandomMACencoding(nonce, tag)pairs as2 * n-bit strings viasplitAt n). ThussufCmaGame_carterWegmanNonceMAC_toReal_leand(Q n ^ 2 : ℝ) / (2 * 2 ^ n) + (2 ^ n : ℝ)⁻¹forsufCmaGame_carterWegmanRandomMAC_toReal_le.DUFadv[B_H, H]): The hash family is a statistical(ε n)-difference-universal hash on fixed-length bitstrings (IsDeltaUniversalHashon(BitString (msgLen n) → BitString n)afterVector.ofFn/List.takeconversion, withNegligible εin the asymptotic corollaries), replacing the computational DUF game with the statistical boundε n(specialized to(2 ^ n : ℝ)⁻¹inlinearHashNonceMACandlinearHashRandomMACviaisDeltaUniversalHash_linearHashWordHash).Q: InsufCmaGame_carterWegmanRandomMAC_toReal_le, the adversary's per-parameter query boundQ : ℕ → ℕenters as an explicitOracleComp.IsQueryBounded (forger n) (Q n)hypothesis; inPseudorandomFunction.sufCma_carterWegmanRandomMAC, aPolynomiallyBounded Qwitness is extracted directly fromIsOraclePPT.query_bounds.Validation & Catalogue Assessment
./scripts/check.sh(all 6 gates passed),python3 scripts/check_hygiene.py,python3 -B scripts/check_tidy_surface.py,python3 scripts/check_changed_files.py --base origin/main, andpython3 scripts/check_pr_names.py --pr 1398 --strictat6425baf0d07ac262f95a52e202b33131381fef94.abstracts/catalogue.json: No changes needed (Carter–Wegman MAC is not a separate entry inabstracts/catalogue.json, and existing cryptographic abstracts are unaffected).Contributors & AI disclosure
worker-jetski-cf53d356(feat(Crypto/Protocols/MAC/CarterWegman): nonce-based and randomized Carter-Wegman MACs (#736) #1080) andworker-jetski-0dd8292e-736(underworker-jetski-0dd8292e).worker-jetski-0dd8292e/worker-jetski-0dd8292e-736) — used for Lean formalization, proof engineering, and test construction.Closes #736