Skip to content

Commit 71b3da7

Browse files
committed
fix: move passkey util to new sdk
1 parent 0a7fa33 commit 71b3da7

File tree

5 files changed

+100
-6
lines changed

5 files changed

+100
-6
lines changed

packages/auth-server/components/account-recovery/oidc-recovery-flow/Step3.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
<script setup lang="ts">
1414
import { bytesToHex, type Hex, toHex } from "viem";
15-
// import { base64UrlToUint8Array, getPublicKeyBytesFromPasskeySignature } from "zksync-sso/utils";
15+
import { base64urlToUint8Array, getPublicKeyBytesFromPasskeySignature } from "zksync-sso-4337/utils";
1616
1717
const emit = defineEmits<{
1818
(e: "done", passkey: PasskeyData): void;
@@ -44,7 +44,7 @@ async function getNewPasskey(): Promise<PasskeyData> {
4444
}
4545
4646
return {
47-
credentialId: toHex(base64UrlToUint8Array(credentialId)),
47+
credentialId: toHex(base64urlToUint8Array(credentialId)),
4848
passkeyPubKey: [bytesToHex(buf1), bytesToHex(buf2)],
4949
};
5050
}

packages/auth-server/composables/useRecoveryGuardian.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { Account, Address, Chain, Hex, Transport, WalletClient } from "viem";
22
import { encodeAbiParameters, keccak256, pad, parseAbiParameters, toHex } from "viem";
33
import { waitForTransactionReceipt } from "viem/actions";
4-
import { getPublicKeyBytesFromPasskeySignature } from "zksync-sso";
5-
import { base64urlToUint8Array } from "zksync-sso-4337/utils";
4+
import { base64urlToUint8Array, getPublicKeyBytesFromPasskeySignature } from "zksync-sso-4337/utils";
65

76
import { GuardianExecutorAbi, RecoveryType } from "~/abi/GuardianExecutorAbi";
87

packages/auth-server/pages/recovery/guardian/(actions)/confirm-recovery.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
<script setup lang="ts">
107107
import { useAppKitAccount } from "@reown/appkit/vue";
108108
import { type Address, hexToBytes, isAddressEqual, keccak256, toHex } from "viem";
109-
// import { base64UrlToUint8Array } from "zksync-sso/utils";
109+
import { base64urlToUint8Array } from "zksync-sso-4337/utils";
110110
import { z } from "zod";
111111
112112
import { uint8ArrayToHex } from "@/utils/formatters";
@@ -168,7 +168,7 @@ const recoveryParams = computedAsync(async () => RecoveryParamsSchema.parseAsync
168168
const recoveryCompleted = computedAsync(async () => {
169169
if (!recoveryParams.value?.accountAddress) return false;
170170
const result = await getRecovery(recoveryParams.value.accountAddress);
171-
return result?.hashedCredentialId === keccak256(toHex(base64UrlToUint8Array(recoveryParams.value.credentialId)));
171+
return result?.hashedCredentialId === keccak256(toHex(base64urlToUint8Array(recoveryParams.value.credentialId)));
172172
});
173173
174174
const guardians = computedAsync(async () => {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { Buffer } from "buffer";
2+
3+
enum COSEKEYS {
4+
kty = 1, // Key Type
5+
alg = 3, // Algorithm
6+
crv = -1, // Curve for EC keys
7+
x = -2, // X coordinate for EC keys
8+
y = -3, // Y coordinate for EC keys
9+
}
10+
11+
type COSEPublicKeyMap = Map<COSEKEYS, number | Buffer>;
12+
13+
function decodeMap(buffer: Buffer): COSEPublicKeyMap {
14+
const map = new Map<COSEKEYS, number | Buffer>();
15+
let offset = 1; // Start after the map header
16+
17+
const mapHeader = buffer[0];
18+
const mapSize = mapHeader & 0x1f; // Number of pairs
19+
20+
for (let i = 0; i < mapSize; i++) {
21+
const [key, keyLength] = decodeInt(buffer, offset);
22+
offset += keyLength;
23+
24+
const [value, valueLength] = decodeValue(buffer, offset);
25+
offset += valueLength;
26+
27+
map.set(key as COSEKEYS, value);
28+
}
29+
30+
return map;
31+
}
32+
33+
function decodeInt(buffer: Buffer, offset: number): [number, number] {
34+
const intByte = buffer[offset];
35+
36+
if (intByte < 24) {
37+
// Small positive integer (0–23)
38+
return [intByte, 1];
39+
} else if (intByte === 0x18) {
40+
// 1-byte unsigned integer
41+
return [buffer[offset + 1], 2];
42+
} else if (intByte === 0x19) {
43+
// 2-byte unsigned integer
44+
return [buffer.readUInt16BE(offset + 1), 3];
45+
} else if (intByte >= 0x20 && intByte <= 0x37) {
46+
// Small negative integer (-1 to -24)
47+
return [-(intByte - 0x20) - 1, 1];
48+
} else if (intByte === 0x38) {
49+
// 1-byte negative integer
50+
return [-1 - buffer[offset + 1], 2];
51+
} else if (intByte === 0x39) {
52+
// 2-byte negative integer
53+
return [-1 - buffer.readUInt16BE(offset + 1), 3];
54+
} else {
55+
throw new Error("Unsupported integer format");
56+
}
57+
}
58+
59+
function decodeBytes(buffer: Buffer, offset: number): [Buffer, number] {
60+
const lengthByte = buffer[offset];
61+
if (lengthByte >= 0x40 && lengthByte <= 0x57) {
62+
const length = lengthByte - 0x40;
63+
return [buffer.slice(offset + 1, offset + 1 + length), length + 1];
64+
} else if (lengthByte === 0x58) {
65+
// Byte array with 1-byte length prefix
66+
const length = buffer[offset + 1];
67+
return [buffer.slice(offset + 2, offset + 2 + length), length + 2];
68+
} else {
69+
throw new Error("Unsupported byte format");
70+
}
71+
}
72+
73+
function decodeValue(buffer: Buffer, offset: number): [number | Buffer, number] {
74+
const type = buffer[offset];
75+
if (type >= 0x40 && type <= 0x5f) {
76+
// Byte array
77+
return decodeBytes(buffer, offset);
78+
} else {
79+
return decodeInt(buffer, offset);
80+
}
81+
}
82+
83+
/**
84+
* Decodes a CBOR-encoded COSE public key (from WebAuthn credential) and returns the x,y coordinates.
85+
* @param publicPasskey - CBOR-encoded COSE public key as Uint8Array
86+
* @returns Tuple of [x, y] coordinates as Buffers
87+
*/
88+
export const getPublicKeyBytesFromPasskeySignature = (publicPasskey: Uint8Array): [Buffer, Buffer] => {
89+
const cosePublicKey = decodeMap(Buffer.from(publicPasskey)); // Decodes CBOR-encoded COSE key
90+
const x = cosePublicKey.get(COSEKEYS.x) as Buffer;
91+
const y = cosePublicKey.get(COSEKEYS.y) as Buffer;
92+
93+
return [Buffer.from(x), Buffer.from(y)];
94+
};

packages/sdk-4337/src/client/passkey/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export {
88
type PasskeyClientActions,
99
passkeyClientActions,
1010
} from "./client-actions.js";
11+
export { getPublicKeyBytesFromPasskeySignature } from "./cose.js";
1112
export {
1213
base64urlToUint8Array,
1314
type CreateCredentialOptions,

0 commit comments

Comments
 (0)