Polynomial-time Adversaries

# Definition 1: Polynomial-time adversaries In cryptography, an **adversary** is an algorithm that tries to break a security property — for instance, inverting a one-way function. We model adversaries as functions `BitString → PMF BitString`: given a challenge, they return a probability distribution over responses. The predicate `PolyTimeAdversary F` asserts that `F` runs in polynomial time. It is defined inductively with two constructors: **`ofDet`** — the base case. Any `PolyTimeComputable` function `f : BitString → BitString` gives a poly-time adversary by returning `pure (f x)` (a point mass at the deterministic output). This covers all adversaries that make no random choices. **`uniformPad`** — models the standard reduction technique where an adversary needs fresh random coins but only receives a deterministic query. Given a `PolyTimeAdversary` `F` and a padding length `k`, the new adversary on input `y`: 1. samples `a ←$ {0,1}^k` (fresh uniform random bits) 2. runs `F` on `a ++ y` (the padded input) 3. strips the first `k` bits of the output and returns the rest The point is that `F` sees a uniformly random prefix on top of its real input, which is exactly the structure used in reductions like [`buildAdv`](QuadraticOWF.html#definition-2 "Quadratic-time one-way functions, Definition 2") in the quadratic OWF construction.
/-- A polynomial-time adversary: a poly-time algorithm (possibly randomized via
    uniform sampling) producing a distribution over bit strings. -/
inductive PolyTimeAdversary : (BitString → PMF BitString) → Prop where
  /-- A deterministic poly-time function, lifted to a distribution via `pure`. -/
  | ofDet {f} : PolyTimeComputable f →
      PolyTimeAdversary (fun x => PMF.pure (f x))
  /-- Prepend `k` fresh uniform random bits to the input, run `F`, then strip
      the prefix. Models reductions that supply random coins to a sub-adversary. -/
  | uniformPad (k : ℕ) {F} : PolyTimeAdversary F →
      PolyTimeAdversary (fun y => do
        let a ← uniformBitStringOfLength k
        let z ← F (a ++ y)
        return List.drop k z)
  /-- Prepend a *fixed* bit string to the input, run `F`, then strip `k` bits.
      Models reductions that use a fixed index or constant prefix. -/
  | fixedPad (pfx : BitString) (k : ℕ) {F} : PolyTimeAdversary F →
      PolyTimeAdversary (fun y => (F (pfx ++ y)).map (·.drop k))

Referenced by

Raw source
import Onewayf.PolyTime
import Onewayf.Bitstrings

-- leandown
-- [meta]
-- title = "Polynomial-time adversaries"
-- group = "Cryptography"
-- [content]

-- # {{definition}}: Polynomial-time adversaries
--
-- In cryptography, an **adversary** is an algorithm that tries to break a
-- security property — for instance, inverting a one-way function. We model
-- adversaries as functions `BitString → PMF BitString`: given a challenge,
-- they return a probability distribution over responses.
--
-- The predicate `PolyTimeAdversary F` asserts that `F` runs in polynomial time.
-- It is defined inductively with two constructors:
--
-- **`ofDet`** — the base case. Any `PolyTimeComputable` function
-- `f : BitString → BitString` gives a poly-time adversary by returning
-- `pure (f x)` (a point mass at the deterministic output). This covers all
-- adversaries that make no random choices.
--
-- **`uniformPad`** — models the standard reduction technique where an adversary
-- needs fresh random coins but only receives a deterministic query. Given a
-- `PolyTimeAdversary` `F` and a padding length `k`, the new adversary on input
-- `y`:
-- 1. samples `a ←$ {0,1}^k` (fresh uniform random bits)
-- 2. runs `F` on `a ++ y` (the padded input)
-- 3. strips the first `k` bits of the output and returns the rest
--
-- The point is that `F` sees a uniformly random prefix on top of its real
-- input, which is exactly the structure used in reductions like `buildAdv`
-- in the quadratic OWF construction.
--
/-- A polynomial-time adversary: a poly-time algorithm (possibly randomized via
    uniform sampling) producing a distribution over bit strings. -/
inductive PolyTimeAdversary : (BitString → PMF BitString) → Prop where
  /-- A deterministic poly-time function, lifted to a distribution via `pure`. -/
  | ofDet {f} : PolyTimeComputable f →
      PolyTimeAdversary (fun x => PMF.pure (f x))
  /-- Prepend `k` fresh uniform random bits to the input, run `F`, then strip
      the prefix. Models reductions that supply random coins to a sub-adversary. -/
  | uniformPad (k : ℕ) {F} : PolyTimeAdversary F →
      PolyTimeAdversary (fun y => do
        let a ← uniformBitStringOfLength k
        let z ← F (a ++ y)
        return List.drop k z)
  /-- Prepend a *fixed* bit string to the input, run `F`, then strip `k` bits.
      Models reductions that use a fixed index or constant prefix. -/
  | fixedPad (pfx : BitString) (k : ℕ) {F} : PolyTimeAdversary F →
      PolyTimeAdversary (fun y => (F (pfx ++ y)).map (·.drop k))