diff --git a/content/docs/zkfetch/index.mdx b/content/docs/zkfetch/index.mdx index e294422..dfb41ca 100644 --- a/content/docs/zkfetch/index.mdx +++ b/content/docs/zkfetch/index.mdx @@ -3,28 +3,19 @@ title: zkFetch SDK description: fetch, but with a zkproof --- -zkFetch allows you to securely fetch remote resources over HTTPS endpoints, providing a proof of correct execution that can be verified by third parties. This ensures that sensitive operations, such as using private API keys, are performed correctly without exposing confidential information. +This is like a regular `fetch` call, but also generates a zkProof of the request and its corresponding response. -## Overview +You can think of this as a tuple `(request, response, zkproof)`. +The `zkproof` tightly couples the request and response, so it becomes impossible to fake the response - secured by cryptography. -You can integrate Reclaim into your backend using zkFetch SDK +In some cases, it might not be possible to reveal the entire request or response. That is because the request or response might contain some sensitive information like api-keys, username/passwords, PII etc. -### Flows +Using zero knowledge proofs, you can redact parts of the request and response without compromising the security of the cryptographic authenticity. So, the tuple that is really generated is +``` +(redacted-request, redacted-response, zkproof) +``` -#### Integrating zkFetch +You can use this library just like you would use a `fetch` call in javascript. -The workflow is as follows: - -1. **Initiate Request:** The user calls zkFetch, providing options such as URL, method, and headers. -2. **Fetch and Generate Proof:** zkFetch performs the fetch operation and generates a proof -3. **Verify and Transform Proof:** The proof is verified using `verifySignedProof` and transformed with the `transform` method - - -## When to Use zkFetch - -zkFetch is recommended for fetching public data where the integrity and authenticity of the data need to be verified without exposing any sensitive information. Use zkFetch in scenarios such as: - -- Ideal when data is publicly available -- Perfect when you have the auth token and endpoint diff --git a/content/docs/zkfetch/installation.mdx b/content/docs/zkfetch/installation.mdx new file mode 100644 index 0000000..a142451 --- /dev/null +++ b/content/docs/zkfetch/installation.mdx @@ -0,0 +1,42 @@ +--- +title: Installation +description: Flutter SDK for Reclaim Protocol +--- + +## Prerequisites +- NodeJS 18 or later + +## Get an API Key +Setup your project using the [Get API Key guide](/api-key). + +## Enable zkFetch +Make sure zkFetch is turned on for your application from the [Dev Tool](https://dev.reclaimprotocol.org). You can do so by navigating to the application, and looking for zkFetch in the Integration tab. + +## Installation + +```bash copy +npm i @reclaimprotocol/zk-fetch +``` + +Please download zk files using this command: +```bash copy +node node_modules/@reclaimprotocol/zk-symmetric-crypto/lib/scripts/download-files +``` + +### Additional NextJS Configuration + +zkFetch uses native modules that need to be externalized in Next.js. Add this to your `next.config.ts`: + +```typescript +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + serverExternalPackages: ['koffi', '@reclaimprotocol/zk-fetch'], +}; + +export default nextConfig; +``` + + + + diff --git a/content/docs/zkfetch/meta.json b/content/docs/zkfetch/meta.json index 7bc70eb..37ced9f 100644 --- a/content/docs/zkfetch/meta.json +++ b/content/docs/zkfetch/meta.json @@ -1,4 +1,4 @@ { "title": "ZK Fetch", - "pages": ["quickstart", "cardano", "stellar"] + "pages": ["installation", "usage", "cardano", "stellar"] } \ No newline at end of file diff --git a/content/docs/zkfetch/quickstart.mdx b/content/docs/zkfetch/quickstart.mdx deleted file mode 100644 index 950146f..0000000 --- a/content/docs/zkfetch/quickstart.mdx +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Quickstart -description: The Reclaim Protocol Proofs are compatible with blockchain applications. ---- - -import { Step, Steps } from 'fumadocs-ui/components/steps'; - -## Prerequisites - -- **Node.js 18.0.0 or later** -- An application ID and secret from Reclaim Protocol. Obtain these from the [Reclaim Developer Protocol](https://dev.reclaimprotocol.org/). - -you can find more examples/starter packs here - -- [React Example](https://gitlab.reclaimprotocol.org/starterpacks/reclaim-zkfetch-client) -- [Express Example](https://gitlab.reclaimprotocol.org/starterpacks/zkfetch-express-example) -- [Ethers.js Example](https://gitlab.reclaimprotocol.org/starterpacks/zkfetch-ethers-example) - -## Quickstart - - - The following tutorial is based on a Node.js - - - - - -### Create an application on Dev Tool -Head to https://dev.reclaimprotocol.org and create a new zkFetch application. Once you create the application, you'll be given an `application ID` and an `application secret`. Please take note of these. These will be used in the next steps. - -### Install zkFetch SDK - -```bash copy -npm i @reclaimprotocol/zk-fetch -``` -For using response redactions additionally, please download zk files using this command: -```bash copy -node node_modules/@reclaimprotocol/zk-symmetric-crypto/lib/scripts/download-files -``` - -### Import Reclaim Client - -```js copy -import { ReclaimClient } from '@reclaimprotocol/zk-fetch'; -``` - -### Initialize Reclaim Client - -```js copy -const client = new ReclaimClient('YOUR_APP_ID', 'YOUR_APP_SECRET') -``` - -### Add Public/Private headers, optional but recommended - -##### For public endpoints -If the endpoint you want to _fetch_ and generate a proof of the response. This endpoint is public, and doesn't need any private data like auth headers/api keys. - -This is useful when -- Verifier needs to verify without re-doing the api call -- The API doesn't need any private headers or auth -- The proof or response needs to be generated for a particular endpoint now, and verified later - -```js copy - const publicOptions = { - method: 'GET', // or POST - headers : { - accept: 'application/json, text/plain, */*' - } - } - const proof = await client.zkFetch( - 'https://your.url.org', - publicOptions - ) -``` - -Note : all the data in the publicOptions will be visible to them who you share the proof with (aka, verifier). - -##### For private endpoint -If you want to _fetch_ and generate a proof of the response, but the fetch involves some private data like auth headers or api keys - -This is useful when -- Using API keys -- Using Auth headers - -```js - const publicOptions = { - method: 'GET', // or POST - headers : { - accept: 'application/json, text/plain, */*' - } - } - - const privateOptions = { - headers : { - apiKey: "123...456", - someOtherHeader: "someOtherValue", - } - } - - const proof = await client.zkFetch( - 'https://your.url.org', - publicOptions, - privateOptions - ) - -``` - -All the data in the privateOptions will stay hidden to the verifier. - - -### Fetch using zkFetch - -```js copy showLineNumbers {11-12} -const proof = await client.zkFetch('https://your.url.org') -``` - -### Additonal Features - -#### Retries and Retry Interval -Add retries and set a retry interval for fetch requests: - -```js -const proof = await client.zkFetch('https://your.url.org', publicOptions, privateOptions, 5, 10000); -``` - -#### Add Geolocation -Specify a geolocation (optional) using a two-letter ISO country code: - -```js -const publicOptions = { - method: 'GET', - headers: { accept: 'application/json' }, - geoLocation: 'US' // Example: 'US' for the United States -}; -const proof = await client.zkFetch('https://your.url.org', publicOptions); -``` -#### Using Response Match and Redactions - -ou can also use responseMatches and responseRedactions to match and redact the response. This is useful when you want to verify the response against a particular value or redact some part of the response. - -```js copy - const publicOptions = { - method: 'GET', // or POST - headers : { - accept: 'application/json, text/plain, */*' - } - } - - const privateOptions = { - responseMatches: [ - { - type: 'contains' | 'regex', // type of match - value: '' | '', // value to match or regex to match - } - ], - responseRedactions: [ - { - jsonPath: '$.data', // JSON path to redact - xPath: '/data', // Xpath to redact - regex: '', // Regex to redact - } - ] - } -``` - -Note: The responseMatches and responseRedactions are optional and can be used as per the requirement. - -### Verify the proofs and transform proof for onchain - -#### Verify the proofs - -Install @reclaimprotocol/js-sdk - -```bash copy -npm install @reclaimprotocol/js-sdk -``` - -Import the Reclaim class from the js-sdk - -```js copy -const { Reclaim } = require('@reclaimprotocol/js-sdk'); -``` - -Use Reclaim.verifySignedProof(proof) - -You must send the proofObject and not the verifiedResponse to the verifier for them to be able to verify. - -```js -const isProofVerified = await Reclaim.verifySignedProof(proof); -``` - -it verifies the authenticity and completeness of a given proof. It checks if the proof contains signatures, recalculates the proof identifier, and verifies it against the provided signatures. If the verification fails, it will log the error and return false. - -More information about the verifySignedProof method can be found [here](https://docs.reclaimprotocol.org/sdk-methods#verifysignedproofproof--promiseboolean) - -#### Transform proof for onchain - -Transforms proof data into a format suitable for on-chain transactions, you need to use it before sending the proof to the blockchain. - -Use Reclaim.transformForOnchain(proof) from the js-sdk to transform the proof for onchain. - -```js -const onchainProof = Reclaim.transformForOnchain(proof); -``` - - - - - -## Summarizing - -```js copy -import { ReclaimClient } from '@reclaimprotocol/zk-fetch'; -import { Reclaim } from '@reclaimprotocol/js-sdk' - -const client = new ReclaimClient(YOUR_APP_ID, YOUR_APP_SECRET); - -const generateProof = async() => { - try{ - // URL to fetch the data from - in this case, the price of Ethereum in USD from the CoinGecko API - const url = 'https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd'; - /* - * Fetch the data from the API and generate a proof for the response. - * The proof will contain the USD price of Ethereum. - */ - const proof = await client.zkFetch(url, { - // public options for the fetch request - method: 'GET', - }, { - // options for the proof generation - responseMatches: [ - /* - * The proof will match the response body with the regex pattern (search for the price of ethereum in the response body - the regex will capture the price in the named group 'price'). - * to extract the price of Ethereum in USD. (e.g. {"ethereum":{"usd":3000}}) - */ - { - "type": "regex", - "value": "\\{\"ethereum\":\\{\"usd\":(?[\\d\\.]+)\\}\\}" - } - ], - }); - - // Verify Proof - const isVerified = await Reclaim.verifySignedProof(proof) - - // Transform the proof data to be used on-chain - const proofData = await Reclaim.transformForOnchain(proof); - - } catch(error){ - console.log(error) - } -} -``` - - - diff --git a/content/docs/zkfetch/usage.mdx b/content/docs/zkfetch/usage.mdx new file mode 100644 index 0000000..c29663d --- /dev/null +++ b/content/docs/zkfetch/usage.mdx @@ -0,0 +1,155 @@ +--- +title: Usage +description: The Reclaim Protocol Proofs are compatible with blockchain applications. +--- + +import { Step, Steps } from 'fumadocs-ui/components/steps'; + +### Import Reclaim Client + +```js copy +import { ReclaimClient } from '@reclaimprotocol/zk-fetch'; +``` + +### Initialize Reclaim Client + +```js copy +const client = new ReclaimClient('YOUR_APP_ID', 'YOUR_APP_SECRET') +``` + +## Add Public/Private headers +Headers are a standard part of any `fetch` request. +When a proof is created, it is created for what was the request and what was its corresponding response. +The `request` consists of `headers` and `body`. + +A typical fetch request looks like so : +``` +fetch(url, { + method: 'POST', + headers : { ... }, + body: {...} +}) +``` + +In this request, there might be sensitive information like api keys or username & password that should not be revealed as part of the proof. + +For that purpose, you should construct two separate request objects `publicOptions` and `privateOptions`. + +As the names suggest, public options will be revealed whereas private options will be redacted. We recommend keeping as little information in `privateOptions` as possible - to maintain the sanctity of the verification. + +Example, +```js + const publicOptions = { + method: 'GET', // or POST + headers : { + accept: 'application/json, text/plain, */*' + } + } + + const privateOptions = { + headers : { + apiKey: "123...456", + }, + body : { + username: "supersecretvalue" + } + } + + const proof = await client.zkFetch( + 'https://your.url.org', + publicOptions, + privateOptions + ) + +``` + +## Reading the response +``` + const data = JSON.parse(proof?.extractedParameterValues?.data); +``` +### Troubleshooting : chunked responses +If the server returns chunked responses, you will need to decode the chunked response before parsing. + +``` +function decodeChunkedResponse(chunkedData: string): string { + // Remove chunk size markers (hex number + \r\n) + // and trailing \r\n markers + return chunkedData + .replace(/^[0-9a-fA-F]+\r\n/, '') // Remove initial chunk size + .replace(/\r\n0\r\n\r\n$/, '') // Remove final chunk marker + .replace(/\r\n[0-9a-fA-F]+\r\n/g, ''); // Remove any intermediate chunk markers +} + +... + + const rawData = proof?.extractedParameterValues?.data || ''; + const cleanedData = decodeChunkedResponse(rawData); + const data = JSON.parse(cleanedData); +``` + +### Example +You can use [LLM x402 project](https://llm-x402.reclaimprotocol.org) as a sample reference, which verifies that the api response actually came from the correct LLM. + + +# Advance Options +## Using Response Match and Redactions +You can also use responseMatches and responseRedactions to match and redact the response. This is useful when you want to verify the response against a particular value and/or redact some part of the response. + +```js copy + const publicOptions = { + method: 'GET', // or POST + headers : { + accept: 'application/json, text/plain, */*' + } + } + + const privateOptions = { + responseMatches: [ + { + type: 'contains' | 'regex', // type of match + value: '' | '', // value to match or regex to match + } + ], + responseRedactions: [ + { + jsonPath: '$.data', // JSON path to redact + xPath: '/data', // Xpath to redact + regex: '', // Regex to redact + } + ] + } +``` + +## Verify the proofs and transform proof for onchain + +### Verify the proofs + +Install @reclaimprotocol/js-sdk + +```bash copy +npm install @reclaimprotocol/js-sdk +``` + +Import the Reclaim class from the js-sdk + +```js copy +const { Reclaim } = require('@reclaimprotocol/js-sdk'); +``` + +Use Reclaim.verifySignedProof(proof) + +You must send the proofObject and not the verifiedResponse to the verifier for them to be able to verify. + +```js +const isProofVerified = await Reclaim.verifySignedProof(proof); +``` + +#### Transform proof for onchain + +Transforms proof data into a format suitable for on-chain transactions, you need to use it before sending the proof to the blockchain. + +Use Reclaim.transformForOnchain(proof) from the js-sdk to transform the proof for onchain. + +```js +const onchainProof = Reclaim.transformForOnchain(proof); +```