Skip to content

Commit 5c74239

Browse files
committed
predicate verifier that accepts a predicate like LT, GT, EQ and which property to check. Atm checking a credential on date_of_birth
1 parent 891527d commit 5c74239

File tree

9 files changed

+239
-23
lines changed

9 files changed

+239
-23
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
.DS_Store
22
Cargo.lock
3-
methods/guest/Cargo.lock
3+
methods/guests/bid_verifier/Cargo.lock
44
target/

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
resolver = "2"
33
members = ["host", "methods"]
44

5-
# Always optimize; building and running the guest takes much longer without optimization.
5+
# Always optimize; building and running the guests takes much longer without optimization.
66
[profile.dev]
77
opt-level = 3
88

data.json

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
{
22
"bidSize": 90000,
33
"eidIssuer": {
4-
"public_key": "08a7afd90669185118473b0c32b131e4ec117640baee540b9c743a782bb6b61e"
4+
"public_key": "777b2f5c9a1a0e52947c406a30ebadc951cca14f3e6a0f25b5306c36c1159c91"
55
},
66
"bank": {
7-
"public_key": "fd7042c505b5a4f047909da8d4c6c344b25a29f233f2201639445568617a6445"
7+
"public_key": "80b7a5472f8b79c011eecaf8115ea93b81494e7cfbc670e397ee705cac20ec2e"
88
},
99
"person": {
10-
"public_key": "5a2de976cf11503f2e6b670e2e12e0fe9f3b014eb615416b8ed0ac401811fbfd"
10+
"public_key": "721ebd125312884b5ce4a047263e04d48631624fc32058318c577ab269be9d9c"
1111
},
1212
"personCredential": {
1313
"credentialSubject": {
1414
"name": "Bob Bobley",
15-
"date_of_birth": "1980-10-01",
15+
"date_of_birth": 19801001,
1616
"nationality": "NO",
17-
"id": "did:key:z6MkkXHLrJ3bpDinQ736dvfBqt1AQhdqECbEkfmm7UHMyTCQ"
17+
"id": "did:key:z6Mkn8ji3BqfuiDdcSQ9PXgnZEB1DWoEY19YX3hHNkYxcc1h"
1818
},
1919
"issuer": {
20-
"id": "did:key:z6Mkf33cM15mFcLdi7fBwV8yKDu8o7LQSTHbaPzJaDWSWogR"
20+
"id": "did:key:z6MknVfWMf9etYYB2XQ5iq4vNwVPBvhewsG4Mu4KG5q1Hhc4"
2121
},
2222
"type": [
2323
"VerifiableCredential",
@@ -26,21 +26,21 @@
2626
"@context": [
2727
"https://www.w3.org/2018/credentials/v1"
2828
],
29-
"issuanceDate": "2023-11-11T20:37:55.000Z",
29+
"issuanceDate": "2023-11-20T19:49:29.000Z",
3030
"proof": {
3131
"type": "JwtProof2020",
32-
"jwt": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiUGVyc29uQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQm9iIEJvYmxleSIsImRhdGVfb2ZfYmlydGgiOiIxOTgwLTEwLTAxIiwibmF0aW9uYWxpdHkiOiJOTyJ9fSwic3ViIjoiZGlkOmtleTp6Nk1ra1hITHJKM2JwRGluUTczNmR2ZkJxdDFBUWhkcUVDYkVrZm1tN1VITXlUQ1EiLCJuYmYiOjE2OTk3MzUwNzUsImlzcyI6ImRpZDprZXk6ejZNa2YzM2NNMTVtRmNMZGk3ZkJ3Vjh5S0R1OG83TFFTVEhiYVB6SmFEV1NXb2dSIn0.ruDArqFrsNLm119AxflJgmOaztogxyF7hMFnFJ8NfoY2aq2fQeMY5gDgKrC4-9_XT8DKYPUm8TXI90QVF9XEBw"
32+
"jwt": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiUGVyc29uQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQm9iIEJvYmxleSIsImRhdGVfb2ZfYmlydGgiOjE5ODAxMDAxLCJuYXRpb25hbGl0eSI6Ik5PIn19LCJzdWIiOiJkaWQ6a2V5Ono2TWtuOGppM0JxZnVpRGRjU1E5UFhnblpFQjFEV29FWTE5WVgzaEhOa1l4Y2MxaCIsIm5iZiI6MTcwMDUwOTc2OSwiaXNzIjoiZGlkOmtleTp6Nk1rblZmV01mOWV0WVlCMlhRNWlxNHZOd1ZQQnZoZXdzRzRNdTRLRzVxMUhoYzQifQ.7c6sPZHwc-UZO2OlDv7_ttNLfnx9cBlvMYyAVXLryx_TTaleohTdaEqYmdpoM1tz3l2IVodWnnLOeDLRMVp6Aw"
3333
}
3434
},
3535
"houseLoanCredential": {
3636
"credentialSubject": {
3737
"loan_amount": 1000000,
3838
"loan_purpose": "house purchase",
3939
"expiration_date": "2023-11-18",
40-
"id": "did:key:z6MkkXHLrJ3bpDinQ736dvfBqt1AQhdqECbEkfmm7UHMyTCQ"
40+
"id": "did:key:z6Mkn8ji3BqfuiDdcSQ9PXgnZEB1DWoEY19YX3hHNkYxcc1h"
4141
},
4242
"issuer": {
43-
"id": "did:key:z6MkwWaUd3uHZchEqcFzFKD2Qy5CTrJdTx6pnXEAdc2B2nDJ"
43+
"id": "did:key:z6Mko7ieXpH2JDCfBc9MijYSLz8LofTtuFoEs9i2rQfrsvNR"
4444
},
4545
"type": [
4646
"VerifiableCredential",
@@ -49,10 +49,10 @@
4949
"@context": [
5050
"https://www.w3.org/2018/credentials/v1"
5151
],
52-
"issuanceDate": "2023-11-11T20:37:55.000Z",
52+
"issuanceDate": "2023-11-20T19:49:29.000Z",
5353
"proof": {
5454
"type": "JwtProof2020",
55-
"jwt": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiSG91c2VMb2FuQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJsb2FuX2Ftb3VudCI6MTAwMDAwMCwibG9hbl9wdXJwb3NlIjoiaG91c2UgcHVyY2hhc2UiLCJleHBpcmF0aW9uX2RhdGUiOiIyMDIzLTExLTE4In19LCJzdWIiOiJkaWQ6a2V5Ono2TWtrWEhMckozYnBEaW5RNzM2ZHZmQnF0MUFRaGRxRUNiRWtmbW03VUhNeVRDUSIsIm5iZiI6MTY5OTczNTA3NSwiaXNzIjoiZGlkOmtleTp6Nk1rd1dhVWQzdUhaY2hFcWNGekZLRDJReTVDVHJKZFR4NnBuWEVBZGMyQjJuREoifQ.bftL5w-4JRKxvIg-5mFE9G305sHPzaSWng-VggTFmKPgXtJytj8XNFtGWh3bkCx1gAj2kdy5y7lMERwdgCv7Cw"
55+
"jwt": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiSG91c2VMb2FuQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJsb2FuX2Ftb3VudCI6MTAwMDAwMCwibG9hbl9wdXJwb3NlIjoiaG91c2UgcHVyY2hhc2UiLCJleHBpcmF0aW9uX2RhdGUiOiIyMDIzLTExLTE4In19LCJzdWIiOiJkaWQ6a2V5Ono2TWtuOGppM0JxZnVpRGRjU1E5UFhnblpFQjFEV29FWTE5WVgzaEhOa1l4Y2MxaCIsIm5iZiI6MTcwMDUwOTc2OSwiaXNzIjoiZGlkOmtleTp6Nk1rbzdpZVhwSDJKRENmQmM5TWlqWVNMejhMb2ZUdHVGb0VzOWkyclFmcnN2TlIifQ.e3esT3D0TsvH_DDpbPVTrSKVLYzKvsoUfVYP6q5yULwjgqfGHOBc32ivD4zBChPPbHAJ1AwkguWe0ZsW14XBAg"
5656
}
5757
}
5858
}

host/src/main.rs

+77-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
use risc0_zkvm::{default_prover, ExecutorEnv, Receipt};
44
use serde::{Deserialize, Serialize};
55
use std::fs;
6+
use std::str::FromStr;
67

7-
use methods::{JWT_VERIFY_ELF, JWT_VERIFY_ID};
8+
use methods::{BID_VERIFIER_ELF, BID_VERIFIER_ID, PREDICATE_VERIFIER_ELF, PREDICATE_VERIFIER_ID};
9+
use crate::Condition::{GT, LT};
810

911
#[derive(Serialize, Deserialize, Debug)]
1012
struct PublicKeyHolder {
@@ -47,13 +49,48 @@ struct Root {
4749
house_loan_credential: Credential,
4850
}
4951

52+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
53+
enum Condition {
54+
LT,
55+
GT,
56+
EQ,
57+
}
58+
59+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
60+
struct Predicate {
61+
field: String,
62+
condition: Condition,
63+
value: u32
64+
}
65+
66+
67+
fn prove_predicate(
68+
jwt: &str,
69+
public_key_issuer: &str,
70+
predicate: Predicate
71+
) -> Receipt {
72+
73+
let input = (jwt, public_key_issuer, predicate);
74+
let env = ExecutorEnv::builder()
75+
.write(&input)
76+
.unwrap()
77+
.build()
78+
.unwrap();
79+
80+
let prover = default_prover();
81+
82+
// Produce a receipt by proving the specified ELF binary.
83+
prover.prove_elf(env, PREDICATE_VERIFIER_ELF).unwrap()
84+
}
85+
5086
fn prove_valid_bid(
5187
bid_size: u32,
5288
person_credential_jwt: &str,
5389
house_loan_credential_jwt: &str,
5490
eid_issuer_public_key: &str,
5591
bank_public_key: &str,
5692
) -> Receipt {
93+
5794
let input = (bid_size, person_credential_jwt, house_loan_credential_jwt, eid_issuer_public_key, bank_public_key);
5895
let env = ExecutorEnv::builder()
5996
.write(&input)
@@ -65,7 +102,7 @@ fn prove_valid_bid(
65102
let prover = default_prover();
66103

67104
// Produce a receipt by proving the specified ELF binary.
68-
prover.prove_elf(env, JWT_VERIFY_ELF).unwrap()
105+
prover.prove_elf(env, BID_VERIFIER_ELF).unwrap()
69106
}
70107

71108
fn main() {
@@ -74,6 +111,36 @@ fn main() {
74111

75112
// read json file from current directory
76113
let data = fs::read_to_string("./data.json").expect("Unable to read file");
114+
// verify_bid_program(&data);
115+
verify_predicate_program(&data);
116+
}
117+
118+
fn verify_predicate_program(data: &String) {
119+
let root: Root = serde_json::from_str(&data).expect("JSON was not well-formatted");
120+
121+
let person_credential = root.person_credential;
122+
123+
let predicate = Predicate{
124+
field: String::from_str("date_of_birth").unwrap(),
125+
condition: GT,
126+
value: 19791001
127+
};
128+
129+
let public_key_eid = root.eid_issuer.public_key;
130+
131+
let receipt = prove_predicate(&person_credential.proof.jwt, &public_key_eid, predicate);
132+
133+
let valid: bool = receipt.journal.decode().unwrap();
134+
receipt.verify(PREDICATE_VERIFIER_ID).unwrap();
135+
136+
println!("\n");
137+
println!("Verification results:");
138+
println!("\n");
139+
println!("{:<30} {}", "Verification status:", if valid { "Verified ✅" } else { "Failed ❌" });
140+
141+
}
142+
143+
fn verify_bid_program(data: &String) {
77144

78145
let root: Root = serde_json::from_str(&data).expect("JSON was not well-formatted");
79146

@@ -85,9 +152,15 @@ fn main() {
85152
let person_credential = root.person_credential;
86153
let house_loan_credential = root.house_loan_credential;
87154

88-
let receipt = prove_valid_bid(bid_size, &person_credential.proof.jwt, &house_loan_credential.proof.jwt, &public_key_eid, &public_key_bank);
155+
let receipt = prove_valid_bid(
156+
bid_size,
157+
&person_credential.proof.jwt,
158+
&house_loan_credential.proof.jwt,
159+
&public_key_eid,
160+
&public_key_bank
161+
);
89162
let (is_valid_bid, bidder_did, bid_size): (u32, String, u32) = receipt.journal.decode().unwrap();
90-
receipt.verify(JWT_VERIFY_ID).unwrap();
163+
receipt.verify(BID_VERIFIER_ID).unwrap();
91164

92165
// print two empty lines
93166
println!("\n");
@@ -99,5 +172,4 @@ fn main() {
99172
println!("{:<30} {}", "Bid status:", if is_valid_bid != 0 { "Valid ✅" } else { "Invalid ❌" });
100173
println!("{:<30} {}", "Bidder DID:", bidder_did);
101174
println!("\n");
102-
103175
}

methods/Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ anyhow = "1.0"
99
clap = "4.4"
1010
k256 = { version = "0.13", features = ["serde"] }
1111
rand_core = "0.6.4"
12-
serde = "1.0"
12+
serde = { version = "1.0", features = ["derive"] }
13+
serde_json = "1.0"
1314

1415
[build-dependencies]
1516
risc0-build = { version = "0.19.1" }
1617

1718
[package.metadata.risc0]
18-
methods = ["guest"]
19+
methods = ["guests/bid_verifier", "guests/predicate_verifier"]
1920

2021
[features]
2122
default = []

methods/guest/Cargo.toml methods/guests/bid_verifier/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "jwt_verify"
2+
name = "bid_verifier"
33
version = "0.1.0"
44
edition = "2021"
55

methods/guest/src/main.rs methods/guests/bid_verifier/src/main.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,27 @@
22

33
use ed25519_dalek::VerifyingKey;
44
use jwt_compact::{alg::*, prelude::*, Token, UntrustedToken};
5-
// If you want to try std support, also update the guest Cargo.toml file
5+
// If you want to try std support, also update the guests Cargo.toml file
66
use risc0_zkvm::guest::env;
77
use serde::{Deserialize, Serialize};
88

99
risc0_zkvm::guest::entry!(main);
1010

11+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
12+
struct GenericCredential {
13+
#[serde(rename = "credentialSubject")]
14+
credential_subject: serde_json::Value, // Flexible subject
15+
issuer: Issuer,
16+
#[serde(rename = "type")]
17+
types: Vec<String>,
18+
#[serde(rename = "@context")]
19+
context: Vec<String>,
20+
#[serde(rename = "issuanceDate")]
21+
issuance_date: String,
22+
proof: Proof,
23+
}
24+
25+
1126
#[derive(Serialize, Deserialize, Debug, PartialEq)]
1227
struct PersonCredentialSubject {
1328
name: String,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "predicate_verifier"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[workspace]
7+
8+
[dependencies]
9+
serde = "1.0"
10+
serde_json = "1.0"
11+
risc0-zkvm = { version = "0.19.1", default-features = false, features = ["std"] }
12+
hex = "0.4.3"
13+
k256 = { version = "=0.13.1", features = ["arithmetic", "serde", "expose-field", "std", "ecdsa"], default_features = false }
14+
jwt-compact = { version = "0.8.0", features = ["ed25519-dalek"] }
15+
ed25519-dalek = "2.0.0"
16+
17+
[profile.release]
18+
lto = "thin"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#![no_main]
2+
3+
use ed25519_dalek::VerifyingKey;
4+
use jwt_compact::{alg::*, prelude::*, Token, UntrustedToken};
5+
// If you want to try std support, also update the guests Cargo.toml file
6+
use risc0_zkvm::guest::env;
7+
use serde::{Deserialize, Serialize};
8+
9+
risc0_zkvm::guest::entry!(main);
10+
11+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
12+
struct GenericCredential {
13+
#[serde(rename = "credentialSubject")]
14+
credential_subject: serde_json::Value,
15+
// Flexible subject
16+
issuer: Issuer,
17+
#[serde(rename = "type")]
18+
types: Vec<String>,
19+
#[serde(rename = "@context")]
20+
context: Vec<String>,
21+
#[serde(rename = "issuanceDate")]
22+
issuance_date: String,
23+
proof: Proof,
24+
}
25+
26+
27+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
28+
struct Issuer {
29+
id: String,
30+
}
31+
32+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
33+
struct Proof {
34+
#[serde(rename = "type")]
35+
proof_type: String,
36+
jwt: String,
37+
}
38+
39+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
40+
struct CredentialClaims {
41+
vc: CredentialSubjectClaims,
42+
sub: String,
43+
iss: String,
44+
}
45+
46+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
47+
struct CredentialSubjectClaims {
48+
#[serde(rename = "credentialSubject")]
49+
credential_subject: serde_json::Value,
50+
#[serde(rename = "type")]
51+
types: Vec<String>,
52+
#[serde(rename = "@context")]
53+
context: Vec<String>,
54+
}
55+
56+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
57+
enum Condition {
58+
LT,
59+
GT,
60+
EQ,
61+
}
62+
63+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
64+
struct Predicate {
65+
field: String,
66+
condition: Condition,
67+
value: u32,
68+
}
69+
70+
fn check_predicate(claims: &CredentialClaims, predicate: &Predicate) -> bool {
71+
let credential_subject = &claims.vc.credential_subject;
72+
let field = &predicate.field;
73+
let value = &predicate.value;
74+
let condition = &predicate.condition;
75+
let credential_subject = credential_subject[field].as_u64().unwrap() as u32;
76+
match condition {
77+
Condition::LT => credential_subject < *value,
78+
Condition::GT => credential_subject > *value,
79+
Condition::EQ => credential_subject == *value,
80+
}
81+
}
82+
83+
pub fn main() {
84+
let (jwt_credential, public_key_issuer, predicate): (String, String, Predicate) = env::read();
85+
86+
let bytes_pk_eid_issuer: &[u8; 32] = &hex::decode(&public_key_issuer).unwrap().try_into().unwrap();
87+
88+
// Verify the signature, panicking if verification fails.
89+
let verifying_key_eid_issuer = VerifyingKey::from_bytes(&bytes_pk_eid_issuer).unwrap();
90+
91+
let untrusted_token_credential = UntrustedToken::new(&jwt_credential).unwrap();
92+
93+
let credential_claims: Token<CredentialClaims> = Ed25519.validator(&verifying_key_eid_issuer).validate(&untrusted_token_credential).unwrap();
94+
let credential = &credential_claims.claims().custom;
95+
96+
let date_of_birth = credential.vc.credential_subject["date_of_birth"].as_u64().unwrap() as u32;
97+
let predicate_date_of_birth = predicate.value;
98+
let predicate_condition = &predicate.condition;
99+
let predicate_field = &predicate.field;
100+
101+
println!("date_of_birth: {}", date_of_birth);
102+
println!("predicate_date_of_birth: {}", predicate_date_of_birth);
103+
println!("predicate_condition: {:?}", predicate_condition);
104+
println!("predicate_field: {}", predicate_field);
105+
106+
let is_valid = check_predicate(credential, &predicate);
107+
108+
// Commit to the journal the verifying key and message that was signed.
109+
env::commit(&(is_valid));
110+
}

0 commit comments

Comments
 (0)