{"id":50390918,"url":"https://github.com/minorglitch/zerofido","last_synced_at":"2026-05-30T18:01:26.488Z","repository":{"id":355010217,"uuid":"1224727687","full_name":"MinorGlitch/zerofido","owner":"MinorGlitch","description":"Passkey and security-key app for Flipper Zero with WebAuthn, FIDO2, U2F, USB HID, and NFC support.","archived":false,"fork":false,"pushed_at":"2026-05-01T11:19:08.000Z","size":2578,"stargazers_count":22,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-01T13:14:05.412Z","etag":null,"topics":["authenticator","ctap2","embedded-c","fap","fido2","fido2-authenticator","fido2-webauth","flipper-zero","flipperzero","passkeys","security-key","u2f","usb-hid","webauthn"],"latest_commit_sha":null,"homepage":"https://github.com/MinorGlitch/zerofido/releases","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MinorGlitch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"buy_me_a_coffee":"astoyanov"}},"created_at":"2026-04-29T15:08:48.000Z","updated_at":"2026-05-01T11:19:12.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MinorGlitch/zerofido","commit_stats":null,"previous_names":["minorglitch/zerofido"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/MinorGlitch/zerofido","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinorGlitch%2Fzerofido","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinorGlitch%2Fzerofido/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinorGlitch%2Fzerofido/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinorGlitch%2Fzerofido/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MinorGlitch","download_url":"https://codeload.github.com/MinorGlitch/zerofido/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinorGlitch%2Fzerofido/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33703065,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authenticator","ctap2","embedded-c","fap","fido2","fido2-authenticator","fido2-webauth","flipper-zero","flipperzero","passkeys","security-key","u2f","usb-hid","webauthn"],"created_at":"2026-05-30T18:01:25.034Z","updated_at":"2026-05-30T18:01:26.480Z","avatar_url":"https://github.com/MinorGlitch.png","language":"C","funding_links":["https://buymeacoffee.com/astoyanov"],"categories":[],"sub_categories":[],"readme":"![License: GPL-3.0-or-later](https://img.shields.io/badge/license-GPL--3.0--or--later-blue)\n![Platform: Flipper Zero](https://img.shields.io/badge/platform-Flipper%20Zero-orange)\n![Protocols: FIDO2 + U2F](https://img.shields.io/badge/protocols-FIDO2%20%2B%20U2F-green)\n\n![ZeroFIDO banner: FIDO2 for Flipper Zero](docs/assets/zerofido-banner.png)\n\n\u003ch3 align=\"center\"\u003e⚠️ ⚠️ Experimental software. Updates may break it. Keep backup sign-in methods. ⚠️ ⚠️\u003c/h3\u003e\n\nZeroFIDO turns a Flipper Zero into a passkey and security-key app. Install the `.fap`,\nopen ZeroFIDO, and approve sign-ins on services that support FIDO2/WebAuthn or legacy U2F.\n\nThe app stores credentials on the Flipper, asks for local approval, supports `ClientPIN`,\nand speaks the CTAP2/FIDO2 protocol used by browsers and security keys. USB HID handles\ndesktop browser flows. NFC builds handle phone flows.\n\nNFC has been tested on iPhone. Android NFC support is next. In the meantime, connect the\nFlipper to the phone over USB when the phone accepts USB security keys.\n\nU2F and FIDO2.0 pass their respective tests in the current FIDO Conformance Tools suite. FIDO2.1\nsupport is in development behind a developer-only build flag. Bug reports, feature requests, and\npull requests are welcome.\n\n## Showcase\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/home-waiting.png\" alt=\"ZeroFIDO waiting for a request\" width=\"400\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/create-passkey.png\" alt=\"ZeroFIDO create passkey approval prompt\" width=\"400\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/credentials-list.png\" alt=\"ZeroFIDO saved credentials list\" width=\"400\"\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003eWaiting for a browser or phone request\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eApproving a new passkey\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eSaved discoverable credentials\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/passkey-detail.png\" alt=\"ZeroFIDO passkey detail screen\" width=\"400\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/settings.png\" alt=\"ZeroFIDO settings screen\" width=\"400\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/pin-menu.png\" alt=\"ZeroFIDO PIN menu\" width=\"400\"\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003ePasskey details\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eOn-device settings\u003c/td\u003e\n    \u003ctd align=\"center\"\u003ePIN management\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/pin-entry.png\" alt=\"ZeroFIDO PIN entry keyboard\" width=\"400\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/reset-confirm.png\" alt=\"ZeroFIDO reset confirmation\" width=\"400\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"docs/screenshots/delete-passkey.png\" alt=\"ZeroFIDO delete passkey confirmation\" width=\"400\"\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003ePIN entry on the Flipper\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eReset confirmation\u003c/td\u003e\n    \u003ctd align=\"center\"\u003eDeleting a saved passkey\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Quick Start\n\n1. Download a release `.fap` from [GitHub Releases](https://github.com/MinorGlitch/zerofido/releases).\n2. Copy it to your Flipper SD card under the Tools apps folder, or install it through qFlipper\n   or Flipper Lab.\n3. Open ZeroFIDO on the Flipper.\n4. Register it as a passkey or security key on a site that supports WebAuthn/FIDO2.\n5. Approve registration and sign-in prompts on the Flipper screen.\n\n## What Works\n\n| Capability | Status |\n| --- | --- |\n| USB HID | Supported in the `usb` and `full` release profiles |\n| NFC | Supported in the `nfc` and `full` release profiles |\n| U2F V2 | Supported |\n| FIDO2.0 / CTAP2.0 | Supported |\n| FIDO2.1 / CTAP2.1 | Developer-only experimental build flag |\n| `ClientPIN` | Supported |\n| Discoverable credentials | Supported |\n| Attestation | Local software attestation when requested |\n\nZeroFIDO builds as an external `.fap` in the Flipper Tools category.\n\n## Daily Use\n\nOpen ZeroFIDO before starting a passkey or security-key flow.\n\n- On desktop, connect the Flipper over USB and use the USB HID build.\n- On phones, hold the Flipper near the NFC reader and use the NFC build. NFC is currently tested on\n  iPhone; Android NFC support is planned. If the phone supports USB security keys, USB is the\n  fallback.\n- When the Flipper asks for approval, confirm only if the site and account look right.\n- If a site asks for a PIN, use the browser or phone prompt. ZeroFIDO keeps the PIN retry state on\n  the Flipper and uses the standard CTAP PIN token flow.\n\n## Settings\n\nZeroFIDO includes an on-device Settings screen.\n\n| Setting | Use |\n| --- | --- |\n| Transport | Choose USB HID or NFC when the build includes both transports. |\n| Attestation | Choose how MakeCredential answers attestation requests. |\n| PIN | Set, change, or manage the ClientPIN used by sites that require user verification. |\n| Auto-accept | Test mode for flows that should not require a touch prompt. Only appears when built with `ZEROFIDO_AUTO_ACCEPT_REQUESTS=1`. |\n\n## Security Model and Limits\n\n- ZeroFIDO runs on general-purpose Flipper Zero hardware. There is no secure element, so physical\n  access to the device changes the risk model.\n- Credential private keys are generated on the device and stored only after being wrapped with the\n  Flipper crypto enclave unique key and a per-record IV. App storage still contains the metadata\n  needed to find and use credentials, including relying-party IDs, user fields, public keys, wrapped\n  private keys, IVs, and counters.\n- Counter floor files and PIN retry state are sealed with the same Flipper crypto APIs. ZeroFIDO\n  protects key material and rollback-sensitive state; it does not encrypt the whole app directory.\n- Attestation is local software attestation, not hardware-backed vendor provenance, and ZeroFIDO is\n  not FIDO Alliance certified.\n- Keep at least one backup sign-in method for accounts you care about.\n\n## Attestation\n\n\u003cdetails\u003e\n\u003csummary\u003eChoosing \u003ccode\u003eAttest: none\u003c/code\u003e or \u003ccode\u003eAttest: packed\u003c/code\u003e\u003c/summary\u003e\n\nZeroFIDO defaults to `Attest: none` and supports two MakeCredential attestation modes from the\non-device Settings screen:\n\n- `Attest: none` returns `fmt: \"none\"` with an empty attestation statement. The credential is still\n  created normally, but ZeroFIDO does not include the local attestation certificate chain or\n  attestation signature.\n- `Attest: packed` allows local software packed attestation when the relying party requests direct\n  attestation. This identifies the ZeroFIDO install, not hardware-backed vendor provenance.\n\nIf the CTAP request includes `attestationFormats` and names a supported format, that explicit\npreference wins over the saved setting. ZeroFIDO currently supports `none` and `packed`.\n\n\u003c/details\u003e\n\n## For Developers\n\n\u003cdetails\u003e\n\u003csummary\u003eDeveloper setup, builds, validation, releases, and certification metadata\u003c/summary\u003e\n\n### Setup\n\nInstall `uv`, then sync the Python tools:\n\n```bash\nuv sync\n```\n\nThe Python toolchain declares Python `3.14+` in `pyproject.toml`. C validation expects\n`clang-format`, `clang-tidy`, `cppcheck`, and a host C compiler.\n\nOn macOS:\n\n```bash\nbrew install llvm cppcheck\n```\n\n### Build Profiles\n\nThe app manifest reads `ZEROFIDO_PROFILE` at build time. The default profile is `usb`, with\nthe stable FIDO2.0 profile enabled by default. Release builds default to\n`ZEROFIDO_RELEASE_DIAGNOSTICS=0`.\n\n| Profile | Build flag | Use |\n| --- | --- | --- |\n| USB HID only | `ZEROFIDO_PROFILE=usb` | Default; desktop browser WebAuthn and U2F testing. |\n| NFC only | `ZEROFIDO_PROFILE=nfc` | Phone and NFC conformance work. |\n| Full | `ZEROFIDO_PROFILE=full` | Both transports in one app. |\n\nRelease-default builds exclude the NFC trace implementation. Diagnostics must opt in:\n\n```bash\nZEROFIDO_PROFILE=nfc ZEROFIDO_RELEASE_DIAGNOSTICS=1 uv run python -m ufbt\n```\n\nBuild a profile:\n\n```bash\nZEROFIDO_PROFILE=nfc uv run python -m ufbt\nZEROFIDO_PROFILE=usb uv run python -m ufbt\nZEROFIDO_PROFILE=full uv run python -m ufbt\n```\n\nBuild and launch on a connected Flipper:\n\n```bash\nZEROFIDO_PROFILE=usb uv run python -m ufbt launch\n```\n\nThe normal build output is `dist/zerofido.fap`.\n\n### Validation\n\nRun the maintained Python tests:\n\n```bash\nuv run python -m unittest discover -s tests -t . -p 'test_*.py'\n```\n\nRun native protocol regressions:\n\n```bash\nuv run python tools/run_protocol_regressions.py\n```\n\nThe native harness checks packed attestation, runtime `Attest: none`, explicit\n`attestationFormats: [\"none\"]`, and required packed-attestation failures.\n\nRun C formatting and analyzers:\n\n```bash\nuv run python tools/check_c.py format\nuv run python tools/check_c.py format --fix\nuv run python tools/check_c.py tidy\nuv run python tools/check_c.py cppcheck\nuv run python tools/check_c.py native\nuv run python tools/check_c.py all\n```\n\nCheck SDK symbols against a local Flipper firmware checkout:\n\n```bash\nuv run python host_tools/check_symbol_gate.py --sdk-root \u003cflipper-firmware-checkout\u003e\n```\n\nCheck and package a built `.fap` with the release export gate:\n\n```bash\nuv run python host_tools/check_symbol_gate.py \\\n  --fap dist/zerofido.fap \\\n  --output-fap dist/zerofido-release.fap\n```\n\n### Host Tools\n\nList and probe FIDO HID devices:\n\n```bash\nuv run python host_tools/ctaphid_probe.py --cmd list\nuv run python host_tools/ctaphid_probe.py --cmd init\nuv run python host_tools/ctaphid_probe.py --cmd getinfo\nuv run python host_tools/ctaphid_probe.py --cmd makecredential\nuv run python host_tools/ctaphid_probe.py --cmd getassertion\n```\n\nRun U2F transport probes:\n\n```bash\nuv run python host_tools/ctaphid_probe.py --cmd u2fversion\nuv run python host_tools/ctaphid_probe.py --cmd u2fregister --u2f-cert-out metadata/u2f-attestation.der\nuv run python host_tools/ctaphid_probe.py --cmd u2finvalidcla\nuv run python host_tools/ctaphid_probe.py --cmd u2fversiondata\nuv run python host_tools/ctaphid_probe.py --cmd u2fauthinvalid\n```\n\nCapture a FIDO2 attestation leaf certificate from `MakeCredential`:\n\n```bash\nuv run python host_tools/ctaphid_probe.py \\\n  --cmd makecredential \\\n  --fido2-cert-out metadata/fido2-attestation.der\n```\n\nCapture NFC trace lines from the Flipper USB CDC console:\n\n```bash\nuv run python host_tools/nfc_trace_console.py --port auto\nuv run python host_tools/nfc_trace_console.py --port \u003cserial-port\u003e --level info --output .tmp/nfc-trace.log\n```\n\nThe iPhone NFC transport notes are in [docs/writeup_ios.md](docs/writeup_ios.md).\n\nCapture reconnecting crash logs from the same CDC console:\n\n```bash\nuv run python tools/flipper_crash_log.py --port auto --output .tmp/flipper-crash.log\n```\n\nPrint firmware footprint data after building:\n\n```bash\nuv run python host_tools/size_ledger.py --artifact dist/zerofido.fap --artifact dist/zerofido-release.fap\n```\n\n### Release Packaging\n\nBuild a release `.fap` for the selected profile and verify that the app exports only\n`zerofido_main`:\n\n```bash\nZEROFIDO_PROFILE=usb \\\nZEROFIDO_RELEASE_DIAGNOSTICS=0 \\\nuv run python host_tools/package_release.py\n```\n\nPackage an existing `dist/zerofido.fap` without rebuilding:\n\n```bash\nuv run python host_tools/package_release.py \\\n  --skip-build \\\n  --fap dist/zerofido.fap \\\n  --output-fap dist/zerofido-release.fap\n```\n\nThe packaged artifact lands at `dist/zerofido-release.fap` by default.\n\n### GitHub Releases\n\nThe `Build profiles` workflow verifies every push and pull request. The `Release` workflow\npublishes GitHub Releases from existing `v*` tags.\n\nCreate and push a tag:\n\n```bash\ngit tag v0.7.0\ngit push origin v0.7.0\n```\n\nThe release workflow builds the `nfc`, `usb`, and `full` profiles with\n`ZEROFIDO_RELEASE_DIAGNOSTICS=0`, packages the stripped `*-release.fap` artifacts, and uploads\n`SHA256SUMS`.\n\nYou can also run the workflow from GitHub Actions with an existing tag such as `v0.7.0`.\n\n### Certification Metadata\n\nMetadata and captured attestation certificates belong to your local certification run. Keep them\nunder `metadata/`; git ignores that directory. The exporter creates `metadata/` and a default\n`metadata/statement.json` when they are missing.\n\n```bash\nuv run python host_tools/export_certification_metadata.py \\\n  --statement metadata/statement.json \\\n  --profile fido2-2.0 \\\n  --client-pin-state unset\n\nuv run python host_tools/export_certification_metadata.py \\\n  --statement metadata/statement.json \\\n  --profile fido2-2.1-experimental \\\n  --client-pin-state unset\n```\n\nThe `fido2-2.1-experimental` metadata profile is for development builds created with\n`ZEROFIDO_DEV_FIDO2_1=1`; release builds ship the FIDO2.0 profile.\n\nThe default outputs are:\n\n- `metadata/metadata-ctap20.json`\n- `metadata/metadata-ctap21-experimental.json`\n\nFor FIDO2 packed attestation chain checks, export metadata with the certificate returned by\nthe same device:\n\n```bash\nuv run python host_tools/ctaphid_probe.py \\\n  --cmd makecredential \\\n  --fido2-cert-out metadata/fido2-attestation.der\n\nuv run python host_tools/export_certification_metadata.py \\\n  --statement metadata/statement.json \\\n  --profile fido2-2.0 \\\n  --fido2-attestation-cert metadata/fido2-attestation.der\n```\n\nFor U2F, export metadata from the certificate returned by U2F Register:\n\n```bash\nuv run python host_tools/ctaphid_probe.py \\\n  --cmd u2fregister \\\n  --u2f-cert-out metadata/u2f-attestation.der\n\nuv run python host_tools/export_certification_metadata.py \\\n  --statement metadata/statement.json \\\n  --profile u2f \\\n  --u2f-attestation-cert metadata/u2f-attestation.der\n```\n\nIf U2F metadata reports an attestation SKID or certificate-path mismatch, regenerate\n`metadata/u2f-attestation.der` and `metadata/metadata-u2f.json` from the same device build you are\ntesting. Older builds regenerated U2F attestation during reset, so metadata captured before a reset\ncan be stale.\n\nIf the conformance tool changes PIN state, regenerate metadata with the matching\n`--client-pin-state` before rerunning that profile.\n\n\u003c/details\u003e\n\n## Support\n\nZeroFIDO is built and maintained in spare time. If it helped you, you can support the work here:\n\n[![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-astoyanov-FFDD00?style=for-the-badge\u0026logo=buymeacoffee\u0026logoColor=000)](https://buymeacoffee.com/astoyanov)\n\nSupport is optional and does not affect releases, issues, or support requests.\n\n## License\n\nZeroFIDO uses the GNU General Public License, version 3 or later. See [`LICENSE`](LICENSE).\n\nDependency and provenance notes live in [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminorglitch%2Fzerofido","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminorglitch%2Fzerofido","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminorglitch%2Fzerofido/lists"}