Proof of Location
A Proof of Location allows a prover to demonstrate that their geographic coordinates lie within a specified area, defined by a center point and a radius, without revealing their exact location.
This primitive is essential for applications where location-based eligibility must be enforced while preserving user privacy. Instead of revealing where they are, users can prove only that they are somewhere inside an allowed region.
Typical examples include:
- geo-fenced voting or governance
- location-based access to digital services or assets
- regulatory or jurisdiction-based eligibility
- location-sensitive identity claims
To preserve privacy while ensuring soundness, the prover’s exact coordinates remain private. A private nonce is mixed into a location hash to prevent brute-force recovery of the coordinates from public outputs.
Why Privacy Matters for Location
Location is among the most sensitive personal data:
- it can uniquely identify individuals
- it reveals habits and behavior
- it enables tracking
Proof of Location allows systems to enforce geographic constraints without ever learning the exact coordinates.
Defining Proof of Location
At a high level, Proof of Location proves the statement:
Statement: I know coordinates
(lat, lon)such that their distance from(lat₀, lon₀)is less than or equal tor.
where:
(lat, lon)is the prover’s private location(lat₀, lon₀)andrare public
Crucially, the verifier learns only that the prover is inside the region, not where inside it they are.
Using the ZK-Toolbox (Developer View)
Inputs and Outputs
- Private inputs:
location: the prover’s exact latitude and longitudenonce: a random salt to protect the location hash
- Public inputs:
center: the latitude and longitude of the allowed arearadius: the radius (in meters)
- Public outputs:
locationHash: a commitment to the location, preventing leakage
Example
import { ProofOfLocation, randomBigInt32ModP } from "@prifilabs/zk-toolbox";
import { randomCirclePoint } from 'random-location';
// step 1: generate the inputs
const TORONTO = { latitude: 43.653908, longitude: -79.384293 };
const RADIUS = 50000; // 50km
const location = randomCirclePoint(TORONTO, RADIUS);
const nonce = randomBigInt32ModP();
const privateInputs = { location, nonce };
const publicInputs = { center: TORONTO, radius: RADIUS };
// step 2: generate the proof
const proofOfLocation = new ProofOfLocation();
const { proof, publicOutputs } = await proofOfLocation.generate(privateInputs, publicInputs);
// step 4: verify the proof
const res = await proofOfLocation.verify(proof, publicInputs, publicOutputs);
console.assert(res);
Behind the Scenes: The CIRCOM Circuit
The main challenge in Proof of Location is computing distances efficiently inside a SNARK.
From Spherical to Euclidean Geometry
GPS coordinates lie on the Earth’s surface and distances are normally computed using the Haversine Formula, which involves trigonometric functions and floating-point approximations.
These are extremely expensive to implement in SNARKs.
Instead, we project coordinates onto a plane using a Mercator projection transforming latitude/longitude into approximate Cartesian coordinates. This allows us to replace spherical distance with a simpler planar distance check.
Manhattan Distance Approximation
Rather than Euclidean distance, we use the Manhattan distance
|x₁ - x₂| + |y₁ - y₂| ≤ R
This avoids square roots and multiplications, making the circuit much more efficient while remaining conservative (i.e., slightly stricter than true Euclidean distance).
The zk‑toolbox wrapper handles the Mercator projection and scaling.
Our Circom Circuit
pragma circom 2.0.0;
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/switcher.circom";
template absDiff(n){
signal input in[2];
signal output out;
component c = LessThan(n);
c.in <== in;
component s = Switcher();
s.sel <== c.out;
s.L <== in[0];
s.R <== in[1];
out <== s.outR - s.outL;
}
template isWithinDistance(n){
signal input points[2][2];
signal input radius;
signal output out;
component dx = absDiff(n);
dx.in <== [points[0][0], points[1][0]];
component dy = absDiff(n);
dy.in <== [points[0][1], points[1][1]];
component checkDistance = LessThan(n);
checkDistance.in <== [dx.out + dy.out, radius];
out <== checkDistance.out;
}
template ProofOfLocation() {
signal input locLatitude;
signal input locLongitude;
signal input nonce;
signal input reqLatitude;
signal input reqLongitude;
signal input radius;
signal output locationWitinRadius;
signal output locationHash;
// check the distance is within radius
component locationWitinRadiusChecker = isWithinDistance(64);
locationWitinRadiusChecker.points <== [[locLatitude, locLongitude], [reqLatitude, reqLongitude]];
locationWitinRadiusChecker.radius <== radius;
locationWitinRadius <== locationWitinRadiusChecker.out;
locationWitinRadius === 1;
// hiding location
component locationHasher = Poseidon(3);
locationHasher.inputs <== [locLatitude, locLongitude, nonce];
locationHash <== locationHasher.out;
}
component main {public [reqLatitude, reqLongitude, radius]} = ProofOfLocation();
What the Circuit Enforces
The circuit guarantees that:
- The prover’s location is within the required radius
- The exact location is never revealed
- A salted commitment to the location is publicly available
The nonce prevents attackers from brute-forcing plausible locations based on the hash output.
Conclusion and Applications
Proof of Location brings zero-knowledge proofs into the realm of spatial privacy.
It enables systems to enforce geographic constraints while preserving user anonymity and preventing location tracking.
Example Applications
-
Geo-fenced voting systems
Allowing only users physically present in a region to vote, without revealing individual locations. -
Jurisdiction-based compliance
Proving that a user is within a legally permitted area for accessing regulated services. -
Location-based digital assets
Unlocking NFTs, tokens, or content only when the user is in a certain place. -
Privacy-preserving access control
Granting access to facilities or services based on proximity, without continuous tracking. -
Decentralized identity with spatial claims
Proving claims such as “I am in Canada” or “I am not in a restricted zone” without revealing an address.