Skip to content

Commit 10092ce

Browse files
authored
✨ Use hyli noir lib for check_jwt (#43)
1 parent c1f3296 commit 10092ce

File tree

11 files changed

+290
-1275
lines changed

11 files changed

+290
-1275
lines changed

hyli-wallet/bun.lock

Lines changed: 254 additions & 386 deletions
Large diffs are not rendered by default.

hyli-wallet/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
"peerDependencies": {
2525
"react": "^19.1.0",
2626
"react-dom": "^19.1.0",
27-
"react-router-dom": "^7.6.1",
28-
"hyli-noir": "^0.1.0"
27+
"react-router-dom": "^7.6.1"
2928
},
3029
"scripts": {
3130
"clean": "rm -rf dist",
@@ -43,6 +42,7 @@
4342
"elliptic": "^6.6.1",
4443
"noir-jwt": "^0.4.5",
4544
"hyli": "^0.4.1",
45+
"hyli-noir": "0.2.6",
4646
"js-sha3": "^0.9.3"
4747
},
4848
"devDependencies": {

hyli-wallet/src/components/auth/AuthForm.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import React, { useState, useEffect } from "react";
2-
import { AuthCredentials, AuthProvider } from "../../providers/BaseAuthProvider";
2+
import { AuthProvider } from "../../providers/BaseAuthProvider";
33
import { ProviderOption, useWalletInternal } from "../../hooks/useWallet";
4-
import { RegistrationStage, WalletErrorCallback, WalletEvent, WalletEventCallback } from "../../types/wallet";
4+
import { RegistrationStage, WalletEvent } from "../../types/wallet";
55
import { getAuthErrorMessage } from "../../utils/errorMessages";
66
import "./AuthForm.css";
77
import { PasswordAuthCredentials } from "../../providers/PasswordAuthProvider";
88
import type { GoogleAuthCredentials } from "../../providers/GoogleAuthProvider";
9-
import { bytesToBigInt, extractClaimsFromJwt, JWTCircuitHelper, pubkeyModulusFromJWK } from "../../utils/jwt";
10-
import { fetchGooglePublicKey } from "../../utils/google";
11-
import { Barretenberg, Fr } from "@aztec/bb.js";
129

1310
type AuthStage =
1411
| "idle" // Initial state, no authentication in progress
@@ -80,7 +77,7 @@ export const AuthForm: React.FC<AuthFormProps> = ({
8077
forceSessionKey,
8178
setLockOpen,
8279
}) => {
83-
const { login, registerAccount: registerWallet, sessionKeyConfig, onWalletEvent, onError } = useWalletInternal();
80+
const { login, registerAccount: registerWallet, onWalletEvent, onError } = useWalletInternal();
8481
const isLocalhost =
8582
typeof window !== "undefined" &&
8683
(window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
@@ -170,7 +167,7 @@ export const AuthForm: React.FC<AuthFormProps> = ({
170167
if (onError) onError(err);
171168
};
172169

173-
const handleGoogleSubmit = async (e: React.FormEvent) => {
170+
const handleGoogleSubmit = async (_: React.FormEvent) => {
174171
try {
175172
setIsSubmitting(true);
176173
setStage("sending_blob");

hyli-wallet/src/providers/GoogleAuthProvider.ts

Lines changed: 28 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
addSessionKeyBlob, // <- version corrigée ci-dessus
1010
WalletEventCallback,
1111
walletContractName,
12-
build_check_jwt_blob,
1312
} from "../types/wallet"; // ajuste le chemin si besoin
1413

1514
import { BlobTransaction } from "hyli"; // ajuste le chemin si besoin
@@ -18,11 +17,8 @@ import { IndexerService } from "../services/IndexerService";
1817
import { sessionKeyService } from "../services/SessionKeyService";
1918

2019
import * as WalletOperations from "../services/WalletOperations";
21-
import { Barretenberg, Fr } from "@aztec/bb.js";
22-
import { bytesToBigInt, extractClaimsFromJwt, JWTCircuitHelper, register_contract } from "../utils/jwt";
23-
import { fetchGooglePublicKey } from "../utils/google";
24-
import { circuit } from "../utils/jwt_circuit";
25-
import { Blob } from "hyli";
20+
import { check_jwt } from "hyli-noir";
21+
import { fetchGooglePublicKeys } from "../utils/google";
2622

2723
export interface GoogleAuthCredentials {
2824
username: string; // requis par AuthCredentials
@@ -167,14 +163,14 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
167163

168164
onWalletEvent?.({ account, type: "checking_password", message: "Verifying Google identity…" });
169165

170-
const jwtBlobData = await this.buildCheckJwtBlob(credentials.googleToken, onError);
166+
const { keys } = await fetchGooglePublicKeys();
167+
168+
const jwtBlobData = await check_jwt.build_blob_from_jwt(credentials.googleToken, keys);
171169

172170
if (jwtBlobData instanceof Error) {
173171
return { success: false, error: jwtBlobData.message };
174172
}
175173

176-
console.log("Blob0 data (stored_hash):", jwtBlobData.blob.data);
177-
178174
const blob1 = verifyIdentityBlob(username, jwtBlobData.nonce);
179175

180176
const blobTx: BlobTransaction = {
@@ -190,7 +186,7 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
190186
blobTx.blobs.push(addSessionKeyBlob(username, newSessionKey.publicKey, expiration, whitelist));
191187
}
192188

193-
await register_contract(nodeService.client, circuit as any);
189+
await check_jwt.register_contract(nodeService.client);
194190

195191
onWalletEvent?.({ account, type: "sending_blob", message: `Sending blob transaction` });
196192
// Skipped, to make sure we send the proof alongside.
@@ -207,17 +203,15 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
207203
onWalletEvent?.({ account, type: "custom", message: `Generating proof of jwt` });
208204

209205
// Generate proof using JWT circuit
210-
const proof_tx = await JWTCircuitHelper.generateProofTx({
211-
identity: account,
212-
stored_hash: jwtBlobData.blob.data,
213-
tx: txHash,
214-
blob_index: 0,
215-
tx_blob_count: 2,
216-
idToken: credentials.googleToken,
217-
jwtPubkey: jwtBlobData.pubkey,
218-
});
219-
220-
console.log("Generated JWT proof:", proof_tx);
206+
const proof_tx = await check_jwt.build_proof_transaction(
207+
account,
208+
jwtBlobData.blob.data,
209+
txHash,
210+
0,
211+
2,
212+
credentials.googleToken,
213+
jwtBlobData.pubkey,
214+
);
221215

222216
await nodeService.client.sendProofTx(proof_tx);
223217

@@ -243,47 +237,6 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
243237
}
244238
}
245239

246-
async buildCheckJwtBlob(
247-
googleToken: string,
248-
onError?: (error: Error) => void,
249-
): Promise<{ blob: Blob; nonce: number; mail_hash: Fr; pubkey: JsonWebKey } | Error> {
250-
const { email, nonce, kid } = extractClaimsFromJwt(googleToken);
251-
252-
if (!email || !nonce || !kid) {
253-
const error = "Invalid Google token: missing email, nonce, or kid";
254-
onError?.(new Error(error));
255-
return new Error(error);
256-
}
257-
258-
// Get Google pubkey
259-
const googleJWTPubkey = await fetchGooglePublicKey(kid);
260-
261-
let mail_hash: Fr = Fr.ZERO;
262-
263-
console.log("Computing mail_hash for email", email);
264-
const bb = await Barretenberg.new();
265-
console.log("selected_mail", email);
266-
console.log("email byte array", new TextEncoder().encode(email));
267-
console.log("email bigint:", bytesToBigInt(new TextEncoder().encode(email)));
268-
mail_hash = await bb.poseidon2Hash([new Fr(bytesToBigInt(new TextEncoder().encode(email)))]).catch((err) => {
269-
console.error("Error computing poseidon hash:", err);
270-
throw err;
271-
});
272-
273-
console.log("Computed mail_hash:", mail_hash);
274-
console.log("mail_hash as bigint:", bytesToBigInt(mail_hash.value));
275-
console.log("mail_hash as hex:", mail_hash.toString());
276-
277-
// Generate proof using JWT circuit
278-
279-
return {
280-
nonce: parseInt(nonce, 10),
281-
mail_hash,
282-
pubkey: googleJWTPubkey,
283-
blob: build_check_jwt_blob(mail_hash.value, nonce, googleJWTPubkey.n as string) as Blob,
284-
};
285-
}
286-
287240
async register(params: RegisterAccountParams<GoogleAuthCredentials>): Promise<AuthResult> {
288241
console.log("[Hyli][Google] register() called");
289242
const nodeService = NodeService.getInstance();
@@ -318,7 +271,9 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
318271
};
319272
}
320273

321-
const jwtBlobData = await this.buildCheckJwtBlob(googleToken, onError);
274+
const { keys } = await fetchGooglePublicKeys();
275+
276+
const jwtBlobData = await check_jwt.build_blob_from_jwt(googleToken, keys);
322277

323278
if (jwtBlobData instanceof Error) {
324279
return { success: false, error: jwtBlobData.message };
@@ -330,7 +285,7 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
330285
username,
331286
jwtBlobData.nonce,
332287
"",
333-
{ Jwt: { hash: Array.from(jwtBlobData.mail_hash.value) } },
288+
{ Jwt: { hash: jwtBlobData.mail_hash } },
334289
inviteCode,
335290
);
336291

@@ -347,7 +302,7 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
347302
blobTx.blobs.push(addSessionKeyBlob(username, newSessionKey.publicKey, expiration, whitelist));
348303
}
349304

350-
await register_contract(nodeService.client, circuit as any);
305+
await check_jwt.register_contract(nodeService.client);
351306

352307
onWalletEvent?.({ account: identity, type: "sending_blob", message: `Sending blob transaction` });
353308
// Skipped, to make sure we send the proof alongside.
@@ -364,17 +319,15 @@ export class GoogleAuthProvider implements AuthProvider<GoogleAuthCredentials> {
364319
onWalletEvent?.({ account: identity, type: "custom", message: `Generating proof of jwt` });
365320

366321
// Generate proof using JWT circuit
367-
const proof_tx = await JWTCircuitHelper.generateProofTx({
322+
const proof_tx = await check_jwt.build_proof_transaction(
368323
identity,
369-
stored_hash: jwtBlobData.blob.data,
370-
tx: txHash,
371-
blob_index: 0,
372-
tx_blob_count: 3,
373-
idToken: googleToken,
374-
jwtPubkey: jwtBlobData.pubkey,
375-
});
376-
377-
console.log("Generated JWT proof:", proof_tx);
324+
jwtBlobData.blob.data,
325+
txHash,
326+
0,
327+
3,
328+
googleToken,
329+
jwtBlobData.pubkey,
330+
);
378331

379332
await nodeService.client.sendProofTx(proof_tx);
380333

hyli-wallet/src/utils/google.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
1-
export async function fetchGooglePublicKey(keyId: string) {
2-
if (!keyId) {
3-
return null;
4-
}
5-
1+
export async function fetchGooglePublicKeys<T extends JsonWebKey & { kid: string }>(): Promise<{ keys: T[] }> {
62
const response = await fetch("https://www.googleapis.com/oauth2/v3/certs");
7-
const keys = await response.json();
8-
9-
const key = keys.keys.find((key: { kid: string }) => key.kid === keyId);
10-
if (!key) {
11-
console.error(`Google public key with id ${keyId} not found`);
12-
return null;
13-
}
14-
15-
return key;
3+
return await response.json();
164
}

0 commit comments

Comments
 (0)