Skip to content

Instantly share code, notes, and snippets.

@0xBigBoss
Created December 29, 2023 15:27
Show Gist options
  • Save 0xBigBoss/5680dcb89243c43fe86936a5374d4bc9 to your computer and use it in GitHub Desktop.
Save 0xBigBoss/5680dcb89243c43fe86936a5374d4bc9 to your computer and use it in GitHub Desktop.
Verify a digital signature using ECDSA and Web Crypto API
export async function verifySignature({
authenticatorData,
clientDataJSON,
r,
s,
x,
y,
}: {
authenticatorData: string
clientDataJSON: string
r: string
s: string
x: bigint
y: bigint
}): Promise<boolean> {
// Step 1: Decode the data
const authenticatorDataArray = new Uint8Array(Buffer.from(authenticatorData.slice(2), 'hex'))
const clientDataHash = new Uint8Array(
await crypto.subtle.digest('SHA-256', Buffer.from(clientDataJSON))
)
const signatureBuffer = new Uint8Array(Buffer.from(r.slice(2) + s.slice(2), 'hex'))
// Combine clientDataJSON and authenticatorData into a single ArrayBuffer for verification
const dataBuffer = new Uint8Array(clientDataHash.length + authenticatorDataArray.length)
dataBuffer.set(clientDataHash, 0)
dataBuffer.set(authenticatorDataArray, clientDataHash.length)
// Convert BigInts to Uint8Array
const x64 = Buffer.from(x.toString(16), 'hex').toString('base64url')
const y64 = Buffer.from(y.toString(16), 'hex').toString('base64url')
const publicKey = {
kty: 'EC',
crv: 'P-256',
x: x64,
y: y64,
ext: true,
}
const importedKey = await crypto.subtle.importKey(
'jwk',
publicKey,
{
name: 'ECDSA',
namedCurve: 'P-256',
},
true,
['verify']
)
// Step 3: Verify the signature
try {
return await crypto.subtle.verify(
{
name: 'ECDSA',
hash: { name: 'SHA-256' },
},
importedKey,
signatureBuffer,
dataBuffer
)
} catch (error) {
console.error('Signature verification failed', error)
return false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment