Skip to content

Commit

Permalink
Merge pull request #3 from proofcarryingdata/refactor/color-check
Browse files Browse the repository at this point in the history
Server-side color check
  • Loading branch information
cedoor authored Sep 4, 2023
2 parents 4623fdc + a51ce4e commit a339397
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
PCDPASS_URL="http://localhost:3000"

# Server.
SERVER_PORT=3000
SERVER_PORT=3005
PRIVATE_KEY="0x42"
47 changes: 40 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,37 @@
</h1>
</p>

| This repository contains a sample application demonstrating how to utilize the PCD SDK to add a PCD to the PCD passport. |
| ------------------------------------------------------------------------------------------------------------------------ |
| This monorepo contains a sample client and server to demonstrate the PCD SDK usage for issuing a PCD with a PCD passport. |
| ------------------------------------------------------------------------------------------------------------------------- |

## 🖼 Context

Proof-Carrying Data (PCD) is a self-contained, independent entity of data carrying sufficient information to be verified and interpreted by a consumer without reliance on exchanges between the producer and consumer. It comprises two primary components: the 'claim,' a straightforward statement (dubbed 'facts'), and the 'proof,' proving the truth of the statement by mathematical or cryptographic means. The elegance lies in the fact that no external information is necessary for validation; everything essential resides within. PCDs have the potential to revolutionize data handling. Envision a world where data flows unrestricted, free from the confinement of silos. PCDs can restore data ownership to individuals, facilitating portability across platforms, and removing barriers. PCD Issuers, whether your bank or Reddit, offer data imbued with cryptography or math (think Merkle Trees and signatures). You can blend it with your private data, creating your unique PCD. Any third-party application (PCD Consumer), from social networks to lending services, can wield this PCD as a key to unlock their services.

## ▶️ Workflow

Now, let's embark on a step-by-step journey to harness the potential of Proof-Carrying Data (PCD) utilizing EdDSA PCDs. In this scenario, a PCD comprises a 'claim,' represented as a simple message (the name of your chosen color), and a 'proof' (a signature) crafted by the PCD Issuer's confidential EdDSA key.

### Step 1: Prepare Your PCD Passport
Before delving into PCDs, ensure you have a valid PCD Passport identity instance. Your PCD Passport can accommodate multiple identities, each potentially carrying several PCDs (akin to attestations). You can efficiently manage these identities using the [zupass](https://github.com/proofcarryingdata/zupass/) PCD Passport.

### Step 2: Request a PCD from the PCD Issuer
Here's where the magic begins. You'll interact with the PCD Issuer implemented in this repository to get a PCD attesting to a signature on your chosen color name message. The process unfolds as follows:

1. The PCD Issuer takes your message and, like a digital wizard, applies its private EdDSA key to create a signature.
2. The Issuer returns the serialized PCD, a package of your 'claim' (the color name) and its corresponding 'proof' (the signature).
3. The client, thanks to the PCD SDK, seamlessly adds this PCD to your Passport.

Now, you've got your 'claim' (the color name) and 'proof' (signature) neatly stored and ready for the next step.

### Step 3: Interact with the PCD Consumer
With your PCD secured in your Passport, it's time to interact with the PCD Consumer, aptly named [example-consumer](https://github.com/proofcarryingdata/example-consumer). This step allows you to unlock the true potential of your PCD. Here's how it unfolds:

1. The PCD Consumer client diligently checks if the 'proof' match with the 'claim.' It does this by asking your PCD from your Passport.
2. The client initiates a challenge, verifying the PCD against the public key to check the validity of the EdDSA signature.
3. If the PCD proves its correctness, you gain access to the consumer features.

Among these features might be the ability to change the background color of the client interface to match the color specified in your original message.

## 🛠 Install

Expand All @@ -25,18 +54,22 @@ cd <your-repo> && yarn

## 📜 Usage

Copy the `.env.example` file as `.env`:
To run everything, you must have a local instance of the [zupass](https://github.com/proofcarryingdata/zupass/) PCD Passport on your machine. Follow this [guide](https://github.com/proofcarryingdata/zupass/#for-developers-local-development) to get it running correctly.

Copy the `.env.example` file as `.env` and add your environment variables:

```bash
cp .env.example .env
```

and add your environment variables or run the app in a local network.
Run the following command to build (client + server):

### Local server
```sh
yarn build
```

You can start your app locally with:
Run the following command to start the application (client + server):

```bash
yarn start
```
```
17 changes: 11 additions & 6 deletions apps/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { useCallback, useState } from "react"
import { constructPassportPcdAddRequestUrl, openPassportPopup } from "@pcd/passport-interface"

/**
* This component allows users to choose a color, which is then signed by
* This page allows users to choose a color, which is then signed by
* the issuer (server) and added to the user's PCDPass as an EdDSA PCD.
*/
export default function App() {
const [color, setColor] = useState("0xffffff")

// Send the color to the server which signs it and returns an EdDSA PCD.
const addEdDSAPCD = useCallback(async () => {
// Send the color to the server which signs it and returns an EdDSA PCD.
const response = await fetch(`http://localhost:${process.env.SERVER_PORT}/sign-message`, {
method: "POST",
mode: "cors",
Expand All @@ -21,6 +21,11 @@ export default function App() {
})
})

if (!response.ok) {
alert("Some error occurred")
return
}

const { serializedPCD } = await response.json()

// The EdDSA is added to the user's PCDPass.
Expand All @@ -37,11 +42,11 @@ export default function App() {
<>
<select name="colors" value={color} onChange={(event: any) => setColor(event.target.value)}>
<option value="0xffffff">White</option>
<option value="0xA27A7A">Red</option>
<option value="0xA2A08B">Yellow</option>
<option value="0xB8B8B8">Gray</option>
<option value="0xCF6969">Red</option>
<option value="0xDDD57E">Yellow</option>
<option value="0xBABABA">Gray</option>
</select>
<button onClick={addEdDSAPCD}>Add PCD signature</button>
<button onClick={addEdDSAPCD}>Add a PCD signature with your color</button>
</>
)
}
55 changes: 32 additions & 23 deletions apps/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import express, { Express, Request, Response } from "express"
dotenv.config({ path: `${process.cwd()}/../../.env` })

if (!process.env.PRIVATE_KEY) {
console.error(`[ERROR] The private key hasn't been set in the environment variables!`)
console.error(`[ERROR] The private key hasn't been set in the environment variables`)

process.exit(1)
}
Expand All @@ -27,36 +27,45 @@ app.get("/", (_req: Request, res: Response) => {
res.send("Express + TypeScript Server")
})

// It signs a message with the issuer EdDSA private key and returns a serialized PCD.
// Sign a message with the issuer EdDSA private key and returns a serialized PCD.
app.post("/sign-message", async (req: Request, res: Response) => {
try {
if (!req.body.color) {
console.error(`[ERROR] No color specified!`)
console.error(`[ERROR] No color specified`)

res.status(400).send()
} else {
console.debug(`[OKAY] color ${process.env.COLOR} has been successfully sent`)

const pcd = await prove({
id: {
argumentType: ArgumentTypeName.String
},
message: {
argumentType: ArgumentTypeName.StringArray,
value: [req.body.color]
},
privateKey: {
argumentType: ArgumentTypeName.String,
value: process.env.PRIVATE_KEY
}
})

const serializedPCD = await serialize(pcd)

res.json({ serializedPCD }).status(200)
return
}

if (!/^0x[0-9A-F]{6}$/i.test(req.body.color)) {
console.error(`[ERROR] No valid color`)

res.status(400).send()
return
}

const pcd = await prove({
id: {
argumentType: ArgumentTypeName.String
},
message: {
argumentType: ArgumentTypeName.StringArray,
value: [req.body.color]
},
privateKey: {
argumentType: ArgumentTypeName.String,
value: process.env.PRIVATE_KEY
}
})

console.debug(`[OKAY] color ${req.body.color} has been successfully signed`)

const serializedPCD = await serialize(pcd)

res.json({ serializedPCD }).status(200)
} catch (error: any) {
console.error(`[ERROR] ${error}`)

res.send(500)
}
})
Expand Down

0 comments on commit a339397

Please sign in to comment.