Skip to content

Commit 9512a3d

Browse files
authored
fix: misreported hw key bug (#936)
* fix: misreported hw key bug * chore: format * fix: code issues spotted by code rabbit AI * chore: format * chore: bump version * chore: format
1 parent f9c0f83 commit 9512a3d

13 files changed

Lines changed: 377 additions & 37 deletions

File tree

infrastructure/eid-wallet/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eid-wallet",
3-
"version": "0.7.0",
3+
"version": "0.7.1",
44
"description": "",
55
"type": "module",
66
"scripts": {

infrastructure/eid-wallet/src-tauri/tauri.conf.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "eID for W3DS",
4-
"version": "0.7.0",
4+
"version": "0.7.1",
55
"identifier": "foundation.metastate.eid-wallet",
66
"build": {
77
"beforeDevCommand": "pnpm dev",
@@ -28,7 +28,7 @@
2828
"active": true,
2929
"targets": "all",
3030
"android": {
31-
"versionCode": 24
31+
"versionCode": 25
3232
},
3333
"icon": [
3434
"icons/32x32.png",

infrastructure/eid-wallet/src/lib/global/controllers/evault.ts

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,33 +158,39 @@ export class VaultController {
158158
/**
159159
* Sync public key to eVault core via wallet-sdk.
160160
* SDK checks /whois and skips PATCH if current key already in certs; otherwise PATCHes /public-key.
161+
* Returns true if the sync succeeded, false otherwise.
161162
*/
162-
async syncPublicKey(eName: string): Promise<void> {
163+
async syncPublicKey(
164+
eName: string,
165+
keyId = "default",
166+
context = "onboarding",
167+
): Promise<boolean> {
163168
if (!this.#walletSdkAdapter) {
164169
console.warn(
165170
"Wallet SDK adapter not available, cannot sync public key",
166171
);
167-
return;
172+
return false;
168173
}
169174
const vault = await this.vault;
170175
if (!vault?.uri) {
171176
console.warn("No vault URI available, cannot sync public key");
172-
return;
177+
return false;
173178
}
174179
try {
175180
await syncPublicKeyToEvault(this.#walletSdkAdapter, {
176181
evaultUri: vault.uri,
177182
eName,
178-
keyId: "default",
179-
context: "onboarding",
183+
keyId,
184+
context,
180185
authToken: PUBLIC_EID_WALLET_TOKEN || null,
181186
registryUrl: PUBLIC_REGISTRY_URL,
182187
});
183188
localStorage.setItem(`publicKeySaved_${eName}`, "true");
184189
console.log(`Public key synced successfully for ${eName}`);
190+
return true;
185191
} catch (error) {
186192
console.error("Failed to sync public key:", error);
187-
// Don't throw - this is a non-critical operation
193+
return false;
188194
}
189195
}
190196

@@ -681,6 +687,64 @@ export class VaultController {
681687
}
682688
}
683689

690+
/**
691+
* Fetch the public key(s) currently registered in the eVault via /whois.
692+
* Decodes JWT payloads from keyBindingCertificates without full verification
693+
* — we only need the public key strings for local comparison.
694+
* Returns empty array on any failure (network, parse, etc).
695+
*/
696+
async fetchRegisteredPublicKeys(eName: string): Promise<string[]> {
697+
const vault = await this.vault;
698+
if (!vault?.uri) {
699+
console.warn(
700+
"No vault URI available, cannot fetch registered keys",
701+
);
702+
return [];
703+
}
704+
705+
try {
706+
const base = vault.uri.replace(/\/$/, "");
707+
const whoisUrl = new URL("/whois", base).toString();
708+
const headers: Record<string, string> = { "X-ENAME": eName };
709+
if (PUBLIC_EID_WALLET_TOKEN) {
710+
headers.Authorization = `Bearer ${PUBLIC_EID_WALLET_TOKEN}`;
711+
}
712+
713+
const response = await axios.get(whoisUrl, {
714+
headers,
715+
timeout: 5000,
716+
});
717+
const certs = response.data?.keyBindingCertificates;
718+
if (!Array.isArray(certs) || certs.length === 0) {
719+
return [];
720+
}
721+
722+
const publicKeys: string[] = [];
723+
for (const jwt of certs) {
724+
try {
725+
const parts = (jwt as string).split(".");
726+
if (parts.length !== 3) continue;
727+
// Decode base64url payload (add padding for atob)
728+
let b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
729+
while (b64.length % 4 !== 0) b64 += "=";
730+
const payload = JSON.parse(atob(b64)) as {
731+
ename?: string;
732+
publicKey?: string;
733+
};
734+
if (payload.ename === eName && payload.publicKey) {
735+
publicKeys.push(payload.publicKey);
736+
}
737+
} catch {
738+
// skip malformed certs
739+
}
740+
}
741+
return publicKeys;
742+
} catch (error) {
743+
console.error("Failed to fetch registered public keys:", error);
744+
return [];
745+
}
746+
}
747+
684748
async clear() {
685749
await this.#store.delete("vault");
686750
}

0 commit comments

Comments
 (0)