{ "version": 3, "sources": ["../src/client.ts", "../src/utils.ts", "../src/server.ts", "../src/parsers.ts", "../src/authenticatorMetadata.ts", "../src/authenticators.ts"], "sourcesContent": ["import * as utils from './utils.js'\nimport { AuthenticateOptions, AuthenticationEncoded, AuthType, NamedAlgo, NumAlgo, RegisterOptions, RegistrationEncoded } from './types.js'\n\n/**\n * Returns whether passwordless authentication is available on this browser/platform or not.\n */\n export function isAvailable() :boolean {\n return !!window.PublicKeyCredential\n}\n\n/**\n * Returns whether the device itself can be used as authenticator.\n */\nexport async function isLocalAuthenticator() :Promise {\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()\n}\n\n\n\n\nasync function getAuthAttachment(authType :AuthType) :Promise {\n if(authType === \"local\")\n return \"platform\";\n if(authType === \"roaming\" || authType === \"extern\")\n return \"cross-platform\";\n if(authType === \"both\")\n return undefined // The webauthn protocol considers `null` as invalid but `undefined` as \"both\"!\n\n // the default case: \"auto\", depending on device capabilities\n try {\n if(await isLocalAuthenticator())\n return \"platform\"\n else\n return \"cross-platform\"\n } catch(e) {\n // might happen due to some security policies\n // see https://w3c.github.io/webauthn/#sctn-isUserVerifyingPlatformAuthenticatorAvailable\n return undefined // The webauthn protocol considers `null` as invalid but `undefined` as \"both\"!\n }\n}\n\n\n\nfunction getAlgoName(num :NumAlgo) :NamedAlgo {\n switch(num) {\n case -7: return \"ES256\"\n // case -8 ignored to to its rarity\n case -257: return \"RS256\"\n default: throw new Error(`Unknown algorithm code: ${num}`)\n }\n}\n\n\n\n/**\n * Creates a cryptographic key pair, in order to register the public key for later passwordless authentication.\n *\n * @param {string} username\n * @param {string} challenge A server-side randomly generated string.\n * @param {Object} [options] Optional parameters.\n * @param {number} [options.timeout=60000] Number of milliseconds the user has to respond to the biometric/PIN check.\n * @param {'required'|'preferred'|'discouraged'} [options.userVerification='required'] Whether to prompt for biometric/PIN check or not.\n * @param {'auto'|'local'|'roaming'|'both'} [options.authenticatorType='auto'] Which device to use as authenticator.\n * 'auto': if the local device can be used as authenticator it will be preferred. Otherwise it will prompt for a roaming device.\n * 'local': use the local device (using TouchID, FaceID, Windows Hello or PIN)\n * 'roaming': use a roaming device (security key or connected phone)\n * 'both': prompt the user to choose between local or roaming device. The UI and user interaction in this case is platform specific.\n * @param {boolean} [attestation=false] If enabled, the device attestation and clientData will be provided as Base64url encoded binary data.\n * Note that this is not available on some platforms.\n */\nexport async function register(username :string, challenge :string, options? :RegisterOptions) :Promise {\n options = options ?? {}\n\n if(!utils.isBase64url(challenge))\n throw new Error('Provided challenge is not properly encoded in Base64url')\n\n const creationOptions :PublicKeyCredentialCreationOptions = {\n challenge: utils.parseBase64url(challenge),\n rp: {\n id: window.location.hostname,\n name: window.location.hostname\n },\n user: {\n id: await utils.sha256(new TextEncoder().encode(username)), // ID should not be directly \"identifiable\" for privacy concerns\n name: username,\n displayName: username,\n },\n pubKeyCredParams: [\n {alg: -7, type: \"public-key\"}, // ES256 (Webauthn's default algorithm)\n {alg: -257, type: \"public-key\"}, // RS256 (for Windows Hello and others)\n ],\n timeout: options.timeout ?? 60000,\n authenticatorSelection: {\n userVerification: options.userVerification ?? \"required\", // Webauthn default is \"preferred\"\n authenticatorAttachment: await getAuthAttachment(options.authenticatorType ?? \"auto\"),\n },\n attestation: \"direct\" // options.attestation ? \"direct\" : \"none\"\n }\n\n if(options.debug)\n console.debug(creationOptions)\n\n const credential = await navigator.credentials.create({publicKey: creationOptions}) as any //PublicKeyCredential\n \n if(options.debug)\n console.debug(credential)\n \n const response = credential.response as any // AuthenticatorAttestationResponse\n \n let registration :RegistrationEncoded = {\n username: username,\n credential: {\n id: credential.id,\n publicKey: utils.toBase64url(response.getPublicKey()),\n algorithm: getAlgoName(credential.response.getPublicKeyAlgorithm())\n },\n authenticatorData: utils.toBase64url(response.getAuthenticatorData()),\n clientData: utils.toBase64url(response.clientDataJSON),\n }\n\n if(options.attestation) {\n registration.attestationData = utils.toBase64url(response.attestationObject)\n }\n\n return registration\n}\n\n\nasync function getTransports(authType :AuthType) :Promise {\n const local :AuthenticatorTransport[] = ['internal']\n\n // 'hybrid' was added mid-2022 in the specs and currently not yet available in the official dom types\n // @ts-ignore\n const roaming :AuthenticatorTransport[] = ['hybrid', 'usb', 'ble', 'nfc']\n \n if(authType === \"local\")\n return local\n if(authType == \"roaming\" || authType === \"extern\")\n return roaming\n if(authType === \"both\")\n return [...local, ...roaming]\n\n // the default case: \"auto\", depending on device capabilities\n try {\n if(await isLocalAuthenticator())\n return local\n else\n return roaming\n } catch(e) {\n return [...local, ...roaming]\n }\n}\n\n\n/**\n * Signs a challenge using one of the provided credentials IDs in order to authenticate the user.\n *\n * @param {string[]} credentialIds The list of credential IDs that can be used for signing.\n * @param {string} challenge A server-side randomly generated string, the base64 encoded version will be signed.\n * @param {Object} [options] Optional parameters.\n * @param {number} [options.timeout=60000] Number of milliseconds the user has to respond to the biometric/PIN check.\n * @param {'required'|'preferred'|'discouraged'} [options.userVerification='required'] Whether to prompt for biometric/PIN check or not.\n */\nexport async function authenticate(credentialIds :string[], challenge :string, options? :AuthenticateOptions) :Promise {\n options = options ?? {}\n\n if(!utils.isBase64url(challenge))\n throw new Error('Provided challenge is not properly encoded in Base64url')\n\n const transports = await getTransports(options.authenticatorType ?? \"auto\");\n\n let authOptions :PublicKeyCredentialRequestOptions = {\n challenge: utils.parseBase64url(challenge),\n rpId: window.location.hostname,\n allowCredentials: credentialIds.map(id => { return {\n id: utils.parseBase64url(id),\n type: 'public-key',\n transports: transports,\n }}),\n userVerification: options.userVerification ?? \"required\",\n timeout: options.timeout ?? 60000,\n }\n\n if(options.debug)\n console.debug(authOptions)\n\n let auth = await navigator.credentials.get({publicKey: authOptions}) as PublicKeyCredential\n \n if(options.debug)\n console.debug(auth)\n\n const response = auth.response as AuthenticatorAssertionResponse\n \n const authentication :AuthenticationEncoded = {\n credentialId: auth.id,\n //userHash: utils.toBase64url(response.userHandle), // unreliable, optional for authenticators\n authenticatorData: utils.toBase64url(response.authenticatorData),\n clientData: utils.toBase64url(response.clientDataJSON),\n signature: utils.toBase64url(response.signature),\n }\n\n return authentication\n}\n\n", "/********************************\n Encoding/Decoding Utils\n********************************/\n\n/*\nlet webCrypto :any = null\n\nexport async function getCrypto() {\n if(!webCrypto) {\n console.log(window?.crypto)\n webCrypto = window?.crypto ?? (await import(\"crypto\")).webcrypto\n console.log(webCrypto)\n }\n return webCrypto\n}\n*/\n\n\nexport function randomChallenge() {\n return crypto.randomUUID()\n}\n\n\nexport function toBuffer(txt :string) :ArrayBuffer {\n return Uint8Array.from(txt, c => c.charCodeAt(0)).buffer\n}\n\nexport function parseBuffer(buffer :ArrayBuffer) :string {\n return String.fromCharCode(...new Uint8Array(buffer))\n}\n\n\nexport function isBase64url(txt :string) :boolean {\n return txt.match(/^[a-zA-Z0-9\\-_]+=*$/) !== null\n}\n\nexport function toBase64url(buffer :ArrayBuffer) :string {\n const txt = btoa(parseBuffer(buffer)) // base64\n return txt.replaceAll('+', '-').replaceAll('/', '_')\n}\n\nexport function parseBase64url(txt :string) :ArrayBuffer {\n txt = txt.replaceAll('-', '+').replaceAll('_', '/') // base64url -> base64\n return toBuffer(atob(txt))\n}\n\n\nexport async function sha256(buffer :ArrayBuffer) :Promise {\n return await crypto.subtle.digest('SHA-256', buffer)\n}\n\nexport function bufferToHex (buffer :ArrayBuffer) :string {\n return [...new Uint8Array (buffer)]\n .map (b => b.toString (16).padStart (2, \"0\"))\n .join (\"\");\n}\n\n\nexport function concatenateBuffers(buffer1 :ArrayBuffer, buffer2 :ArrayBuffer) {\n var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);\n tmp.set(new Uint8Array(buffer1), 0);\n tmp.set(new Uint8Array(buffer2), buffer1.byteLength);\n return tmp;\n };", "import { parseAuthentication, parseRegistration } from \"./parsers.js\";\nimport { AuthenticationEncoded, AuthenticationParsed, CredentialKey, NamedAlgo, RegistrationEncoded, RegistrationParsed } from \"./types.js\";\nimport * as utils from './utils.js'\n\n\nasync function isValid(validator :any, value :any) :Promise {\n if(typeof validator === 'function') {\n const res = validator(value)\n if(res instanceof Promise)\n return await res\n else\n return res\n }\n // the validator can be a single value too\n return validator === value\n}\n\nasync function isNotValid(validator :any, value :any) :Promise {\n return !(await isValid(validator, value))\n}\n\ninterface RegistrationChecks {\n challenge: string | Function,\n origin: string | Function\n}\n\n\nexport async function verifyRegistration(registrationRaw: RegistrationEncoded, expected: RegistrationChecks): Promise {\n const registration = parseRegistration(registrationRaw)\n registration.client.challenge\n\n if (registration.client.type !== \"webauthn.create\")\n throw new Error(`Unexpected ClientData type: ${registration.client.type}`)\n\n if (await isNotValid(expected.origin, registration.client.origin))\n throw new Error(`Unexpected ClientData origin: ${registration.client.origin}`)\n\n if (await isNotValid(expected.challenge, registration.client.challenge))\n throw new Error(`Unexpected ClientData challenge: ${registration.client.challenge}`)\n\n return registration\n}\n\n\ninterface AuthenticationChecks {\n challenge: string | Function,\n origin: string | Function,\n userVerified: boolean,\n counter: number\n}\n\n\nexport async function verifyAuthentication(authenticationRaw: AuthenticationEncoded, credential: CredentialKey, expected: AuthenticationChecks): Promise {\n if (authenticationRaw.credentialId !== credential.id)\n throw new Error(`Credential ID mismatch: ${authenticationRaw.credentialId} vs ${credential.id}`)\n\n const isValidSignature: boolean = await verifySignature({\n algorithm: credential.algorithm,\n publicKey: credential.publicKey,\n authenticatorData: authenticationRaw.authenticatorData,\n clientData: authenticationRaw.clientData,\n signature: authenticationRaw.signature\n })\n\n if(!isValidSignature)\n throw new Error(`Invalid signature: ${authenticationRaw.signature}`)\n\n const authentication = parseAuthentication(authenticationRaw)\n\n if (authentication.client.type !== \"webauthn.get\")\n throw new Error(`Unexpected clientData type: ${authentication.client.type}`)\n\n if (await isNotValid(expected.origin, authentication.client.origin))\n throw new Error(`Unexpected ClientData origin: ${authentication.client.origin}`)\n\n if (await isNotValid(expected.challenge, authentication.client.challenge))\n throw new Error(`Unexpected ClientData challenge: ${authentication.client.challenge}`)\n\n // this only works because we consider `rp.origin` and `rp.id` to be the same during authentication/registration\n const rpId = new URL(authentication.client.origin).hostname\n const expectedRpIdHash = utils.toBase64url(await utils.sha256(utils.toBuffer(rpId)))\n if (authentication.authenticator.rpIdHash !== expectedRpIdHash)\n throw new Error(`Unexpected RpIdHash: ${authentication.authenticator.rpIdHash} vs ${expectedRpIdHash}`)\n\n if (!authentication.authenticator.flags.userPresent)\n throw new Error(`Unexpected authenticator flags: missing userPresent`)\n\n if (!authentication.authenticator.flags.userVerified && expected.userVerified)\n throw new Error(`Unexpected authenticator flags: missing userVerified`)\n\n if (authentication.authenticator.counter <= expected.counter)\n throw new Error(`Unexpected authenticator counter: ${authentication.authenticator.counter} (should be > ${expected.counter})`)\n\n return authentication\n}\n\n\n// https://w3c.github.io/webauthn/#sctn-public-key-easy\n// https://www.iana.org/assignments/cose/cose.xhtml#algorithms\n/*\nUser agents MUST be able to return a non-null value for getPublicKey() when the credential public key has a COSEAlgorithmIdentifier value of:\n\n-7 (ES256), where kty is 2 (with uncompressed points) and crv is 1 (P-256).\n\n-257 (RS256).\n\n-8 (EdDSA), where crv is 6 (Ed25519).\n*/\nfunction getAlgoParams(algorithm: NamedAlgo): any {\n switch (algorithm) {\n case 'RS256':\n return {\n name: 'RSASSA-PKCS1-v1_5',\n hash: 'SHA-256'\n };\n case 'ES256':\n return {\n name: 'ECDSA',\n namedCurve: 'P-256',\n hash: 'SHA-256',\n };\n // case 'EdDSA': Not supported by browsers\n default:\n throw new Error(`Unknown or unsupported crypto algorithm: ${algorithm}. Only 'RS256' and 'ES256' are supported.`)\n }\n}\n\ntype AlgoParams = AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm\n\nasync function parseCryptoKey(algoParams: AlgoParams, publicKey: string): Promise {\n const buffer = utils.parseBase64url(publicKey)\n return crypto.subtle.importKey('spki', buffer, algoParams, false, ['verify'])\n}\n\n\n\ntype VerifyParams = {\n algorithm: NamedAlgo,\n publicKey: string, // Base64url encoded\n authenticatorData: string, // Base64url encoded\n clientData: string, // Base64url encoded\n signature: string, // Base64url encoded\n}\n\n\n// https://w3c.github.io/webauthn/#sctn-verifying-assertion\n// https://w3c.github.io/webauthn/#sctn-signature-attestation-types\n/* Emphasis mine:\n\n6.5.6. Signature Formats for Packed Attestation, FIDO U2F Attestation, and **Assertion Signatures**\n\n[...] For COSEAlgorithmIdentifier -7 (ES256) [...] the sig value MUST be encoded as an ASN.1 [...]\n[...] For COSEAlgorithmIdentifier -257 (RS256) [...] The signature is not ASN.1 wrapped.\n[...] For COSEAlgorithmIdentifier -37 (PS256) [...] The signature is not ASN.1 wrapped.\n*/\n// see also https://gist.github.com/philholden/50120652bfe0498958fd5926694ba354\nexport async function verifySignature({ algorithm, publicKey, authenticatorData, clientData, signature }: VerifyParams): Promise {\n const algoParams = getAlgoParams(algorithm)\n let cryptoKey = await parseCryptoKey(algoParams, publicKey)\n console.debug(cryptoKey)\n\n let clientHash = await utils.sha256(utils.parseBase64url(clientData));\n\n // during \"login\", the authenticatorData is exactly 37 bytes\n let comboBuffer = utils.concatenateBuffers(utils.parseBase64url(authenticatorData), clientHash)\n\n console.debug('Crypto Algo: ' + JSON.stringify(algoParams))\n console.debug('Public key: ' + publicKey)\n console.debug('Data: ' + utils.toBase64url(comboBuffer))\n console.debug('Signature: ' + signature)\n\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify\n let signatureBuffer = utils.parseBase64url(signature)\n if(algorithm == 'ES256')\n signatureBuffer = convertASN1toRaw(signatureBuffer)\n\n const isValid = await crypto.subtle.verify(algoParams, cryptoKey, signatureBuffer, comboBuffer)\n\n return isValid\n}\n\nfunction convertASN1toRaw(signatureBuffer :ArrayBuffer) {\n // Convert signature from ASN.1 sequence to \"raw\" format\n const usignature = new Uint8Array(signatureBuffer);\n const rStart = usignature[4] === 0 ? 5 : 4;\n const rEnd = rStart + 32;\n const sStart = usignature[rEnd + 2] === 0 ? rEnd + 3 : rEnd + 2;\n const r = usignature.slice(rStart, rEnd);\n const s = usignature.slice(sStart);\n return new Uint8Array([...r, ...s]);\n}", "import * as authenticators from './authenticators.js'\nimport * as utils from './utils.js'\nimport { AuthenticatorInfo, ClientInfo, RegistrationEncoded, RegistrationParsed, AuthenticationEncoded, AuthenticationParsed } from './types'\n\nconst utf8Decoder = new TextDecoder('utf-8')\n\nexport function parseClient(data :string|ArrayBuffer) :ClientInfo {\n if(typeof data == 'string')\n data = utils.parseBase64url(data)\n return JSON.parse(utf8Decoder.decode(data))\n}\n\n\nexport function parseAuthenticator(data :string|ArrayBuffer) :AuthenticatorInfo {\n if(typeof data == 'string')\n data = utils.parseBase64url(data)\n return authenticators.parseAuthBuffer(data)\n}\n\n\nexport function parseAttestation(data :string|ArrayBuffer) :unknown {\n if(typeof data == 'string')\n data = utils.parseBase64url(data)\n return 'Really complex to parse. Good luck with that one!'\n}\n\n\n\nexport function parseRegistration(registration :RegistrationEncoded) :RegistrationParsed {\n return {\n username: registration.username,\n credential: registration.credential,\n\n client: parseClient(registration.clientData),\n authenticator: parseAuthenticator(registration.authenticatorData),\n attestation: registration.attestationData ? parseAttestation(registration.attestationData) : null\n }\n}\n\nexport function parseAuthentication(authentication :AuthenticationEncoded) :AuthenticationParsed {\n return {\n credentialId: authentication.credentialId,\n client: parseClient(authentication.clientData),\n authenticator: parseAuthenticator(authentication.authenticatorData),\n signature: authentication.signature\n }\n}", "export default {\n \"9c835346-796b-4c27-8898-d6032f515cc5\": {\n \"name\": \"Cryptnox FIDO2\"\n },\n \"c5ef55ff-ad9a-4b9f-b580-adebafe026d0\": {\n \"name\": \"YubiKey 5Ci\"\n },\n \"39a5647e-1853-446c-a1f6-a79bae9f5bc7\": {\n \"name\": \"Vancosys Android Authenticator\"\n },\n \"3789da91-f943-46bc-95c3-50ea2012f03a\": {\n \"name\": \"NEOWAVE Winkeo FIDO2\"\n },\n \"fa2b99dc-9e39-4257-8f92-4a30d23c4118\": {\n \"name\": \"YubiKey 5 Series with NFC\"\n },\n \"4e768f2c-5fab-48b3-b300-220eb487752b\": {\n \"name\": \"Hideez Key 4 FIDO2 SDK\"\n },\n \"931327dd-c89b-406c-a81e-ed7058ef36c6\": {\n \"name\": \"Swissbit iShield FIDO2\"\n },\n \"e1a96183-5016-4f24-b55b-e3ae23614cc6\": {\n \"name\": \"ATKey.Pro CTAP2.0\"\n },\n \"08987058-cadc-4b81-b6e1-30de50dcbe96\": {\n \"name\": \"Windows Hello Hardware Authenticator\"\n },\n \"d91c5288-0ef0-49b7-b8ae-21ca0aa6b3f3\": {\n \"name\": \"KEY-ID FIDO2 Authenticator\"\n },\n \"ee041bce-25e5-4cdb-8f86-897fd6418464\": {\n \"name\": \"Feitian ePass FIDO2-NFC Authenticator\"\n },\n \"73bb0cd4-e502-49b8-9c6f-b59445bf720b\": {\n \"name\": \"YubiKey 5 FIPS Series\"\n },\n \"149a2021-8ef6-4133-96b8-81f8d5b7f1f5\": {\n \"name\": \"Security Key by Yubico with NFC\"\n },\n \"3b1adb99-0dfe-46fd-90b8-7f7614a4de2a\": {\n \"name\": \"GoTrust Idem Key FIDO2 Authenticator\"\n },\n \"f8a011f3-8c0a-4d15-8006-17111f9edc7d\": {\n \"name\": \"Security Key by Yubico\"\n },\n \"2c0df832-92de-4be1-8412-88a8f074df4a\": {\n \"name\": \"Feitian FIDO Smart Card\"\n },\n \"c5703116-972b-4851-a3e7-ae1259843399\": {\n \"name\": \"NEOWAVE Badgeo FIDO2\"\n },\n \"820d89ed-d65a-409e-85cb-f73f0578f82a\": {\n \"name\": \"Vancosys iOS Authenticator\"\n },\n \"b6ede29c-3772-412c-8a78-539c1f4c62d2\": {\n \"name\": \"Feitian BioPass FIDO2 Plus Authenticator\"\n },\n \"85203421-48f9-4355-9bc8-8a53846e5083\": {\n \"name\": \"YubiKey 5Ci FIPS\"\n },\n \"d821a7d4-e97c-4cb6-bd82-4237731fd4be\": {\n \"name\": \"Hyper FIDO Bio Security Key\"\n },\n \"516d3969-5a57-5651-5958-4e7a49434167\": {\n \"name\": \"SmartDisplayer BobeePass (NFC-BLE FIDO2 Authenticator)\"\n },\n \"b93fd961-f2e6-462f-b122-82002247de78\": {\n \"name\": \"Android Authenticator with SafetyNet Attestation\"\n },\n \"2fc0579f-8113-47ea-b116-bb5a8db9202a\": {\n \"name\": \"YubiKey 5 Series with NFC\"\n },\n \"9ddd1817-af5a-4672-a2b9-3e3dd95000a9\": {\n \"name\": \"Windows Hello VBS Hardware Authenticator\"\n },\n \"d8522d9f-575b-4866-88a9-ba99fa02f35b\": {\n \"name\": \"YubiKey Bio Series\"\n },\n \"692db549-7ae5-44d5-a1e5-dd20a493b723\": {\n \"name\": \"HID Crescendo Key\"\n },\n \"3e22415d-7fdf-4ea4-8a0c-dd60c4249b9d\": {\n \"name\": \"Feitian iePass FIDO Authenticator\"\n },\n \"aeb6569c-f8fb-4950-ac60-24ca2bbe2e52\": {\n \"name\": \"HID Crescendo C2300\"\n },\n \"9f0d8150-baa5-4c00-9299-ad62c8bb4e87\": {\n \"name\": \"GoTrust Idem Card FIDO2 Authenticator\"\n },\n \"12ded745-4bed-47d4-abaa-e713f51d6393\": {\n \"name\": \"Feitian AllinOne FIDO2 Authenticator\"\n },\n \"88bbd2f0-342a-42e7-9729-dd158be5407a\": {\n \"name\": \"Precision InnaIT Key FIDO 2 Level 2 certified\"\n },\n \"34f5766d-1536-4a24-9033-0e294e510fb0\": {\n \"name\": \"YubiKey 5 Series CTAP2.1 Preview 1 \"\n },\n \"83c47309-aabb-4108-8470-8be838b573cb\": {\n \"name\": \"YubiKey Bio Series (Enterprise Profile)\"\n },\n \"be727034-574a-f799-5c76-0929e0430973\": {\n \"name\": \"Crayonic KeyVault K1 (USB-NFC-BLE FIDO2 Authenticator)\"\n },\n \"b92c3f9a-c014-4056-887f-140a2501163b\": {\n \"name\": \"Security Key by Yubico\"\n },\n \"54d9fee8-e621-4291-8b18-7157b99c5bec\": {\n \"name\": \"HID Crescendo Enabled\"\n },\n \"6028b017-b1d4-4c02-b4b3-afcdafc96bb2\": {\n \"name\": \"Windows Hello Software Authenticator\"\n },\n \"6d44ba9b-f6ec-2e49-b930-0c8fe920cb73\": {\n \"name\": \"Security Key by Yubico with NFC\"\n },\n \"e416201b-afeb-41ca-a03d-2281c28322aa\": {\n \"name\": \"ATKey.Pro CTAP2.1\"\n },\n \"9f77e279-a6e2-4d58-b700-31e5943c6a98\": {\n \"name\": \"Hyper FIDO Pro\"\n },\n \"73402251-f2a8-4f03-873e-3cb6db604b03\": {\n \"name\": \"uTrust FIDO2 Security Key\"\n },\n \"c1f9a0bc-1dd2-404a-b27f-8e29047a43fd\": {\n \"name\": \"YubiKey 5 FIPS Series with NFC\"\n },\n \"504d7149-4e4c-3841-4555-55445a677357\": {\n \"name\": \"WiSECURE AuthTron USB FIDO2 Authenticator\"\n },\n \"cb69481e-8ff7-4039-93ec-0a2729a154a8\": {\n \"name\": \"YubiKey 5 Series\"\n },\n \"ee882879-721c-4913-9775-3dfcce97072a\": {\n \"name\": \"YubiKey 5 Series\"\n },\n \"8c97a730-3f7b-41a6-87d6-1e9b62bda6f0\": {\n \"name\": \"FT-JCOS FIDO Fingerprint Card\"\n },\n \"a1f52be5-dfab-4364-b51c-2bd496b14a56\": {\n \"name\": \"OCTATCO EzFinger2 FIDO2 AUTHENTICATOR\"\n },\n \"3e078ffd-4c54-4586-8baa-a77da113aec5\": {\n \"name\": \"Hideez Key 3 FIDO2\"\n },\n \"d41f5a69-b817-4144-a13c-9ebd6d9254d6\": {\n \"name\": \"ATKey.Card CTAP2.0\"\n },\n \"bc2fe499-0d8e-4ffe-96f3-94a82840cf8c\": {\n \"name\": \"OCTATCO EzQuant FIDO2 AUTHENTICATOR\"\n },\n \"1c086528-58d5-f211-823c-356786e36140\": {\n \"name\": \"Atos CardOS FIDO2\"\n },\n \"77010bd7-212a-4fc9-b236-d2ca5e9d4084\": {\n \"name\": \"Feitian BioPass FIDO2 Authenticator\"\n },\n \"833b721a-ff5f-4d00-bb2e-bdda3ec01e29\": {\n \"name\": \"Feitian ePass FIDO2 Authenticator\"\n }\n}", "import authenticatorMetadata from './authenticatorMetadata.js' //assert {type: 'json'}\nimport * as utils from './utils.js'\n\n\nexport function parseAuthBuffer(authData :ArrayBuffer) {\n console.debug(authData)\n let flags = new DataView(authData.slice(32,33)).getUint8(0)\n console.debug(flags)\n\n // https://w3c.github.io/webauthn/#sctn-authenticator-data\n let parsed :any = {\n rpIdHash: utils.toBase64url(authData.slice(0,32)),\n flags: {\n userPresent: !!(flags & 1),\n //reserved1: !!(flags & 2),\n userVerified: !!(flags & 4),\n backupEligibility: !!(flags & 8),\n backupState: !!(flags & 16),\n //reserved2: !!(flags & 32),\n attestedData: !!(flags & 64),\n extensionsIncluded: !!(flags & 128)\n },\n counter: new DataView(authData.slice(33,37)).getUint32(0, false), // Big-Endian!\n }\n\n if(authData.byteLength > 37) {\n // registration contains additional data\n\n const aaguid = extractAaguid(authData)\n // https://w3c.github.io/webauthn/#attested-credential-data\n //let credentialLength = new DataView(authData.slice(53,55)).getUint16(0, false) // Big-Endian!\n \n parsed = {\n ...parsed,\n aaguid, // bytes 37->53\n name: resolveAuthenticatorName(aaguid)\n // credentialBytes, // bytes 53->55: credential length\n // credentialId: utils.toBase64url(authData.slice(55, 55+credentialLength)),\n //publicKey: until where? ...and it's encoded using a strange format, let's better avoid it\n //extensions: starting where?\n }\n }\n\n return parsed\n}\n\nexport function extractAaguid(authData :ArrayBuffer) :string {\n return formatAaguid(authData.slice(37, 53)) // 16 bytes\n}\n\nfunction formatAaguid(buffer :ArrayBuffer) :string {\n let aaguid = utils.bufferToHex(buffer)\n aaguid = aaguid.substring(0,8) + '-' + aaguid.substring(8,12) + '-' + aaguid.substring(12,16) + '-' + aaguid.substring(16,20) + '-' + aaguid.substring(20,32)\n return aaguid // example: \"d41f5a69-b817-4144-a13c-9ebd6d9254d6\"\n}\n\nexport function resolveAuthenticatorName(aaguid :string) :string {\n const aaguidMetadata = updatedAuthenticatorMetadata ?? authenticatorMetadata //await getAaguidMetadata()\n return aaguidMetadata[aaguid]?.name\n}\n\nlet updatedAuthenticatorMetadata :any = null\n\n// List of AAGUIDs are encoded as JWT here: https://mds.fidoalliance.org/\nexport async function updateDevicesMetadata() {\n // this function is rather resource intensive and time consuming\n // therefore, the result is cached in local storage\n const jwt = await (await fetch(\"https://mds.fidoalliance.org\")).text()\n\n // the response is a JWT including all AAGUIDs and their metadata\n console.debug(jwt)\n\n // let us ignore the JWT verification, since this is solely for descriptive purposes, not signed data\n const payload = jwt.split('.')[1].replaceAll('-', '+').replaceAll('_', '/')\n const json = JSON.parse(atob(payload))\n console.debug(json)\n\n let aaguidMetadata :any = {}\n for(const e of json.entries) {\n if(!e.aaguid || !e.metadataStatement)\n continue\n\n aaguidMetadata[e.aaguid] = {name: e.metadataStatement.description}\n }\n\n console.debug(aaguidMetadata)\n updatedAuthenticatorMetadata = aaguidMetadata\n}\n"], "mappings": "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", "names": ["client_exports", "__export", "authenticate", "isAvailable", "isLocalAuthenticator", "register", "utils_exports", "__export", "bufferToHex", "concatenateBuffers", "isBase64url", "parseBase64url", "parseBuffer", "randomChallenge", "sha256", "toBase64url", "toBuffer", "txt", "c", "buffer", "b", "buffer1", "buffer2", "tmp", "isAvailable", "isLocalAuthenticator", "getAuthAttachment", "authType", "getAlgoName", "num", "register", "username", "challenge", "options", "isBase64url", "creationOptions", "parseBase64url", "sha256", "credential", "response", "registration", "toBase64url", "getTransports", "local", "roaming", "authenticate", "credentialIds", "transports", "authOptions", "id", "auth", "server_exports", "__export", "verifyAuthentication", "verifyRegistration", "verifySignature", "parsers_exports", "__export", "parseAttestation", "parseAuthentication", "parseAuthenticator", "parseClient", "parseRegistration", "authenticatorMetadata_default", "parseAuthBuffer", "authData", "flags", "parsed", "toBase64url", "aaguid", "extractAaguid", "resolveAuthenticatorName", "formatAaguid", "buffer", "bufferToHex", "updatedAuthenticatorMetadata", "authenticatorMetadata_default", "utf8Decoder", "parseClient", "data", "parseBase64url", "parseAuthenticator", "parseAuthBuffer", "parseAttestation", "parseRegistration", "registration", "parseAuthentication", "authentication", "isValid", "validator", "value", "res", "isNotValid", "verifyRegistration", "registrationRaw", "expected", "registration", "parseRegistration", "verifyAuthentication", "authenticationRaw", "credential", "verifySignature", "authentication", "parseAuthentication", "rpId", "expectedRpIdHash", "toBase64url", "sha256", "toBuffer", "getAlgoParams", "algorithm", "parseCryptoKey", "algoParams", "publicKey", "buffer", "parseBase64url", "authenticatorData", "clientData", "signature", "cryptoKey", "clientHash", "comboBuffer", "concatenateBuffers", "signatureBuffer", "convertASN1toRaw", "usignature", "rStart", "rEnd", "sStart", "r", "s"] }