1. Introduction
IoT deployments increasingly collect environmental, industrial, health, mobility, and smart-city measurements through heterogeneous sensors and edge gateways. These data streams are valuable precisely because they can be shared across organizations, but they are also sensitive: a sensor reading can reveal location, equipment state, user behavior, or operational schedules. IPFS is attractive in this setting because sensor records can be chunked, content-addressed, cached near edge consumers, and retrieved without a single storage operator [
1,
2]. However, content addressing alone does not solve authorization. A sensor owner can encrypt chunks or register policy decisions on a blockchain, but the policy-checking process itself should not reveal requester attributes, facility roles, sensor-group topology, or internal authorization rules.
Blockchain-based access control addresses auditability by executing authorization logic in smart contracts, but public ledgers make both attributes and policies observable. Ciphertext-policy attribute-based encryption (CP-ABE) supports fine-grained authorization [
3,
4], while recent blockchain-assisted designs improve update and audit workflows. However, CP-ABE often couples the access policy to ciphertext and decryption cost, making frequent sensor stream updates and large attribute universes expensive. Zero-knowledge access control offers a different route: the requester proves that private credentials satisfy a sensor owner policy, and the chain or edge gateway verifies only a succinct proof. The original zk-Guard framework follows this route by combining Groth16 zk-SNARKs [
5] with a universal policy circuit, sparse policy configuration matrices, and Merkle tree proofs (MTPs) for IPFS chunks [
6]. Its central insight is valuable for IoT: the circuit should be reusable while sensor owners update policies and content roots.
The same design, however, leaves several production-level security gaps. First, a sparse configuration matrix can be semantically label-hidden but still structure-revealing: an observer can infer policy size, sparsity, role hierarchy, and policy-update patterns. Second, the MTP that links a requested IPFS chunk to a root block is not by itself a freshness guarantee. If a content identifier changes after an update, a stale proof tied to an old root can remain meaningful unless the authorization proof is bound to a current on-chain version. Third, compiling rich policies into tree-shaped constraints can push complexity to the prover when policies include nested Boolean expressions, range predicates, or frequent updates. Fourth, a gateway that releases IPFS chunks after proof verification can still be flooded by high-volume requests unless each accepted request carries an economic cost.
This paper proposes zk-Guard-R, a resilient redesign of zk-SNARK access control for IoT sensor data stored on IPFS. The design keeps the original goal of decoupling circuits from policies, but changes what is public, what is versioned, and what the prover executes. Instead of publishing a sparse policy matrix, zk-Guard-R stores only a policy commitment. Instead of using a single content root, it separates a long-lived logical sensor policy root from a frequently updated physical IPFS data root. Instead of compiling each policy into a tree-shaped circuit, it verifies attributes in one shallow module and evaluates a private reverse-Polish policy bytecode in a bounded stack interpreter. Finally, instead of treating bandwidth as a free post-verification resource, it places a payment channel voucher in front of gateway release.
To isolate the novelty more precisely, we distinguish between three roles of the paper. The original mechanisms are the combination of hidden policy commitments with nonce-bound double roots for IPFS-backed sensor streams, the use of a bounded private policy interpreter as the target access relation, and the coupling of accepted gateway release to voucher state. The adapted mechanisms are standard Merkle commitments, Groth16 proofs, range check gadgets, and payment channel accounting. The engineering integration is the gnark, Solidity, and Kubo/IPFS prototype that tests the main commitment, freshness, range, verifier gas, and gateway-metering surfaces under one reproducible workflow.
The contributions are as follows:
- 1.
We identify a policy-side-channel problem in public sparse policy encodings and introduce a policy commitment layer in which the policy matrix or bytecode is a private witness while only a commitment is stored on-chain.
- 2.
We define a double root freshness model that binds proofs to a logical policy root, a current IPFS data root, and a registry nonce, making stale MTPs unverifiable immediately after an authorized root update.
- 3.
We design a two-plane proving architecture: an attribute plane proves possession and range predicates over committed attributes, while a bounded stack interpreter evaluates private policy bytecode without regenerating setup material for each policy shape.
- 4.
We integrate a verification gateway with payment channel vouchers, converting bandwidth exhaustion from a free attack into a costed interaction while preserving off-chain proof verification for edge gateways.
- 5.
We implement a reproducible gnark BN254/Groth16 prototype for the IoT access statement and report constraint counts, proof time, verification time, memory use, deployed Solidity verifier gas, Kubo/IPFS gateway stress results, and comparisons against zk-Guard-style, CP-ABE-style, blockchain ABAC, and IoT token baselines.
The contribution claims are therefore calibrated as follows. The implemented prototype supports the committed-vector relation, range predicate, data root freshness, nonce binding, Solidity verification, and gateway stress tests. The bounded reverse-Polish policy interpreter is specified at the protocol and cost-model level, but its full instruction-decoding and stack-transition circuit is not included in the current benchmark tables; implementing and benchmarking this full interpreter is identified as a remaining engineering task.
The paper is organized as follows.
Section 2 reviews the relevant literature.
Section 3 gives the system and threat model.
Section 4 presents the zk-Guard-R protocol.
Section 5 analyzes security properties.
Section 6 gives complexity and prototype evaluation, and
Section 7 concludes.
3. System and Threat Model
3.1. Entities
zk-Guard-R contains seven entities. The attribute issuer authenticates requesters and issues signed attribute commitments, for example organization, device class, duty role, or consent status. The sensor owner uploads encrypted sensor chunks or time-window aggregates to IPFS, defines access policies, and registers commitments and roots. The data requester may be a mobile client, edge analytics service, or emergency-response application that holds private attributes and generates access proofs. The on-chain registry stores only commitments, verification keys, roots, and nonces. The prover is the requester’s local proof-generation component. The edge verification gateway checks proofs and payment vouchers before releasing chunks. The IPFS provider stores and serves content-addressed sensor chunks.
3.2. Adversary
We consider a probabilistic polynomial-time adversary that can observe the blockchain, read all public registry state, submit malformed access requests, replay old proofs, inspect policy-update timing, and operate malicious IPFS nodes or gateway clients. The adversary may control some requesters and may obtain old sensor content identifiers. The adversary cannot break the binding and hiding properties of the chosen commitment scheme, forge issuer signatures, find hash collisions, or produce false accepting zk-SNARK proofs except with negligible probability.
We additionally make the trust and leakage boundaries explicit. A compromised issuer can issue false attributes and is outside the protection of the proof relation unless issuer keys are revoked in the registry. Colluding requesters can pool their legitimately issued attributes only if the issuer credential format permits delegation; the intended instantiation binds attributes to requester keys. Observers may learn metadata such as policy-version timing, accessed sensor identifiers, proof submissions, voucher activity, configured public bounds, and gateway availability events. These metadata are not hidden by zk-Guard-R and are included in the leakage function in
Section 5.
The gateway is assumed to be economically rational and auditable. It may refuse service or attempt to overcharge, but payment channel state and signed receipts allow disputes. A malicious gateway can deny availability, so zk-Guard-R supports multiple gateways; it does not claim that one gateway alone provides censorship resistance.
For front-running and state-desynchronization, the verifier accepts a request only against the latest registry tuple returned by the contract or by a signed registry snapshot whose block height is within the configured freshness window. Voucher replay is prevented by monotonically increasing channel sequence numbers and gateway-side receipt logs. Proof verification flooding remains a network-layer and verifier-capacity issue; the voucher mechanism meters the expensive chunk release path rather than claiming to eliminate all packet-level denial of service.
3.3. Security Goals and Non-Goals
zk-Guard-R targets five goals:
- 1.
Access-decision soundness: A proof is accepted only if the user owns valid attributes satisfying the committed policy for the current registry state.
- 2.
Policy confidentiality: Public observers learn the existence and version of a policy but not the policy matrix, bytecode, sparsity pattern, or attribute labels beyond what is intentionally disclosed.
- 3.
Replay resistance: Proofs and MTPs tied to old data roots or old nonces are rejected after a registry update.
- 4.
Attribute privacy with numeric predicates: Equality and range predicates are proved without revealing raw attribute values.
- 5.
Economic DoS resistance: Accepted chunk release consumes a signed voucher or channel balance, making large-scale bandwidth abuse costly.
The design does not guarantee deletion of sensor chunks already pinned by third parties in IPFS. Freshness prevents current authorized gateways from releasing stale versions, but cryptographic confidentiality for old pinned blocks requires encrypted chunks and versioned key rotation.
4. The zk-Guard-R Design
4.1. Design Overview
zk-Guard-R reorganizes zk-Guard into four layers (
Figure 1). The registry layer stores commitments and freshness state. The proof layer checks attributes, policy bytecode, range predicates, and root freshness inside a zk-SNARK. The gateway layer verifies proofs and payment vouchers off-chain. The storage layer only releases chunks that match the current data root.
4.2. Notation and Registry State
Let
U be the requester attribute universe,
P a sensor access policy, and
the IPFS chunk set of a sensor stream or time-window aggregate. The registry stores
where
is a hiding and binding commitment to the policy representation,
identifies the long-lived sensor authorization object,
is the current Merkle root over encrypted IPFS chunk identifiers,
is a monotonically increasing version,
is the verification key, and
is the sensor owner’s signature over the tuple.
4.3. Policy Commitment Layer
The original sparse matrix
is replaced by a private policy witness. The sensor owner computes a commitment
and publishes only
. The prover supplies
and
privately. The circuit enforces
before evaluating the policy. For a Merkle commitment, the circuit either recomputes the root over a bounded policy array or verifies authenticated openings for the bytecode cells used by the interpreter. For a KZG commitment, openings are succinct outside the circuit, but in-circuit verification is costly unless the proof system natively supports the same pairing arithmetic. Therefore, the default zk-Guard-R instantiation uses a SNARK-friendly Merkle commitment, and treats KZG as a public-verifier optimization for future pairing-friendly implementations.
The confidentiality theorem below is stated for the full-root mode in which the policy program is padded to the public bound and the circuit recomputes or verifies a fixed-shape commitment. In an optimized authenticated-opening mode, the leakage function must additionally include the number of opened cells q, and, if openings are not padded or accessed in a fixed schedule, the access pattern of opened bytecode locations. We therefore treat the opening mode as a performance optimization that requires padding to recover the same structure-hiding claim.
4.4. Double Root Freshness and Nonce Binding
zk-Guard-R separates policy validity from content freshness.
changes only when the logical access object changes, for example, when a sensor owner replaces the policy family.
changes whenever the encrypted IPFS sensor chunk set changes. The nonce
increases on every authorized update. The public inputs to the access proof include
where
is the public commitment to the user’s attribute commitment set. The circuit checks that the MTP for the requested chunk reconstructs
, and the contract or gateway checks that
and
match the current registry state.
4.5. Attribute Plane and Policy Interpreter
The proof is split into two planes. The attribute plane proves that the user owns committed attributes issued by an authorized issuer. For equality attributes, the leaf contains a commitment to a key-value pair. For numeric attributes, the leaf contains a Pedersen-style commitment
, and the circuit verifies a range predicate by bit decomposition:
This supports statements such as and without revealing the raw age.
The policy plane executes a bounded reverse-Polish bytecode program. The instruction set is deliberately small:
The circuit contains a stack of size and a loop of length . Each step fetches one committed instruction, decodes it by one-hot selector constraints, updates the stack, and enforces that leaves a root value equal to 1. The circuit is independent of the syntactic tree of a particular policy, although the chosen bounds the maximum policy length.
The public bounds and are deployment parameters rather than hidden values. They should be selected from the largest policy class supported by the deployment; larger bounds improve policy flexibility but increase prover cost even for short policies. In the current gnark prototype, we instantiate a simpler private policy vector circuit rather than the full bytecode VM. This lets us measure the dominant MiMC-Merkle, range, data root, nonce, Solidity verifier, and gateway components without claiming that the full interpreter circuit has already been benchmarked.
4.6. Gateway and Payment Channel Release
The gateway accepts a request only if it contains: (i) the proof , (ii) the public state tuple , (iii) an MTP for the requested chunk, and (iv) a signed payment channel voucher with sequence number j. The gateway first checks that the channel has sufficient locked balance and that the voucher sequence number is fresh. It then verifies the proof against the current registry state. If verification succeeds, it releases the requested encrypted chunk and records a signed receipt. The final channel settlement charges only accepted releases; invalid proofs can be rate-limited by requiring a refundable verification deposit or by charging a small verification voucher.
4.7. Protocol Algorithms
Table 1 summarizes the main procedures. The algorithms are written at the interface level so that different SNARK backends, commitment schemes, and channel systems can instantiate them.
5. Security Analysis
Definition 1 (Access-decision soundness)
. An adversary wins the access-decision soundness game if it outputs a proof π and public input accepted by , but there is no valid issued attribute set, policy opening, range-witness assignment, and current data root proof satisfying the zk-Guard-R relation.
Theorem 1. If the underlying zk-SNARK is knowledge-sound, the commitment scheme is binding, the issuer signature is unforgeable, and the hash function used for Merkle roots is collision-resistant, then zk-Guard-R satisfies access-decision soundness.
Proof. Assume an adversary produces an accepting proof for a false access decision, as shown in
Table 2. Knowledge soundness yields a witness satisfying the arithmetic relation. The relation includes issuer-signature verification or a membership proof under an issuer-authorized attribute root; otherwise, signature unforgeability is broken. It includes the equality
; if the adversary uses a different policy from the committed one, binding is broken. It includes range and Boolean interpreter constraints; therefore, the policy result must equal 1 for the extracted attributes. It also includes reconstruction of
from the chunk MTP; if an invalid path is accepted, collision resistance is broken. Thus an accepting proof for a false decision contradicts at least one assumed primitive. □
Definition 2 (Policy confidentiality leakage)
. Let denote the public leakage consisting of the policy identifier, commitment , verification key identity, configured bounds , registry update times, proof submission times, requested sensor identifiers, voucher metadata, and gateway availability events. In the full-root padded mode, excludes policy labels, Boolean structure, sparsity pattern, and the actual bytecode length below . In authenticated-opening mode, additionally includes the number of opened cells and any unpadded opening pattern.
Definition 3 (Policy confidentiality)
. Policy confidentiality holds if any two policies and satisfying induce computationally indistinguishable public views for any chain observer.
Theorem 2. In the full-root padded mode, if the policy commitment is hiding and the zk-SNARK is zero-knowledge, then zk-Guard-R hides policy labels, contents, Boolean structure, sparsity pattern, and actual bytecode length up to the leakage function .
Proof. The public registry contains , roots, nonces, verification keys, and public bounds, but not P, its sparse matrix, or its padded bytecode. Hiding of makes commitments to and indistinguishable when their leakage functions match. The proof transcript reveals no witness information beyond the truth of the relation by zero knowledge. Since the full-root mode pads the program to and evaluates a fixed-shape circuit with stack bound , the public circuit and transcript do not expose the actual policy tree, sparsity, labels, or sub-bound bytecode length. The remaining metadata listed in are explicitly outside the hidden witness and must be mitigated, if necessary, by operational measures such as batching, cover traffic, and fixed-length update windows. □
Definition 4 (Replay resistance)
. Replay resistance holds if a proof generated for registry version and data root is rejected after a valid update to , except with negligible probability.
Theorem 3. Assuming the registry enforces monotonic nonces and authenticated owner updates, zk-Guard-R rejects stale proofs after data root updates.
Proof. Every accepted proof has public inputs containing and . The verifier or gateway obtains the latest tuple from the registry and requires exact equality. After an owner-authorized update, and, for content changes, except with a hash collision. A proof bound to the old tuple therefore fails the public-input equality check. A forged update would violate owner-signature authentication or registry monotonicity. □
Proposition 1 (Economic request bound)
. Let ϵ be the minimum non-refundable cost charged per accepted chunk release, and let D be the attacker’s locked channel deposit. Ignoring network-level amplification outside the gateway, the attacker can obtain at most accepted releases before settlement or channel exhaustion.
This proposition does not eliminate denial-of-service at the packet layer. It narrows the economically rational attack surface at the application layer: bandwidth-consuming releases are coupled to spendable channel state, and invalid requests can be filtered by deposits, voucher freshness, and proof prechecks.
Malicious gateways are handled by auditability rather than trust. A gateway can deny service, delay release, or equivocate about availability; clients can switch gateways, and signed receipts plus channel state provide dispute evidence for overcharging or replayed vouchers. Collusion between a requester and a gateway cannot forge access because proof verification still uses the current registry tuple, but collusion can reveal the chunks legitimately released to that requester. These cases are now treated as deployment threats rather than hidden by the formal proof.
7. Conclusions
This paper presented zk-Guard-R, a policy-hidden and replay-safe zk-SNARK access control framework for IoT sensor data stored on IPFS. The design replaces public sparse policy matrices with hidden policy commitments, binds access proofs to both logical and physical roots plus a nonce, separates attribute possession from policy interpretation through a bounded stack-based policy VM, supports numeric predicates over committed attributes, and uses payment channel vouchers to meter gateway bandwidth. The resulting architecture keeps succinct public verification while addressing policy side channels, stale MTP replay, policy-update friction, limited predicate expressiveness, and economically free request flooding. The gnark research prototype shows that real MiMC-Merkle policy and attribute commitments substantially increase prover-side cost but keep the public-input count and deployed verifier gas constant as the evaluated attribute universe grows. At , the implemented vector prototype used 425,574 constraints, generated proofs in 3121.100 ms in the original run and ms over three repeated runs, verified in 0.727 ms in the original run and ms over repeated runs, used approximately 641–654 MB peak Go heap allocation, and consumed 241,942 gas for a deployed Solidity verifier transaction on Anvil. A local Kubo/IPFS gateway stress test further confirmed that stale nonces are rejected before release and that accepted flood traffic is bounded by voucher budget. These values should be read as reproducible prototype evidence. The main remaining engineering tasks are to implement and benchmark the complete bytecode interpreter circuit, benchmark Circom and Halo2 backends, replace the CP-ABE proxy with a complete CP-ABE implementation, export proving and verification key sizes, add concurrent gateway experiments, and repeat the experiments on connected ARM edge and Android/mobile-class devices.