Skip to content

Commit

Permalink
feat: remove webauthn-p256 in favor of Ox (#3232)
Browse files Browse the repository at this point in the history
* feat: remove webauthn-p256 in favor of Ox

Co-Authored-By: Micah Zoltu <[email protected]>

* chore: up size

---------

Co-authored-by: Micah Zoltu <[email protected]>
  • Loading branch information
jxom and MicahZoltu authored Jan 16, 2025
1 parent 884f5ee commit e1df486
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 48 deletions.
5 changes: 5 additions & 0 deletions .changeset/forty-walls-invite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"viem": patch
---

Upgraded WebAuthn Accounts to use `ox` instead of `webauthn-p256`.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
{
"name": "import * from 'viem/account-abstraction'",
"path": "./src/_esm/account-abstraction/index.js",
"limit": "47 kB",
"limit": "49 kB",
"import": "*"
},
{
Expand Down
65 changes: 54 additions & 11 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 27 additions & 7 deletions src/account-abstraction/accounts/createWebAuthnCredential.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
// biome-ignore lint/performance/noBarrelFile:
export {
type CreateCredentialParameters as CreateWebAuthnCredentialParameters,
type CreateCredentialReturnType as CreateWebAuthnCredentialReturnType,
type P256Credential,
createCredential as createWebAuthnCredential,
} from 'webauthn-p256'
// TODO(v3): Remove this in favor of `ox/WebAuthnP256` entirely.
import * as PublicKey from 'ox/PublicKey'
import * as WebAuthnP256 from 'ox/WebAuthnP256'

import type { Hex } from '../../types/misc.js'

export type P256Credential = {
id: WebAuthnP256.P256Credential['id']
publicKey: Hex
raw: WebAuthnP256.P256Credential['raw']
}

export type CreateWebAuthnCredentialParameters =
WebAuthnP256.createCredential.Options

export type CreateWebAuthnCredentialReturnType = P256Credential

export async function createWebAuthnCredential(
parameters: CreateWebAuthnCredentialParameters,
): Promise<CreateWebAuthnCredentialReturnType> {
const credential = await WebAuthnP256.createCredential(parameters)
return {
id: credential.id,
publicKey: PublicKey.toHex(credential.publicKey, { includePrefix: false }),
raw: credential.raw,
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { Address, TypedData } from 'abitype'
import {
type WebAuthnData,
parseSignature as parseP256Signature,
} from 'webauthn-p256'
import * as Signature from 'ox/Signature'
import type * as WebAuthnP256 from 'ox/WebAuthnP256'

import type { LocalAccount } from '../../../accounts/types.js'
import { readContract } from '../../../actions/public/readContract.js'
Expand Down Expand Up @@ -319,10 +317,10 @@ export function toWebAuthnSignature({
webauthn,
signature,
}: {
webauthn: WebAuthnData
webauthn: WebAuthnP256.SignMetadata
signature: Hex
}) {
const { r, s } = parseP256Signature(signature)
const { r, s } = Signature.fromHex(signature)
return encodeAbiParameters(
[
{
Expand Down
32 changes: 16 additions & 16 deletions src/account-abstraction/accounts/toWebAuthnAccount.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PublicKey, Signature, WebAuthnP256 } from 'ox'
import { expect, test } from 'vitest'

import { verify } from 'webauthn-p256'
import { typedData } from '../../../test/src/constants.js'
import { hashMessage, hashTypedData, keccak256 } from '../../utils/index.js'
import { toWebAuthnAccount } from './toWebAuthnAccount.js'
Expand Down Expand Up @@ -109,11 +109,11 @@ test('sign', async () => {
}
`)

const valid = await verify({
publicKey: account.publicKey,
signature,
webauthn,
hash: keccak256('0xdeadbeef'),
const valid = WebAuthnP256.verify({
challenge: keccak256('0xdeadbeef'),
metadata: webauthn,
signature: Signature.fromHex(signature),
publicKey: PublicKey.fromHex(account.publicKey),
})
expect(valid).toBeTruthy()
})
Expand Down Expand Up @@ -169,11 +169,11 @@ test('signMessage', async () => {
}
`)

const valid = await verify({
publicKey: account.publicKey,
signature,
webauthn,
hash: hashMessage('hello world'),
const valid = WebAuthnP256.verify({
challenge: hashMessage('hello world'),
metadata: webauthn,
signature: Signature.fromHex(signature),
publicKey: PublicKey.fromHex(account.publicKey),
})
expect(valid).toBeTruthy()
})
Expand Down Expand Up @@ -230,14 +230,14 @@ test('signTypedData', async () => {
}
`)

const valid = await verify({
publicKey: account.publicKey,
signature,
webauthn,
hash: hashTypedData({
const valid = WebAuthnP256.verify({
challenge: hashTypedData({
...typedData.basic,
primaryType: 'Mail',
}),
metadata: webauthn,
signature: Signature.fromHex(signature),
publicKey: PublicKey.fromHex(account.publicKey),
})
expect(valid).toBeTruthy()
})
20 changes: 16 additions & 4 deletions src/account-abstraction/accounts/toWebAuthnAccount.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { type P256Credential, type SignParameters, sign } from 'webauthn-p256'
import * as Signature from 'ox/Signature'
import * as WebAuthnP256 from 'ox/WebAuthnP256'

import type { ErrorType } from '../../errors/utils.js'
import { hashMessage } from '../../utils/signature/hashMessage.js'
import { hashTypedData } from '../../utils/signature/hashTypedData.js'
import type { P256Credential } from './createWebAuthnCredential.js'
import type { WebAuthnAccount } from './types.js'

export type ToWebAuthnAccountParameters = {
Expand All @@ -19,11 +21,11 @@ export type ToWebAuthnAccountParameters = {
*
* @default window.navigator.credentials.get
*/
getFn?: SignParameters['getFn'] | undefined
getFn?: WebAuthnP256.sign.Options['getFn'] | undefined
/**
* The relying party identifier to use.
*/
rpId?: SignParameters['rpId'] | undefined
rpId?: WebAuthnP256.sign.Options['rpId'] | undefined
}

export type ToWebAuthnAccountReturnType = WebAuthnAccount
Expand All @@ -44,7 +46,17 @@ export function toWebAuthnAccount(
id,
publicKey,
async sign({ hash }) {
return sign({ credentialId: id, getFn, hash, rpId })
const { metadata, raw, signature } = await WebAuthnP256.sign({
credentialId: id,
getFn,
challenge: hash,
rpId,
})
return {
signature: Signature.toHex(signature),
raw,
webauthn: metadata,
}
},
async signMessage({ message }) {
return this.sign({ hash: hashMessage(message) })
Expand Down
9 changes: 8 additions & 1 deletion src/account-abstraction/accounts/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Abi, Address, TypedData } from 'abitype'
import type { SignReturnType as WebAuthnSignReturnType } from 'webauthn-p256'
import type * as WebAuthnP256 from 'ox/WebAuthnP256'

import type { Client } from '../../clients/createClient.js'
import type { Hash, Hex, SignableMessage } from '../../types/misc.js'
Expand Down Expand Up @@ -219,6 +219,13 @@ export type SmartAccount<
>
>

// TODO(v3): Remove this in favor of `WebAuthnP256.sign.ReturnType` from Ox.
export type WebAuthnSignReturnType = {
signature: Hex
webauthn: WebAuthnP256.SignMetadata
raw: WebAuthnP256.sign.ReturnType['raw']
}

export type WebAuthnAccount = {
id: string
publicKey: Hex
Expand Down
3 changes: 1 addition & 2 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@
"@scure/bip39": "1.5.0",
"abitype": "1.0.7",
"isows": "1.0.6",
"ox": "0.6.0",
"webauthn-p256": "0.0.10",
"ox": "0.6.5",
"ws": "8.18.0"
},
"license": "MIT",
Expand Down

0 comments on commit e1df486

Please sign in to comment.