phygital-token-sdk 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,8 +12,6 @@ pnpm add phygital-token-sdk @solana/kit
12
12
 
13
13
  ## Off-chain authentication
14
14
 
15
- The authenticator uses the compressed secp256r1 **public key** as the WebAuthn `credential.id`.
16
-
17
15
  ```ts
18
16
  import { createSolanaRpc } from "@solana/kit";
19
17
  import {
@@ -23,11 +21,13 @@ import {
23
21
  fetchPhygitalToken,
24
22
  } from "phygital-token-sdk";
25
23
 
24
+ const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
25
+
26
26
  // Server: issue a short-lived challenge
27
27
  const message = crypto.randomUUID();
28
28
 
29
- // Client: native NFC modal
30
- const response = await startAuthentication(message);
29
+ // Client: native NFC modal (rpc required for placeholder recovery)
30
+ const response = await startAuthentication(message, rpc);
31
31
 
32
32
  // Server: check the signature (no RPC)
33
33
  const { isVerified, secp256r1PublicKey } = verifyResponse({
@@ -36,7 +36,6 @@ const { isVerified, secp256r1PublicKey } = verifyResponse({
36
36
  });
37
37
 
38
38
  if (isVerified) {
39
- const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
40
39
  const { data } = await fetchPhygitalToken(
41
40
  rpc,
42
41
  await findPhygitalTokenPda(secp256r1PublicKey),
@@ -45,6 +44,12 @@ if (isVerified) {
45
44
  }
46
45
  ```
47
46
 
47
+ Native / kiosk readers: pass `transceive` in the third argument — browser WebAuthn (and `rpc`) is skipped.
48
+
49
+ ```ts
50
+ const response = await startAuthentication(message, rpc, { transceive });
51
+ ```
52
+
48
53
  ## On-chain `verify` (CPI)
49
54
 
50
55
  Use this when **your program** needs a possession proof. Your program CPIs `verify` with `VerifyCpiBuilder`.
@@ -54,22 +59,25 @@ The tap uses your `messageHash` (32 bytes) as the WebAuthn challenge. Hash with
54
59
  ### Client (TypeScript)
55
60
 
56
61
  ```ts
62
+ import { createSolanaRpc } from "@solana/kit";
57
63
  import {
58
64
  buildMessageHash,
59
65
  authenticatePasskeyForSecp256r1Verify,
60
66
  buildSecp256r1VerifyInstruction,
61
67
  } from "phygital-token-sdk";
62
68
 
69
+ const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
63
70
  const messageHash = buildMessageHash(message);
64
71
  const tap = await authenticatePasskeyForSecp256r1Verify({
72
+ rpc,
65
73
  messageHash,
66
74
  });
67
75
  const { secp256r1VerifyInstruction, phygitalTokenPda, secp256r1VerifyArgs } =
68
- await buildSecp256r1VerifyInstruction(tap);
76
+ buildSecp256r1VerifyInstruction(tap);
69
77
 
70
78
  const instructions = [
71
79
  secp256r1VerifyInstruction, // immediately before your instruction
72
- yourProgramInstruction, // use phygitalTokenPda & secp256r1VerifyArgs as inputs when generating your program instruction
80
+ yourProgramInstruction, // use phygitalTokenPda & secp256r1VerifyArgs as inputs
73
81
  ];
74
82
  ```
75
83
 
@@ -1,9 +1,13 @@
1
1
  import { type Address, type Instruction, type Rpc, type SolanaRpcApi, type TransactionSigner } from "@solana/kit";
2
2
  import { type AuthenticationResponseJSON } from "../utils/passkey/webauthn.js";
3
3
  import { type Secp256r1VerifyEntry } from "../utils/passkey/secp256r1.js";
4
+ import type { Base64URLString } from "../utils/passkey/webauthn.js";
4
5
  export type TransferSession = {
5
6
  rpc: Rpc<SolanaRpcApi>;
7
+ /** Phygital token PDA derived from {@link secp256r1Pubkey}. */
6
8
  phygitalToken: Address;
9
+ /** Base64url compressed secp256r1 passkey public key for the physical token. */
10
+ secp256r1Pubkey: Base64URLString;
7
11
  slotHash: Uint8Array;
8
12
  slotNumber: bigint;
9
13
  challenge: Uint8Array;
@@ -16,15 +20,22 @@ export type TransferSession = {
16
20
  * {@link completeTransfer}.
17
21
  *
18
22
  * @param input.rpc - Kit `Rpc`. Convert a web3.js Connection with `toRpc`.
19
- * @param input.phygitalToken - Kit `Address` (phygital token PDA). Convert a PublicKey with `toAddress`.
20
- * @param input.rpId - Relying party ID. Defaults to `window.location.hostname`.
23
+ * @param input.secp256r1Pubkey - Base64url compressed secp256r1 public key for the
24
+ * physical token (same shape as `verifyResponse().secp256r1PublicKey`). The phygital
25
+ * token PDA is derived via {@link findPhygitalTokenPda}.
26
+ * @param input.rpId - Relying party ID for the NFC tap. Defaults to `window.location.hostname`.
21
27
  */
22
28
  export declare function beginTransfer(input: {
23
29
  rpc: Rpc<SolanaRpcApi>;
24
- phygitalToken: Address;
30
+ secp256r1Pubkey: Base64URLString;
25
31
  rpId?: string;
26
32
  }): Promise<TransferSession>;
27
- /** Prompts the physical token passkey (WebAuthn / NFC tap). */
33
+ /**
34
+ * Prompts the physical token passkey (WebAuthn / NFC tap).
35
+ * Passes {@link TransferSession.secp256r1Pubkey} in `allowCredentials` for the browser UI.
36
+ * If the platform echoes a random placeholder id, recovery disambiguates by checking
37
+ * which candidate has an initialized PhygitalToken PDA on-chain.
38
+ */
28
39
  export declare function authenticatePasskeyForTransfer(session: TransferSession): Promise<AuthenticationResponseJSON>;
29
40
  /**
30
41
  * Builds the two on-chain instructions after passkey authentication.
@@ -1 +1 @@
1
- {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../src/instructions/transfer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,GAAG,EACR,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAIL,KAAK,0BAA0B,EAChC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAC;AAKvC,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,UAAU,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE;IACzC,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,eAAe,CAAC,CAe3B;AAED,+DAA+D;AAC/D,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,0BAA0B,CAAC,CAIrC;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,0BAA0B,EACpC,SAAS,EAAE,iBAAiB,EAC5B,6BAA6B,CAAC,EAAE,oBAAoB,EAAE,GACrD,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBxB"}
1
+ {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../src/instructions/transfer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,GAAG,EACR,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAIL,KAAK,0BAA0B,EAChC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAC;AAKvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACvB,+DAA+D;IAC/D,aAAa,EAAE,OAAO,CAAC;IACvB,gFAAgF;IAChF,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,UAAU,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE;IACzC,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,eAAe,CAAC,CAiB3B;AAED;;;;;GAKG;AACH,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,0BAA0B,CAAC,CASrC;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,0BAA0B,EACpC,SAAS,EAAE,iBAAiB,EAC5B,6BAA6B,CAAC,EAAE,oBAAoB,EAAE,GACrD,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBxB"}
@@ -4,6 +4,7 @@ import { buildSecp256r1VerifyInstructionFromWebAuthnResponse, buildTransferChall
4
4
  import { getLatestSlotHash } from "../utils/slotHash.js";
5
5
  import { getTransferOwnershipInstruction } from "../generated/index.js";
6
6
  import { parseSecp256r1Pubkey } from "../utils/parseSecp256r1Pubkey.js";
7
+ import { findPhygitalTokenPda } from "../utils/pdas/token.js";
7
8
  /**
8
9
  * Prepares a transfer session with slot-bound challenge data.
9
10
  * Recipient is chosen at wallet confirmation and must sign the transfer transaction.
@@ -11,27 +12,36 @@ import { parseSecp256r1Pubkey } from "../utils/parseSecp256r1Pubkey.js";
11
12
  * {@link completeTransfer}.
12
13
  *
13
14
  * @param input.rpc - Kit `Rpc`. Convert a web3.js Connection with `toRpc`.
14
- * @param input.phygitalToken - Kit `Address` (phygital token PDA). Convert a PublicKey with `toAddress`.
15
- * @param input.rpId - Relying party ID. Defaults to `window.location.hostname`.
15
+ * @param input.secp256r1Pubkey - Base64url compressed secp256r1 public key for the
16
+ * physical token (same shape as `verifyResponse().secp256r1PublicKey`). The phygital
17
+ * token PDA is derived via {@link findPhygitalTokenPda}.
18
+ * @param input.rpId - Relying party ID for the NFC tap. Defaults to `window.location.hostname`.
16
19
  */
17
20
  export async function beginTransfer(input) {
21
+ const phygitalToken = await findPhygitalTokenPda(input.secp256r1Pubkey);
18
22
  const { slotHash, slotNumber } = await getLatestSlotHash(input.rpc);
19
23
  const challenge = await buildTransferChallenge({
20
- phygitalToken: input.phygitalToken,
24
+ phygitalToken,
21
25
  slotHash,
22
26
  });
23
27
  return {
24
28
  rpc: input.rpc,
25
- phygitalToken: input.phygitalToken,
29
+ secp256r1Pubkey: input.secp256r1Pubkey,
30
+ phygitalToken,
26
31
  slotHash,
27
32
  slotNumber,
28
33
  challenge,
29
34
  rpId: input.rpId ?? window.location.hostname,
30
35
  };
31
36
  }
32
- /** Prompts the physical token passkey (WebAuthn / NFC tap). */
37
+ /**
38
+ * Prompts the physical token passkey (WebAuthn / NFC tap).
39
+ * Passes {@link TransferSession.secp256r1Pubkey} in `allowCredentials` for the browser UI.
40
+ * If the platform echoes a random placeholder id, recovery disambiguates by checking
41
+ * which candidate has an initialized PhygitalToken PDA on-chain.
42
+ */
33
43
  export async function authenticatePasskeyForTransfer(session) {
34
- return authenticateWithWebauthn(nfcWebAuthnRequestOptions(bufferToBase64URLString(session.challenge), session.rpId));
44
+ return authenticateWithWebauthn(nfcWebAuthnRequestOptions(bufferToBase64URLString(session.challenge), session.rpId, session.secp256r1Pubkey), session.rpc);
35
45
  }
36
46
  /**
37
47
  * Builds the two on-chain instructions after passkey authentication.
@@ -40,7 +50,7 @@ export async function authenticatePasskeyForTransfer(session) {
40
50
  * @param recipient - Kit `TransactionSigner`. Convert a web3.js Keypair with `toTransactionSigner`.
41
51
  */
42
52
  export async function completeTransfer(session, response, recipient, existingSecp256r1VerifyInputs) {
43
- const { secp256r1VerifyInstruction, signedMessageIndex, clientDataJson } = await buildSecp256r1VerifyInstructionFromWebAuthnResponse({
53
+ const { secp256r1VerifyInstruction, signedMessageIndex, clientDataJson } = buildSecp256r1VerifyInstructionFromWebAuthnResponse({
44
54
  response,
45
55
  secp256r1PublicKey: parseSecp256r1Pubkey(response.id),
46
56
  existingSecp256r1VerifyInputs,
@@ -1 +1 @@
1
- {"version":3,"file":"transfer.js","sourceRoot":"","sources":["../../src/instructions/transfer.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,GAE1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,mDAAmD,EACnD,sBAAsB,GAEvB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAWxE;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAInC;IACC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC;QAC7C,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,QAAQ;KACT,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,QAAQ;QACR,UAAU;QACV,SAAS;QACT,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ;KAC7C,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,OAAwB;IAExB,OAAO,wBAAwB,CAC7B,yBAAyB,CAAC,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CACpF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAwB,EACxB,QAAoC,EACpC,SAA4B,EAC5B,6BAAsD;IAEtD,MAAM,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,cAAc,EAAE,GACtE,MAAM,mDAAmD,CAAC;QACxD,QAAQ;QACR,kBAAkB,EAAE,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,6BAA6B;KAC9B,CAAC,CAAC;IAEL,MAAM,iBAAiB,GAAG,+BAA+B,CAAC;QACxD,SAAS;QACT,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,mBAAmB,EAAE;YACnB,uBAAuB,EAAE,CAAC,CAAC;YAC3B,kBAAkB;YAClB,cAAc;SACf;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"transfer.js","sourceRoot":"","sources":["../../src/instructions/transfer.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,GAE1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,mDAAmD,EACnD,sBAAsB,GAEvB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAe9D;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAInC;IACC,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACxE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC;QAC7C,aAAa;QACb,QAAQ;KACT,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,aAAa;QACb,QAAQ;QACR,UAAU;QACV,SAAS;QACT,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ;KAC7C,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,OAAwB;IAExB,OAAO,wBAAwB,CAC7B,yBAAyB,CACvB,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,EAC1C,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,eAAe,CACxB,EACD,OAAO,CAAC,GAAG,CACZ,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAwB,EACxB,QAAoC,EACpC,SAA4B,EAC5B,6BAAsD;IAEtD,MAAM,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,cAAc,EAAE,GACtE,mDAAmD,CAAC;QAClD,QAAQ;QACR,kBAAkB,EAAE,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,6BAA6B;KAC9B,CAAC,CAAC;IAEL,MAAM,iBAAiB,GAAG,+BAA+B,CAAC;QACxD,SAAS;QACT,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,mBAAmB,EAAE;YACnB,uBAAuB,EAAE,CAAC,CAAC;YAC3B,kBAAkB;YAClB,cAAc;SACf;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,CAAC;AACzD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { type AuthenticationResponseJSON } from "../utils/passkey/webauthn.js";
2
- import type { Address, Instruction } from "@solana/kit";
2
+ import type { Address, Instruction, Rpc, SolanaRpcApi } from "@solana/kit";
3
3
  import { type Secp256r1VerifyEntry } from "../utils/passkey/secp256r1.js";
4
4
  import { type Secp256r1VerifyArgsArgs } from "../generated/index.js";
5
5
  /** SHA-256 `message` to a 32-byte digest for on-chain `verify`. */
@@ -11,12 +11,14 @@ export declare function buildMessageHash(message: Uint8Array): Uint8Array;
11
11
  * digest your program must pass to `VerifyCpiBuilder.message_hash`. Hash with
12
12
  * {@link buildMessageHash} first.
13
13
  *
14
+ * @param input.rpc - Kit `Rpc`. Used when the platform echoes a placeholder credential id.
14
15
  * @param input.messageHash - SHA-256 of the message you bind on-chain (32 bytes).
15
16
  * @param input.rpId - WebAuthn relying party for the **browser tap** only.
16
17
  * Defaults to `window.location.hostname`. On-chain `expected_rp_id` /
17
18
  * `expected_origins` are set on your CPI, not here.
18
19
  */
19
20
  export declare function authenticatePasskeyForSecp256r1Verify(input: {
21
+ rpc: Rpc<SolanaRpcApi>;
20
22
  messageHash: Uint8Array;
21
23
  rpId?: string;
22
24
  }): Promise<AuthenticationResponseJSON>;
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/instructions/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,0BAA0B,EAIhC,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAKrE,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,CAEhE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qCAAqC,CAAC,KAAK,EAAE;IACjE,WAAW,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAOtC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,0BAA0B,EACpC,6BAA6B,CAAC,EAAE,oBAAoB,EAAE,EACtD,uBAAuB,SAAK,GAC3B,OAAO,CAAC;IACT,0BAA0B,EAAE,WAAW,CAAC;IACxC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,mBAAmB,EAAE,uBAAuB,CAAC;CAC9C,CAAC,CAkBD"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/instructions/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,0BAA0B,EAIhC,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAKrE,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,CAEhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,qCAAqC,CAAC,KAAK,EAAE;IACjE,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACvB,WAAW,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAQtC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,0BAA0B,EACpC,6BAA6B,CAAC,EAAE,oBAAoB,EAAE,EACtD,uBAAuB,SAAK,GAC3B,OAAO,CAAC;IACT,0BAA0B,EAAE,WAAW,CAAC;IACxC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,mBAAmB,EAAE,uBAAuB,CAAC;CAC9C,CAAC,CAkBD"}
@@ -15,13 +15,14 @@ export function buildMessageHash(message) {
15
15
  * digest your program must pass to `VerifyCpiBuilder.message_hash`. Hash with
16
16
  * {@link buildMessageHash} first.
17
17
  *
18
+ * @param input.rpc - Kit `Rpc`. Used when the platform echoes a placeholder credential id.
18
19
  * @param input.messageHash - SHA-256 of the message you bind on-chain (32 bytes).
19
20
  * @param input.rpId - WebAuthn relying party for the **browser tap** only.
20
21
  * Defaults to `window.location.hostname`. On-chain `expected_rp_id` /
21
22
  * `expected_origins` are set on your CPI, not here.
22
23
  */
23
24
  export async function authenticatePasskeyForSecp256r1Verify(input) {
24
- return authenticateWithWebauthn(nfcWebAuthnRequestOptions(bufferToBase64URLString(input.messageHash), input.rpId ?? window.location.hostname));
25
+ return authenticateWithWebauthn(nfcWebAuthnRequestOptions(bufferToBase64URLString(input.messageHash), input.rpId ?? window.location.hostname), input.rpc);
25
26
  }
26
27
  /**
27
28
  * After the tap: secp256r1_verify instruction to prepend, plus the phygital
@@ -39,7 +40,7 @@ export async function authenticatePasskeyForSecp256r1Verify(input) {
39
40
  export async function buildSecp256r1VerifyInstruction(response, existingSecp256r1VerifyInputs, verifyArgsRelativeIndex = -1) {
40
41
  const secp256r1PublicKey = parseSecp256r1Pubkey(response.id);
41
42
  const phygitalTokenPda = await findPhygitalTokenPda(secp256r1PublicKey);
42
- const { secp256r1VerifyInstruction, signedMessageIndex, clientDataJson } = await buildSecp256r1VerifyInstructionFromWebAuthnResponse({
43
+ const { secp256r1VerifyInstruction, signedMessageIndex, clientDataJson } = buildSecp256r1VerifyInstructionFromWebAuthnResponse({
43
44
  secp256r1PublicKey,
44
45
  response,
45
46
  existingSecp256r1VerifyInputs,
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/instructions/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mDAAmD,GAEpD,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAgC,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,OAAmB;IAClD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,qCAAqC,CAAC,KAG3D;IACC,OAAO,wBAAwB,CAC7B,yBAAyB,CACvB,uBAAuB,CAAC,KAAK,CAAC,WAAW,CAAC,EAC1C,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CACvC,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,QAAoC,EACpC,6BAAsD,EACtD,uBAAuB,GAAG,CAAC,CAAC;IAM5B,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;IACxE,MAAM,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,cAAc,EAAE,GACtE,MAAM,mDAAmD,CAAC;QACxD,kBAAkB;QAClB,QAAQ;QACR,6BAA6B;KAC9B,CAAC,CAAC;IACL,OAAO;QACL,0BAA0B;QAC1B,gBAAgB;QAChB,mBAAmB,EAAE;YACnB,uBAAuB;YACvB,kBAAkB;YAClB,cAAc;SACf;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/instructions/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mDAAmD,GAEpD,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAgC,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,OAAmB;IAClD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,qCAAqC,CAAC,KAI3D;IACC,OAAO,wBAAwB,CAC7B,yBAAyB,CACvB,uBAAuB,CAAC,KAAK,CAAC,WAAW,CAAC,EAC1C,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CACvC,EACD,KAAK,CAAC,GAAG,CACV,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,QAAoC,EACpC,6BAAsD,EACtD,uBAAuB,GAAG,CAAC,CAAC;IAM5B,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;IACxE,MAAM,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,cAAc,EAAE,GACtE,mDAAmD,CAAC;QAClD,kBAAkB;QAClB,QAAQ;QACR,6BAA6B;KAC9B,CAAC,CAAC;IACL,OAAO;QACL,0BAA0B;QAC1B,gBAAgB;QAChB,mBAAmB,EAAE;YACnB,uBAAuB;YACvB,kBAAkB;YAClB,cAAc;SACf;KACF,CAAC;AACJ,CAAC"}
@@ -1,4 +1,4 @@
1
- import { base64URLStringToBuffer } from "./passkey/internal.js";
1
+ import { base64URLStringToBuffer } from "./passkey/webauthn.js";
2
2
  /**
3
3
  * Parse a base64url-encoded 33-byte compressed secp256r1 value
4
4
  * (passkey public key **or** chip identifier — both use the same wire shape).
@@ -1,31 +1,16 @@
1
1
  import { type AuthenticationResponseJSON } from "./webauthn.js";
2
- export { base64URLStringToBuffer } from "./webauthn.js";
3
- /**
4
- * Normalizes a raw 64-byte `r||s` P-256 ECDSA signature to its canonical
5
- * low-S form (`s <= n/2`).
6
- *
7
- * Hardware signers — NFC secure elements and platform authenticators — often
8
- * emit high-S signatures. They are valid ECDSA but non-canonical, and both
9
- * `@noble/curves` (default `lowS: true`) and Solana's secp256r1 precompile
10
- * reject them. Always run a raw signature through this before verifying or
11
- * before building an on-chain secp256r1 verify instruction.
12
- */
13
- export declare function normalizeSignatureToLowS(signature: Uint8Array): Uint8Array;
14
2
  export declare function convertSignatureDERtoRS(signature: Uint8Array): Uint8Array;
15
- export declare function getClientDataJsonBytes(authResponse: AuthenticationResponseJSON): Uint8Array;
16
- export declare function getSecp256r1Message(authResponse: AuthenticationResponseJSON): Uint8Array;
17
- /**
18
- * Recover a compressed secp256r1 public key from a WebAuthn assertion signature
19
- * and the signed message (`authenticatorData || SHA-256(clientDataJSON)`).
20
- *
21
- * WebAuthn signatures omit the ECDSA recovery id, so recids 0–3 are tried until
22
- * a recovered key verifies the assertion.
23
- */
24
- export declare function recoverSecp256r1PublicKey(signature: Uint8Array, message: Uint8Array): Uint8Array;
3
+ /** WebAuthn signed payload: `authenticatorData || SHA-256(clientDataJSON)`. */
4
+ export declare function buildSecp256r1Message(authenticatorData: Uint8Array, clientDataJSON: Uint8Array): Uint8Array;
5
+ /** DER signature and signed message bytes from a WebAuthn assertion. */
6
+ export declare function parseWebAuthnAssertion(response: AuthenticationResponseJSON): {
7
+ signature: Uint8Array;
8
+ message: Uint8Array;
9
+ };
10
+ export declare function recoverSecp256r1PublicKeyCandidates(signature: Uint8Array, message: Uint8Array): Uint8Array[];
25
11
  export declare function parseWebAuthnClientData(clientDataJSON: string): {
26
12
  challenge: string;
27
13
  origin: string;
28
14
  crossOrigin: boolean;
29
- truncatedClientDataJson: Uint8Array<ArrayBuffer>;
30
15
  };
31
16
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/utils/passkey/internal.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAkCxD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAoB1E;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAEzE;AA2DD,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,0BAA0B,GACvC,UAAU,CAEZ;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,0BAA0B,GACvC,UAAU,CASZ;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,UAAU,GAClB,UAAU,CAkBZ;AAED,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM;IAK1D,SAAS;IACT,MAAM;IACN,WAAW;IACX,uBAAuB;EAE1B"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/utils/passkey/internal.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,eAAe,CAAC;AAgDvB,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAEzE;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,iBAAiB,EAAE,UAAU,EAC7B,cAAc,EAAE,UAAU,GACzB,UAAU,CAQZ;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,0BAA0B,GAAG;IAC5E,SAAS,EAAE,UAAU,CAAC;IACtB,OAAO,EAAE,UAAU,CAAC;CACrB,CAUA;AAED,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,UAAU,GAClB,UAAU,EAAE,CAwBd;AAiBD,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;CACtB,CAeA"}
@@ -1,147 +1,96 @@
1
1
  import { p256 } from "@noble/curves/nist.js";
2
2
  import { sha256 } from "@noble/hashes/sha2.js";
3
3
  import { base64URLStringToBuffer, } from "./webauthn.js";
4
- export { base64URLStringToBuffer } from "./webauthn.js";
5
- function uint8ArrayToHex(bytes) {
6
- return Array.from(bytes)
7
- .map((b) => b.toString(16).padStart(2, "0"))
8
- .join("");
4
+ const CURVE_ORDER = p256.Point.CURVE().n;
5
+ function bytesEqual(a, b) {
6
+ return a.length === b.length && a.every((byte, index) => byte === b[index]);
9
7
  }
10
- function hexToUint8Array(hex) {
11
- const bytes = new Uint8Array(hex.length / 2);
12
- for (let i = 0; i < bytes.length; i += 1) {
13
- bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
14
- }
15
- return bytes;
8
+ function isDerEcdsaSignature(signature) {
9
+ return signature.length >= 2 && signature[0] === 0x30;
16
10
  }
17
- function extractAdditionalFields(clientData) {
18
- const knownKeys = new Set(["type", "challenge", "origin", "crossOrigin"]);
19
- const remaining = {};
20
- for (const key in clientData) {
21
- if (!knownKeys.has(key)) {
22
- remaining[key] = clientData[key];
23
- }
11
+ function parseWebAuthnSignature(signature) {
12
+ if (signature.length === 64) {
13
+ return {
14
+ noble: p256.Signature.fromBytes(signature, "compact"),
15
+ compact: signature,
16
+ };
24
17
  }
25
- if (Object.keys(remaining).length === 0) {
26
- return new Uint8Array();
18
+ if (isDerEcdsaSignature(signature)) {
19
+ const noble = p256.Signature.fromBytes(signature, "der");
20
+ return { noble, compact: noble.toBytes("compact") };
27
21
  }
28
- const serialized = JSON.stringify(remaining);
29
- return new Uint8Array(new TextEncoder().encode(serialized.slice(1, -1)));
22
+ throw new Error("expected 64-byte compact or DER ECDSA signature");
30
23
  }
31
- /**
32
- * Normalizes a raw 64-byte `r||s` P-256 ECDSA signature to its canonical
33
- * low-S form (`s <= n/2`).
34
- *
35
- * Hardware signers — NFC secure elements and platform authenticators — often
36
- * emit high-S signatures. They are valid ECDSA but non-canonical, and both
37
- * `@noble/curves` (default `lowS: true`) and Solana's secp256r1 precompile
38
- * reject them. Always run a raw signature through this before verifying or
39
- * before building an on-chain secp256r1 verify instruction.
40
- */
41
- export function normalizeSignatureToLowS(signature) {
24
+ function normalizeSignatureToLowS(signature) {
42
25
  if (signature.length !== 64) {
43
26
  throw new Error(`expected 64-byte raw r||s signature, got ${signature.length} bytes`);
44
27
  }
45
- const order = p256.Point.CURVE().n;
46
- const halfOrder = order >> 1n;
47
- const sBig = BigInt(`0x${uint8ArrayToHex(signature.slice(32, 64))}`);
48
- if (sBig <= halfOrder) {
28
+ const sig = p256.Signature.fromBytes(signature, "compact");
29
+ if (!sig.hasHighS()) {
49
30
  return signature;
50
31
  }
51
- const sLow = order - sBig;
52
- const sPad = hexToUint8Array(sLow.toString(16).padStart(64, "0"));
53
- const normalized = new Uint8Array(64);
54
- normalized.set(signature.slice(0, 32), 0);
55
- normalized.set(sPad, 32);
56
- return normalized;
32
+ return new p256.Signature(sig.r, CURVE_ORDER - sig.s).toBytes("compact");
57
33
  }
58
34
  export function convertSignatureDERtoRS(signature) {
59
- return normalizeSignatureToLowS(parseSignatureToRS(signature));
60
- }
61
- function parseSignatureToRS(signature) {
62
- if (signature.length === 64) {
63
- return signature;
64
- }
65
- if (signature[0] !== 0x30) {
66
- throw new Error("Invalid DER sequence");
67
- }
68
- const totalLength = signature[1];
69
- let offset = 2;
70
- if (totalLength > 0x80) {
71
- const lengthBytes = totalLength & 0x7f;
72
- offset += lengthBytes;
73
- }
74
- if (signature[offset] !== 0x02) {
75
- throw new Error("Expected INTEGER for r");
76
- }
77
- const rLen = signature[offset + 1];
78
- const rStart = offset + 2;
79
- const r = signature.slice(rStart, rStart + rLen);
80
- offset = rStart + rLen;
81
- if (signature[offset] !== 0x02) {
82
- throw new Error("Expected INTEGER for s");
83
- }
84
- const sLen = signature[offset + 1];
85
- const sStart = offset + 2;
86
- const s = signature.slice(sStart, sStart + sLen);
87
- const rStripped = r[0] === 0x00 && r.length > 32 ? r.slice(1) : r;
88
- const sStripped = s[0] === 0x00 && s.length > 32 ? s.slice(1) : s;
89
- if (rStripped.length > 32 || sStripped.length > 32) {
90
- throw new Error("r or s length > 32 bytes");
91
- }
92
- const rawSig = new Uint8Array(64);
93
- rawSig.set(rStripped, 32 - rStripped.length);
94
- rawSig.set(sStripped, 64 - sStripped.length);
95
- return rawSig;
35
+ return normalizeSignatureToLowS(parseWebAuthnSignature(signature).compact);
96
36
  }
97
- function toCompressedPublicKey(point) {
98
- return point.toBytes(true);
99
- }
100
- function signatureFromBytes(signature) {
101
- if (signature.length >= 2 && signature[0] === 0x30) {
102
- return p256.Signature.fromBytes(signature, "der");
103
- }
104
- return p256.Signature.fromBytes(parseSignatureToRS(signature), "compact");
105
- }
106
- export function getClientDataJsonBytes(authResponse) {
107
- return base64URLStringToBuffer(authResponse.response.clientDataJSON);
108
- }
109
- export function getSecp256r1Message(authResponse) {
110
- const clientDataJSON = base64URLStringToBuffer(authResponse.response.clientDataJSON);
111
- const authenticatorData = base64URLStringToBuffer(authResponse.response.authenticatorData);
37
+ /** WebAuthn signed payload: `authenticatorData || SHA-256(clientDataJSON)`. */
38
+ export function buildSecp256r1Message(authenticatorData, clientDataJSON) {
112
39
  const clientDataHash = sha256(clientDataJSON);
113
- return new Uint8Array([...authenticatorData, ...clientDataHash]);
40
+ const message = new Uint8Array(authenticatorData.length + clientDataHash.length);
41
+ message.set(authenticatorData, 0);
42
+ message.set(clientDataHash, authenticatorData.length);
43
+ return message;
44
+ }
45
+ /** DER signature and signed message bytes from a WebAuthn assertion. */
46
+ export function parseWebAuthnAssertion(response) {
47
+ return {
48
+ signature: convertSignatureDERtoRS(base64URLStringToBuffer(response.response.signature)),
49
+ message: buildSecp256r1Message(base64URLStringToBuffer(response.response.authenticatorData), base64URLStringToBuffer(response.response.clientDataJSON)),
50
+ };
114
51
  }
115
- /**
116
- * Recover a compressed secp256r1 public key from a WebAuthn assertion signature
117
- * and the signed message (`authenticatorData || SHA-256(clientDataJSON)`).
118
- *
119
- * WebAuthn signatures omit the ECDSA recovery id, so recids 0–3 are tried until
120
- * a recovered key verifies the assertion.
121
- */
122
- export function recoverSecp256r1PublicKey(signature, message) {
123
- const sig = signatureFromBytes(signature);
124
- const verifyRs = normalizeSignatureToLowS(parseSignatureToRS(signature));
52
+ export function recoverSecp256r1PublicKeyCandidates(signature, message) {
53
+ const parsed = parseWebAuthnSignature(signature);
54
+ const digest = sha256(message);
55
+ const verifySignature = normalizeSignatureToLowS(parsed.compact);
56
+ const candidates = [];
125
57
  for (let recoveryId = 0; recoveryId < 4; recoveryId += 1) {
126
58
  try {
127
- const publicKey = toCompressedPublicKey(sig.addRecoveryBit(recoveryId).recoverPublicKey(message));
128
- if (p256.verify(verifyRs, message, publicKey, { prehash: false })) {
129
- return publicKey;
59
+ const publicKey = parsed.noble
60
+ .addRecoveryBit(recoveryId)
61
+ .recoverPublicKey(digest)
62
+ .toBytes(true);
63
+ if (!p256.verify(verifySignature, message, publicKey)) {
64
+ continue;
65
+ }
66
+ if (!candidates.some((candidate) => bytesEqual(candidate, publicKey))) {
67
+ candidates.push(publicKey);
130
68
  }
131
69
  }
132
70
  catch {
133
- // try next recovery id
71
+ // invalid recovery id for this (r, s)
134
72
  }
135
73
  }
136
- throw new Error("Failed to recover secp256r1 public key from signature");
74
+ return candidates;
75
+ }
76
+ function readRequiredClientDataString(value, field) {
77
+ if (typeof value !== "string" || value.length === 0) {
78
+ throw new Error(`WebAuthn clientDataJSON.${field} must be a non-empty string.`);
79
+ }
80
+ return value;
137
81
  }
138
82
  export function parseWebAuthnClientData(clientDataJSON) {
139
- const parsed = JSON.parse(new TextDecoder().decode(base64URLStringToBuffer(clientDataJSON)));
83
+ let parsed;
84
+ try {
85
+ parsed = JSON.parse(new TextDecoder().decode(base64URLStringToBuffer(clientDataJSON)));
86
+ }
87
+ catch {
88
+ throw new Error("WebAuthn clientDataJSON must be valid JSON.");
89
+ }
140
90
  return {
141
- challenge: String(parsed.challenge),
142
- origin: String(parsed.origin),
143
- crossOrigin: Boolean(parsed.crossOrigin),
144
- truncatedClientDataJson: extractAdditionalFields(parsed),
91
+ challenge: readRequiredClientDataString(parsed.challenge, "challenge"),
92
+ origin: readRequiredClientDataString(parsed.origin, "origin"),
93
+ crossOrigin: parsed.crossOrigin === true,
145
94
  };
146
95
  }
147
96
  //# sourceMappingURL=internal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","sourceRoot":"","sources":["../../../src/utils/passkey/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EACL,uBAAuB,GAExB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,SAAS,eAAe,CAAC,KAAiB;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,uBAAuB,CAAC,UAAmC;IAClE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;IAE1E,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,SAAS,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,UAAU,EAAE,CAAC;IAC1B,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7C,OAAO,IAAI,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAAqB;IAC5D,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,4CAA4C,SAAS,CAAC,MAAM,QAAQ,CACrE,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACrE,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;IAC1B,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACtC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1C,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,SAAqB;IAC3D,OAAO,wBAAwB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAqB;IAC/C,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;QACvC,MAAM,IAAI,WAAW,CAAC;IACxB,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAEjD,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElE,IAAI,SAAS,CAAC,MAAM,GAAG,EAAE,IAAI,SAAS,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAE7C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAAC,KAA8C;IAC3E,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAqB;IAC/C,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnD,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,kBAAkB,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,YAAwC;IAExC,OAAO,uBAAuB,CAAC,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,YAAwC;IAExC,MAAM,cAAc,GAAG,uBAAuB,CAC5C,YAAY,CAAC,QAAQ,CAAC,cAAc,CACrC,CAAC;IACF,MAAM,iBAAiB,GAAG,uBAAuB,CAC/C,YAAY,CAAC,QAAQ,CAAC,iBAAiB,CACxC,CAAC;IACF,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;IAC9C,OAAO,IAAI,UAAU,CAAC,CAAC,GAAG,iBAAiB,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACvC,SAAqB,EACrB,OAAmB;IAEnB,MAAM,GAAG,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,wBAAwB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAEzE,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,GAAG,CAAC,EAAE,UAAU,IAAI,CAAC,EAAE,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,qBAAqB,CACrC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CACzD,CAAC;YACF,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;gBAClE,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,cAAsB;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CACvB,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAC,CACvC,CAAC;IAC7B,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;QACnC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7B,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC;QACxC,uBAAuB,EAAE,uBAAuB,CAAC,MAAM,CAAC;KACzD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../../../src/utils/passkey/internal.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { sha256 } from "@noble/hashes/sha2.js";
2
- import { base64URLStringToBuffer } from "../internal.js";
2
+ import { base64URLStringToBuffer } from "../webauthn.js";
3
3
  import { ApduError } from "./errors.js";
4
4
  import { buildCollectedClientDataJSON } from "./clientData.js";
5
5
  function userVerificationToOptionalUvBool(uv) {
@@ -4,22 +4,17 @@ import { type Secp256r1VerifyEntry } from "../../instructions/internal/secp256r1
4
4
  import { SECP256R1_PROGRAM_ADDRESS } from "../consts.js";
5
5
  import type { Secp256r1Pubkey } from "../../generated/index.js";
6
6
  export type { Secp256r1VerifyEntry };
7
- export declare function buildVerifyInputFromWebAuthn(input: {
8
- secp256r1PublicKey: Secp256r1Pubkey;
9
- response: AuthenticationResponseJSON;
10
- }): Secp256r1VerifyEntry;
11
7
  export declare function buildTransferChallenge(input: {
12
8
  phygitalToken: Address;
13
9
  slotHash: Uint8Array;
14
10
  }): Promise<Uint8Array>;
15
- export type WebAuthnSecp256r1Verification = {
16
- signedMessageIndex: number;
17
- secp256r1VerifyInstruction: Instruction<typeof SECP256R1_PROGRAM_ADDRESS>;
18
- clientDataJson: Uint8Array;
19
- };
20
11
  export declare function buildSecp256r1VerifyInstructionFromWebAuthnResponse(input: {
21
12
  secp256r1PublicKey: Secp256r1Pubkey;
22
13
  response: AuthenticationResponseJSON;
23
14
  existingSecp256r1VerifyInputs?: Secp256r1VerifyEntry[];
24
- }): Promise<WebAuthnSecp256r1Verification>;
15
+ }): {
16
+ signedMessageIndex: number;
17
+ secp256r1VerifyInstruction: Instruction<typeof SECP256R1_PROGRAM_ADDRESS>;
18
+ clientDataJson: Uint8Array;
19
+ };
25
20
  //# sourceMappingURL=secp256r1.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"secp256r1.d.ts","sourceRoot":"","sources":["../../../src/utils/passkey/secp256r1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAqB,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EACL,yBAAyB,EAE1B,MAAM,cAAc,CAAC;AAQtB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAiBrC,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,kBAAkB,EAAE,eAAe,CAAC;IACpC,QAAQ,EAAE,0BAA0B,CAAC;CACtC,GAAG,oBAAoB,CAWvB;AAED,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,UAAU,CAAC;CACtB,GAAG,OAAO,CAAC,UAAU,CAAC,CAQtB;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0BAA0B,EAAE,WAAW,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1E,cAAc,EAAE,UAAU,CAAC;CAC5B,CAAC;AAEF,wBAAsB,mDAAmD,CAAC,KAAK,EAAE;IAC/E,kBAAkB,EAAE,eAAe,CAAC;IACpC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,6BAA6B,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACxD,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAazC"}
1
+ {"version":3,"file":"secp256r1.d.ts","sourceRoot":"","sources":["../../../src/utils/passkey/secp256r1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAqB,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EACL,yBAAyB,EAE1B,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,YAAY,EAAE,oBAAoB,EAAE,CAAC;AA8BrC,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,UAAU,CAAC;CACtB,GAAG,OAAO,CAAC,UAAU,CAAC,CAQtB;AAED,wBAAgB,mDAAmD,CAAC,KAAK,EAAE;IACzE,kBAAkB,EAAE,eAAe,CAAC;IACpC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,6BAA6B,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACxD,GAAG;IACF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0BAA0B,EAAE,WAAW,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1E,cAAc,EAAE,UAAU,CAAC;CAC5B,CAaA"}
@@ -1,7 +1,8 @@
1
+ import { base64URLStringToBuffer } from "./webauthn.js";
1
2
  import { getAddressEncoder } from "@solana/kit";
2
3
  import { getSecp256r1VerifyInstruction, } from "../../instructions/internal/secp256r1Verify.js";
3
4
  import { SECP256R1_PROGRAM_ADDRESS, TRANSFER_ACTION_BYTES, } from "../consts.js";
4
- import { base64URLStringToBuffer, convertSignatureDERtoRS, getClientDataJsonBytes, getSecp256r1Message, } from "./internal.js";
5
+ import { parseWebAuthnAssertion } from "./internal.js";
5
6
  import { sha256 } from "@noble/hashes/sha2.js";
6
7
  function concatBytes(...parts) {
7
8
  const total = parts.reduce((sum, part) => sum + part.length, 0);
@@ -16,9 +17,8 @@ function concatBytes(...parts) {
16
17
  function encodeAddress(addressValue) {
17
18
  return new Uint8Array(getAddressEncoder().encode(addressValue));
18
19
  }
19
- export function buildVerifyInputFromWebAuthn(input) {
20
- const signature = convertSignatureDERtoRS(base64URLStringToBuffer(input.response.response.signature));
21
- const message = getSecp256r1Message(input.response);
20
+ function buildVerifyInputFromWebAuthn(input) {
21
+ const { signature, message } = parseWebAuthnAssertion(input.response);
22
22
  return {
23
23
  publicKey: input.secp256r1PublicKey[0],
24
24
  signature,
@@ -28,7 +28,7 @@ export function buildVerifyInputFromWebAuthn(input) {
28
28
  export async function buildTransferChallenge(input) {
29
29
  return sha256(concatBytes(TRANSFER_ACTION_BYTES, encodeAddress(input.phygitalToken), new Uint8Array(input.slotHash)));
30
30
  }
31
- export async function buildSecp256r1VerifyInstructionFromWebAuthnResponse(input) {
31
+ export function buildSecp256r1VerifyInstructionFromWebAuthnResponse(input) {
32
32
  const existing = input.existingSecp256r1VerifyInputs;
33
33
  const parsed = buildVerifyInputFromWebAuthn(input);
34
34
  let signedMessageIndex = 0;
@@ -39,7 +39,7 @@ export async function buildSecp256r1VerifyInstructionFromWebAuthnResponse(input)
39
39
  return {
40
40
  signedMessageIndex,
41
41
  secp256r1VerifyInstruction: getSecp256r1VerifyInstruction(existing ?? [parsed]),
42
- clientDataJson: getClientDataJsonBytes(input.response),
42
+ clientDataJson: base64URLStringToBuffer(input.response.response.clientDataJSON),
43
43
  };
44
44
  }
45
45
  //# sourceMappingURL=secp256r1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"secp256r1.js","sourceRoot":"","sources":["../../../src/utils/passkey/secp256r1.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAkC,MAAM,aAAa,CAAC;AAChF,OAAO,EACL,6BAA6B,GAE9B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EACL,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAK/C,SAAS,WAAW,CAAC,GAAG,KAAmB;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChE,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtB,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,YAAqB;IAC1C,OAAO,IAAI,UAAU,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,KAG5C;IACC,MAAM,SAAS,GAAG,uBAAuB,CACvC,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAC3D,CAAC;IACF,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEpD,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACtC,SAAS;QACT,OAAO;KACR,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAG5C;IACC,OAAO,MAAM,CACX,WAAW,CACT,qBAAqB,EACrB,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,EAClC,IAAI,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAC/B,CACF,CAAC;AACJ,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,mDAAmD,CAAC,KAIzE;IACC,MAAM,QAAQ,GAAG,KAAK,CAAC,6BAA6B,CAAC;IACrD,MAAM,MAAM,GAAG,4BAA4B,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,IAAI,QAAQ,EAAE,MAAM,EAAE,CAAC;QACrB,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IACD,OAAO;QACL,kBAAkB;QAClB,0BAA0B,EAAE,6BAA6B,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/E,cAAc,EAAE,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC;KACvD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"secp256r1.js","sourceRoot":"","sources":["../../../src/utils/passkey/secp256r1.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAkC,MAAM,aAAa,CAAC;AAChF,OAAO,EACL,6BAA6B,GAE9B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EACL,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAK/C,SAAS,WAAW,CAAC,GAAG,KAAmB;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChE,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtB,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,YAAqB;IAC1C,OAAO,IAAI,UAAU,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,4BAA4B,CAAC,KAGrC;IACC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEtE,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACtC,SAAS;QACT,OAAO;KACR,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAG5C;IACC,OAAO,MAAM,CACX,WAAW,CACT,qBAAqB,EACrB,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,EAClC,IAAI,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAC/B,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mDAAmD,CAAC,KAInE;IAKC,MAAM,QAAQ,GAAG,KAAK,CAAC,6BAA6B,CAAC;IACrD,MAAM,MAAM,GAAG,4BAA4B,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,IAAI,QAAQ,EAAE,MAAM,EAAE,CAAC;QACrB,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IACD,OAAO;QACL,kBAAkB;QAClB,0BAA0B,EAAE,6BAA6B,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/E,cAAc,EAAE,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC;KAChF,CAAC;AACJ,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { Rpc, SolanaRpcApi } from "@solana/kit";
1
2
  /**
2
3
  * Minimal WebAuthn JSON helpers used by this SDK.
3
4
  *
@@ -49,12 +50,18 @@ export declare function base64URLStringToBuffer(base64URLString: string): Uint8A
49
50
  * `challenge` is a base64url string. For on-chain verify, pass the base64url
50
51
  * encoding of `messageHash` (SHA-256 of `message`).
51
52
  * Callers must pass `rpId` (tap helpers default to `window.location.hostname`).
53
+ *
54
+ * Without `credentialId`, uses a random `allowCredentials` id so browsers show the NFC prompt.
55
+ * With `credentialId`, passes that base64url compressed secp256r1 public key (e.g. transfer flow).
56
+ * When the platform echoes a 16-byte placeholder id, {@link authenticateWithWebauthn} recovers the
57
+ * public key from the signature and disambiguates via on-chain PhygitalToken PDAs.
52
58
  */
53
- export declare function nfcWebAuthnRequestOptions(challenge: Base64URLString, rpId: string): PublicKeyCredentialRequestOptionsJSON;
59
+ export declare function nfcWebAuthnRequestOptions(challenge: Base64URLString, rpId: string, credentialId?: Base64URLString): PublicKeyCredentialRequestOptionsJSON;
54
60
  /**
55
61
  * Browser WebAuthn assertion via `navigator.credentials.get` (NFC / security key).
56
- * No conditional UI / autofill — options must include `challenge` and typically
57
- * NFC `allowCredentials` transports.
62
+ *
63
+ * @param rpc - Used to disambiguate secp256r1 public key recovery when `rawId` is 16 bytes
64
+ * (platform echoed the random placeholder instead of the 33-byte authenticator credential id).
58
65
  */
59
- export declare function authenticateWithWebauthn(optionsJSON: PublicKeyCredentialRequestOptionsJSON): Promise<AuthenticationResponseJSON>;
66
+ export declare function authenticateWithWebauthn(optionsJSON: PublicKeyCredentialRequestOptionsJSON, rpc: Rpc<SolanaRpcApi>): Promise<AuthenticationResponseJSON>;
60
67
  //# sourceMappingURL=webauthn.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webauthn.d.ts","sourceRoot":"","sources":["../../../src/utils/passkey/webauthn.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AAEH,6CAA6C;AAC7C,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,4BAA4B,GACpC,KAAK,GACL,OAAO,GACP,QAAQ,GACR,UAAU,GACV,KAAK,GACL,YAAY,GACZ,KAAK,CAAC;AAEV,MAAM,MAAM,iCAAiC,GAAG;IAC9C,EAAE,EAAE,eAAe,CAAC;IACpB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;CAC7C,CAAC;AAEF,iDAAiD;AACjD,MAAM,MAAM,qCAAqC,GAAG;IAClD,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,iCAAiC,EAAE,CAAC;IACvD,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;IAC/C,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,cAAc,GAAG,eAAe,CAAC,CAAC;IAC3D,UAAU,CAAC,EAAE,oCAAoC,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG;IAC/C,cAAc,EAAE,eAAe,CAAC;IAChC,iBAAiB,EAAE,eAAe,CAAC;IACnC,SAAS,EAAE,eAAe,CAAC;IAC3B,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,0BAA0B,GAAG;IACvC,EAAE,EAAE,eAAe,CAAC;IACpB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,kCAAkC,CAAC;IAC7C,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,sBAAsB,EAAE,qCAAqC,CAAC;IAC9D,IAAI,EAAE,uBAAuB,CAAC;CAC/B,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,WAAW,GAAG,eAAe,GACpC,eAAe,CAWjB;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAEpE;AAED,4CAA4C;AAC5C,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,UAAU,CAU3E;AAuBD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,MAAM,GACX,qCAAqC,CAcvC;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,qCAAqC,GACjD,OAAO,CAAC,0BAA0B,CAAC,CAuErC"}
1
+ {"version":3,"file":"webauthn.d.ts","sourceRoot":"","sources":["../../../src/utils/passkey/webauthn.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;GAMG;AAEH,6CAA6C;AAC7C,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,4BAA4B,GACpC,KAAK,GACL,OAAO,GACP,QAAQ,GACR,UAAU,GACV,KAAK,GACL,YAAY,GACZ,KAAK,CAAC;AAEV,MAAM,MAAM,iCAAiC,GAAG;IAC9C,EAAE,EAAE,eAAe,CAAC;IACpB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;CAC7C,CAAC;AAEF,iDAAiD;AACjD,MAAM,MAAM,qCAAqC,GAAG;IAClD,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,iCAAiC,EAAE,CAAC;IACvD,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;IAC/C,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,cAAc,GAAG,eAAe,CAAC,CAAC;IAC3D,UAAU,CAAC,EAAE,oCAAoC,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG;IAC/C,cAAc,EAAE,eAAe,CAAC;IAChC,iBAAiB,EAAE,eAAe,CAAC;IACnC,SAAS,EAAE,eAAe,CAAC;IAC3B,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,0BAA0B,GAAG;IACvC,EAAE,EAAE,eAAe,CAAC;IACpB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,kCAAkC,CAAC;IAC7C,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,sBAAsB,EAAE,qCAAqC,CAAC;IAC9D,IAAI,EAAE,uBAAuB,CAAC;CAC/B,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,WAAW,GAAG,eAAe,GACpC,eAAe,CAWjB;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAEpE;AAED,4CAA4C;AAC5C,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,UAAU,CAU3E;AA0BD;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,eAAe,GAC7B,qCAAqC,CAevC;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,qCAAqC,EAClD,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,GACrB,OAAO,CAAC,0BAA0B,CAAC,CAsErC"}
@@ -1,5 +1,5 @@
1
- import { sha256 } from "@noble/hashes/sha2.js";
2
- import { recoverSecp256r1PublicKey } from "./internal.js";
1
+ import { buildSecp256r1Message } from "./internal.js";
2
+ import { recoverSecp256r1PublicKeyWithPhygitalToken } from "../pdas/token.js";
3
3
  /** Convert an ArrayBuffer or TypedArray view into a Base64URL string. */
4
4
  export function bufferToBase64URLString(buffer) {
5
5
  const bytes = buffer instanceof ArrayBuffer
@@ -42,20 +42,28 @@ function toPublicKeyCredentialDescriptor(descriptor) {
42
42
  : {}),
43
43
  };
44
44
  }
45
+ /** Random `allowCredentials` placeholder ids are 16 bytes; vault keys are 33 bytes. */
46
+ const PLACEHOLDER_CREDENTIAL_ID_LENGTH = 16;
45
47
  /**
46
48
  * Browser WebAuthn request options for an NFC passkey assertion.
47
49
  * `challenge` is a base64url string. For on-chain verify, pass the base64url
48
50
  * encoding of `messageHash` (SHA-256 of `message`).
49
51
  * Callers must pass `rpId` (tap helpers default to `window.location.hostname`).
52
+ *
53
+ * Without `credentialId`, uses a random `allowCredentials` id so browsers show the NFC prompt.
54
+ * With `credentialId`, passes that base64url compressed secp256r1 public key (e.g. transfer flow).
55
+ * When the platform echoes a 16-byte placeholder id, {@link authenticateWithWebauthn} recovers the
56
+ * public key from the signature and disambiguates via on-chain PhygitalToken PDAs.
50
57
  */
51
- export function nfcWebAuthnRequestOptions(challenge, rpId) {
58
+ export function nfcWebAuthnRequestOptions(challenge, rpId, credentialId) {
52
59
  return {
53
60
  challenge,
54
61
  rpId,
55
62
  userVerification: "preferred",
56
63
  allowCredentials: [
57
64
  {
58
- id: bufferToBase64URLString(crypto.getRandomValues(new Uint8Array(16))),
65
+ id: credentialId ??
66
+ bufferToBase64URLString(crypto.getRandomValues(new Uint8Array(PLACEHOLDER_CREDENTIAL_ID_LENGTH))),
59
67
  type: "public-key",
60
68
  transports: ["nfc"],
61
69
  },
@@ -64,10 +72,11 @@ export function nfcWebAuthnRequestOptions(challenge, rpId) {
64
72
  }
65
73
  /**
66
74
  * Browser WebAuthn assertion via `navigator.credentials.get` (NFC / security key).
67
- * No conditional UI / autofill — options must include `challenge` and typically
68
- * NFC `allowCredentials` transports.
75
+ *
76
+ * @param rpc - Used to disambiguate secp256r1 public key recovery when `rawId` is 16 bytes
77
+ * (platform echoed the random placeholder instead of the 33-byte authenticator credential id).
69
78
  */
70
- export async function authenticateWithWebauthn(optionsJSON) {
79
+ export async function authenticateWithWebauthn(optionsJSON, rpc) {
71
80
  if (typeof window === "undefined" ||
72
81
  typeof window.PublicKeyCredential === "undefined") {
73
82
  throw new Error("WebAuthn is not supported in this browser");
@@ -96,16 +105,10 @@ export async function authenticateWithWebauthn(optionsJSON) {
96
105
  const clientDataJSON = bufferToBase64URLString(response.clientDataJSON);
97
106
  const signature = bufferToBase64URLString(response.signature);
98
107
  let credentialId = credential.id;
99
- const placeholderIds = new Set(optionsJSON.allowCredentials?.map((descriptor) => descriptor.id) ?? []);
100
- if (placeholderIds.has(credentialId)) {
101
- const clientDataBytes = new Uint8Array(response.clientDataJSON);
102
- const authenticatorDataBytes = new Uint8Array(response.authenticatorData);
103
- const message = new Uint8Array([
104
- ...authenticatorDataBytes,
105
- ...sha256(clientDataBytes),
106
- ]);
108
+ if (new Uint8Array(credential.rawId).length === PLACEHOLDER_CREDENTIAL_ID_LENGTH) {
107
109
  const signatureBytes = new Uint8Array(response.signature);
108
- credentialId = bufferToBase64URLString(recoverSecp256r1PublicKey(signatureBytes, message));
110
+ const message = buildSecp256r1Message(new Uint8Array(response.authenticatorData), new Uint8Array(response.clientDataJSON));
111
+ credentialId = bufferToBase64URLString(await recoverSecp256r1PublicKeyWithPhygitalToken(rpc, signatureBytes, message));
109
112
  }
110
113
  return {
111
114
  id: credentialId,
@@ -1 +1 @@
1
- {"version":3,"file":"webauthn.js","sourceRoot":"","sources":["../../../src/utils/passkey/webauthn.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webauthn.js","sourceRoot":"","sources":["../../../src/utils/passkey/webauthn.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type Address } from "@solana/kit";
1
+ import { type Address, type Rpc, type SolanaRpcApi } from "@solana/kit";
2
2
  import { type Secp256r1Pubkey } from "../../generated/index.js";
3
3
  import type { Base64URLString } from "../passkey/webauthn.js";
4
4
  /**
@@ -8,4 +8,10 @@ import type { Base64URLString } from "../passkey/webauthn.js";
8
8
  * PDA seeds: `["token", pubkey[1..]]` — the compressed-point prefix byte is dropped.
9
9
  */
10
10
  export declare function findPhygitalTokenPda(secp256r1Pubkey: Secp256r1Pubkey | Base64URLString): Promise<Address>;
11
+ /**
12
+ * Recover a compressed secp256r1 public key from a WebAuthn assertion.
13
+ * When multiple keys verify the signature, selects the candidate whose
14
+ * {@link findPhygitalTokenPda} exists on-chain.
15
+ */
16
+ export declare function recoverSecp256r1PublicKeyWithPhygitalToken(rpc: Rpc<SolanaRpcApi>, signature: Uint8Array, message: Uint8Array): Promise<Uint8Array>;
11
17
  //# sourceMappingURL=token.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/utils/pdas/token.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAGb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,eAAe,EAAE,eAAe,GAAG,eAAe,GACjD,OAAO,CAAC,OAAO,CAAC,CAelB"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/utils/pdas/token.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAGZ,KAAK,GAAG,EACR,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,eAAe,EAAE,eAAe,GAAG,eAAe,GACjD,OAAO,CAAC,OAAO,CAAC,CAelB;AAED;;;;GAIG;AACH,wBAAsB,0CAA0C,CAC9D,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CA6BrB"}
@@ -1,6 +1,8 @@
1
1
  import { getProgramDerivedAddress, getBytesEncoder, } from "@solana/kit";
2
2
  import { PHYGITAL_TOKEN_PROGRAM_ADDRESS, } from "../../generated/index.js";
3
+ import { fetchAllMaybePhygitalToken } from "../../generated/accounts/phygitalToken.js";
3
4
  import { parseSecp256r1Pubkey } from "../parseSecp256r1Pubkey.js";
5
+ import { recoverSecp256r1PublicKeyCandidates } from "../passkey/internal.js";
4
6
  const TOKEN_SEED = new TextEncoder().encode("token");
5
7
  /**
6
8
  * Derive the token PDA from the compressed secp256r1 passkey public key.
@@ -21,4 +23,27 @@ export async function findPhygitalTokenPda(secp256r1Pubkey) {
21
23
  });
22
24
  return token;
23
25
  }
26
+ /**
27
+ * Recover a compressed secp256r1 public key from a WebAuthn assertion.
28
+ * When multiple keys verify the signature, selects the candidate whose
29
+ * {@link findPhygitalTokenPda} exists on-chain.
30
+ */
31
+ export async function recoverSecp256r1PublicKeyWithPhygitalToken(rpc, signature, message) {
32
+ const candidates = recoverSecp256r1PublicKeyCandidates(signature, message);
33
+ if (candidates.length === 0) {
34
+ throw new Error("Failed to recover secp256r1 public key from signature");
35
+ }
36
+ if (candidates.length === 1) {
37
+ return candidates[0];
38
+ }
39
+ const tokenAccounts = await fetchAllMaybePhygitalToken(rpc, await Promise.all(candidates.map((candidate) => findPhygitalTokenPda([candidate]))));
40
+ const matches = tokenAccounts.filter((account) => account.exists);
41
+ if (matches.length === 1) {
42
+ return new Uint8Array(matches[0].data.publicKey[0]);
43
+ }
44
+ if (matches.length === 0) {
45
+ throw new Error("No recovered secp256r1 public key matches an initialized PhygitalToken on-chain.");
46
+ }
47
+ throw new Error("Ambiguous secp256r1 public key recovery: multiple keys match PhygitalToken accounts.");
48
+ }
24
49
  //# sourceMappingURL=token.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/utils/pdas/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,wBAAwB,EACxB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAGlE,MAAM,UAAU,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,eAAkD;IAElD,MAAM,MAAM,GACV,OAAO,eAAe,KAAK,QAAQ;QACjC,CAAC,CAAC,oBAAoB,CAAC,eAAe,CAAC;QACvC,CAAC,CAAC,eAAe,CAAC;IAEtB,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,wBAAwB,CAAC;QAC7C,cAAc,EAAE,8BAA8B;QAC9C,KAAK,EAAE;YACL,eAAe,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;YACpC,eAAe,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC7C;KACF,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/utils/pdas/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,wBAAwB,EACxB,eAAe,GAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,mCAAmC,EAAE,MAAM,wBAAwB,CAAC;AAG7E,MAAM,UAAU,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,eAAkD;IAElD,MAAM,MAAM,GACV,OAAO,eAAe,KAAK,QAAQ;QACjC,CAAC,CAAC,oBAAoB,CAAC,eAAe,CAAC;QACvC,CAAC,CAAC,eAAe,CAAC;IAEtB,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,wBAAwB,CAAC;QAC7C,cAAc,EAAE,8BAA8B;QAC9C,KAAK,EAAE;YACL,eAAe,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;YACpC,eAAe,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC7C;KACF,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,0CAA0C,CAC9D,GAAsB,EACtB,SAAqB,EACrB,OAAmB;IAEnB,MAAM,UAAU,GAAG,mCAAmC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,0BAA0B,CACpD,GAAG,EACH,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CACpF,CAAC;IACF,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAElE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;AACJ,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { Rpc, SolanaRpcApi } from "@solana/kit";
1
2
  import { type AuthenticationResponseJSON } from "./passkey/webauthn.js";
2
3
  /** Result of {@link verifyResponse}. */
3
4
  export type VerifyResponseResult = {
@@ -16,9 +17,14 @@ export type VerifyResponseOptions = {
16
17
  * Browser: opens the system WebAuthn/NFC modal.
17
18
  * Native / kiosk: pass `transceive` to talk to an IsoDep reader via APDUs.
18
19
  *
19
- * @param rpId - Relying party ID. Defaults to `window.location.hostname`.
20
+ * @param rpc - Kit `Rpc`. Required for browser WebAuthn recovery disambiguation.
21
+ * @param options.transceive - Native NFC reader; when set, skips browser WebAuthn.
22
+ * @param options.rpId - Relying party ID. Defaults to `window.location.hostname`.
20
23
  */
21
- export declare function startAuthentication(message: string, transceive?: (apdu: Uint8Array) => Promise<Uint8Array>, rpId?: string): Promise<AuthenticationResponseJSON>;
24
+ export declare function startAuthentication(message: string, rpc: Rpc<SolanaRpcApi>, options?: {
25
+ transceive?: (apdu: Uint8Array) => Promise<Uint8Array>;
26
+ rpId?: string;
27
+ }): Promise<AuthenticationResponseJSON>;
22
28
  /**
23
29
  * **Authentication (server)** — verify a fresh tap signature.
24
30
  *
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/utils/verify.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,0BAA0B,EAChC,MAAM,uBAAuB,CAAC;AAU/B,wCAAwC;AACxC,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,0CAA0C;AAC1C,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,0BAA0B,CAAC;CACtC,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,EACtD,IAAI,SAA2B,GAC9B,OAAO,CAAC,0BAA0B,CAAC,CAuBrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,EAC7B,eAAe,EACf,QAAQ,GACT,EAAE,qBAAqB,GAAG,oBAAoB,CAwB9C"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/utils/verify.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAIL,KAAK,0BAA0B,EAChC,MAAM,uBAAuB,CAAC;AAQ/B,wCAAwC;AACxC,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,0CAA0C;AAC1C,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,0BAA0B,CAAC;CACtC,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,EACtB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACA,OAAO,CAAC,0BAA0B,CAAC,CAwBrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,EAC7B,eAAe,EACf,QAAQ,GACT,EAAE,qBAAqB,GAAG,oBAAoB,CAqB9C"}
@@ -1,6 +1,6 @@
1
1
  import { p256 } from "@noble/curves/nist.js";
2
2
  import { authenticateWithWebauthn, nfcWebAuthnRequestOptions, utf8ToBase64URLString, } from "./passkey/webauthn.js";
3
- import { base64URLStringToBuffer, convertSignatureDERtoRS, getSecp256r1Message, parseWebAuthnClientData, } from "./passkey/internal.js";
3
+ import { parseWebAuthnAssertion, parseWebAuthnClientData, } from "./passkey/internal.js";
4
4
  import { authenticateWithApdu } from "./passkey/nfc/index.js";
5
5
  import { parseSecp256r1Pubkey } from "../utils/parseSecp256r1Pubkey.js";
6
6
  /**
@@ -9,11 +9,14 @@ import { parseSecp256r1Pubkey } from "../utils/parseSecp256r1Pubkey.js";
9
9
  * Browser: opens the system WebAuthn/NFC modal.
10
10
  * Native / kiosk: pass `transceive` to talk to an IsoDep reader via APDUs.
11
11
  *
12
- * @param rpId - Relying party ID. Defaults to `window.location.hostname`.
12
+ * @param rpc - Kit `Rpc`. Required for browser WebAuthn recovery disambiguation.
13
+ * @param options.transceive - Native NFC reader; when set, skips browser WebAuthn.
14
+ * @param options.rpId - Relying party ID. Defaults to `window.location.hostname`.
13
15
  */
14
- export async function startAuthentication(message, transceive, rpId = window.location.hostname) {
16
+ export async function startAuthentication(message, rpc, options) {
15
17
  const challenge = utf8ToBase64URLString(message);
16
- if (transceive) {
18
+ const rpId = options?.rpId ?? window.location.hostname;
19
+ if (options?.transceive) {
17
20
  return authenticateWithApdu({
18
21
  challenge,
19
22
  rpId: "",
@@ -26,9 +29,9 @@ export async function startAuthentication(message, transceive, rpId = window.loc
26
29
  transports: ["nfc"],
27
30
  },
28
31
  ],
29
- }, transceive);
32
+ }, options.transceive);
30
33
  }
31
- return authenticateWithWebauthn(nfcWebAuthnRequestOptions(challenge, rpId));
34
+ return authenticateWithWebauthn(nfcWebAuthnRequestOptions(challenge, rpId), rpc);
32
35
  }
33
36
  /**
34
37
  * **Authentication (server)** — verify a fresh tap signature.
@@ -51,8 +54,7 @@ export function verifyResponse({ expectedMessage, response, }) {
51
54
  if (clientData.challenge !== expectedChallenge) {
52
55
  throw new Error("Message mismatch.");
53
56
  }
54
- const signature = convertSignatureDERtoRS(base64URLStringToBuffer(response.response.signature));
55
- const message = getSecp256r1Message(response);
57
+ const { signature, message } = parseWebAuthnAssertion(response);
56
58
  const isVerified = p256.verify(signature, message, new Uint8Array(parseSecp256r1Pubkey(response.id)[0]));
57
59
  return {
58
60
  isVerified,
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/utils/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,GAEtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAexE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,UAAsD,EACtD,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ;IAE/B,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAEjD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,oBAAoB,CACzB;YACE,SAAS;YACT,IAAI,EAAE,EAAE;YACR,gBAAgB,EAAE,WAAW;YAC7B,MAAM,EAAE,EAAE;YACV,gBAAgB,EAAE;gBAChB;oBACE,EAAE,EAAE,EAAE;oBACN,IAAI,EAAE,YAAY;oBAClB,UAAU,EAAE,CAAC,KAAK,CAAC;iBACpB;aACF;SACF,EACD,UAAU,CACX,CAAC;IACJ,CAAC;IAED,OAAO,wBAAwB,CAAC,yBAAyB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,eAAe,EACf,QAAQ,GACc;IACtB,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,eAAe,CAAC,CAAC;IAEjE,MAAM,UAAU,GAAG,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAE7E,IAAI,UAAU,CAAC,SAAS,KAAK,iBAAiB,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,SAAS,GAAG,uBAAuB,CACvC,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CACrD,CAAC;IACF,MAAM,OAAO,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAE9C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAC5B,SAAS,EACT,OAAO,EACP,IAAI,UAAU,CAAC,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CACrD,CAAC;IAEF,OAAO;QACL,UAAU;QACV,kBAAkB,EAAE,QAAQ,CAAC,EAAE;KAChC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/utils/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,GAEtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAexE;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,GAAsB,EACtB,OAGC;IAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAEvD,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;QACxB,OAAO,oBAAoB,CACzB;YACE,SAAS;YACT,IAAI,EAAE,EAAE;YACR,gBAAgB,EAAE,WAAW;YAC7B,MAAM,EAAE,EAAE;YACV,gBAAgB,EAAE;gBAChB;oBACE,EAAE,EAAE,EAAE;oBACN,IAAI,EAAE,YAAY;oBAClB,UAAU,EAAE,CAAC,KAAK,CAAC;iBACpB;aACF;SACF,EACD,OAAO,CAAC,UAAU,CACnB,CAAC;IACJ,CAAC;IAED,OAAO,wBAAwB,CAAC,yBAAyB,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AACnF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,eAAe,EACf,QAAQ,GACc;IACtB,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,eAAe,CAAC,CAAC;IAEjE,MAAM,UAAU,GAAG,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAE7E,IAAI,UAAU,CAAC,SAAS,KAAK,iBAAiB,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAEhE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAC5B,SAAS,EACT,OAAO,EACP,IAAI,UAAU,CAAC,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CACrD,CAAC;IAEF,OAAO;QACL,UAAU;QACV,kBAAkB,EAAE,QAAQ,CAAC,EAAE;KAChC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phygital-token-sdk",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "TypeScript client for the Phygital Token Solana program",
5
5
  "license": "MIT",
6
6
  "author": "Revibase",