diff --git a/CHANGELOG.md b/CHANGELOG.md
index 433205c..29b0b95 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,8 +4,18 @@ All notable changes are documented here.
## Unreleased
+## 0.2.0 - 2026-08-19
+
- Added auditable TOTP time travel using live time, bounded positive or negative period offsets, or a frozen local date/time interpreted in an explicit IANA timezone.
- Added DST gap rejection and earlier/later disambiguation for repeated wall-clock times, with effective local time, UTC instant, Unix seconds and TOTP counter diagnostics.
+- Added an OTP timeline, bounded clock-drift search, JSON interoperability vectors, and custom RFC 6238 T0 support with provisioning-portability warnings.
+- Added complete Google Authenticator multi-QR batch assembly and explicit Aegis, 2FAS, andOTP and legacy FreeOTP JSON importers.
+- Added the Apache-2.0 jsQR decoder as a bundled fallback when `BarcodeDetector` is missing or cannot decode an image.
+- Added collection health reports for reused secrets, duplicate labels, short secrets and non-default timing.
+- Added a versioned encrypted-backup format using PBKDF2-HMAC-SHA-256 and authenticated AES-256-GCM, with no persistent browser storage.
+- Added layered WebAuthn registration verification for none, packed/self, FIDO U2F, TPM 2.0, Android Key and Apple anonymous attestation statements.
+- Added explicit local import and JWS verification of FIDO Metadata Service v3 snapshots, while keeping signer-chain trust separate and unestablished by default.
+- Updated the transitive `nanoid` build dependency to 3.3.18; `npm audit` reports no known vulnerabilities.
## 0.1.0 - 2026-08-19
diff --git a/LICENSES/README.md b/LICENSES/README.md
index 8e2172e..8149bb1 100644
--- a/LICENSES/README.md
+++ b/LICENSES/README.md
@@ -2,4 +2,4 @@
OTP & Passkey Tools is `GPL-3.0-or-later`; the full project licence is at `../LICENSE`.
-`THIRD_PARTY_NOTICES.md` identifies shipped packages and adapted algorithms. Release preparation collates the exact installed runtime package licence files into `npm-runtime-licenses.txt`. `QRCode-MIT.txt` preserves the licence for the QR construction algorithm rewritten in this project.
+`THIRD_PARTY_NOTICES.md` identifies shipped packages and adapted algorithms. Release preparation collates the exact installed runtime package licence files, including jsQR's Apache-2.0 licence, into `npm-runtime-licenses.txt`. `QRCode-MIT.txt` preserves the licence for the QR construction algorithm rewritten in this project.
diff --git a/README.md b/README.md
index b59f18c..5c8cc15 100644
--- a/README.md
+++ b/README.md
@@ -9,11 +9,16 @@ Authentication material stays in the active tab. The application has no backend,
- RFC 4226 HOTP and RFC 6238 TOTP generation and bounded diagnostic verification using SHA-1, SHA-256 or SHA-512, with exact 64-bit counters and preserved leading zeroes.
- Strict `otpauth://` parsing/serialization, random secret generation, masked values, interoperability findings, live period display and a project-owned QR encoder.
- Auditable TOTP time travel using positive/negative period offsets or a frozen local date/time in an explicit IANA timezone, including DST-gap rejection and repeated-time disambiguation.
+- Bounded clock-drift search, past/current/future OTP timelines, downloadable interoperability vectors and custom RFC 6238 T0 diagnostics.
- RFC 6287 OCRA-1 suite parsing and computation for counter, numeric/alphanumeric/hex challenge, PIN/password hash, session and timestamp inputs. Official RFC interoperability vectors cover SHA-1, SHA-256 and SHA-512 paths.
-- Import of line-delimited provisioning URIs, Google Authenticator migration QR payloads, the documented CSV shape and RFC 6030 PSKC files containing plain secrets. Encrypted PSKC is rejected rather than guessed.
-- Explicit URI-list and CSV export with an unencrypted-secret warning.
+- Import of line-delimited provisioning URIs, complete Google Authenticator multi-QR batches, Aegis plaintext JSON, 2FAS JSON, andOTP plaintext JSON, legacy FreeOTP JSON, the documented CSV shape and RFC 6030 PSKC files containing plain secrets. Unsupported encrypted vendor formats are rejected rather than guessed.
+- Cross-browser QR image decoding through native `BarcodeDetector` when available and a bundled jsQR fallback everywhere else.
+- Credential-collection health reports for duplicated secrets/labels, weak secret lengths and non-default timing.
+- Explicit URI-list and CSV export with an unencrypted-secret warning, plus a versioned authenticated encrypted backup using PBKDF2-SHA-256 and AES-256-GCM.
- Bounded CBOR, `clientDataJSON`, authenticator-data and attestation-object inspection, including flags, RP ID hash, counter, AAGUID, credential ID, COSE key and extensions.
- Layered assertion verification for challenge, origin, cross-origin state, RP ID hash, user presence/verification, signature counter, and ES256, RS256, PS256 or Ed25519 signatures.
+- Layered registration verification for none, packed/self, FIDO U2F, TPM 2.0, Android Key and Apple anonymous attestation, including certificate signatures and format-specific credential/challenge bindings.
+- Explicit offline FIDO Metadata Service v3 JWT snapshot import, signer verification, AAGUID matching and authenticator status display. Imported metadata never silently establishes a trust root.
- Serializable registration/request option examples, browser capability diagnostics and an ephemeral in-memory live ceremony lab.
## Security boundary
@@ -26,7 +31,7 @@ https://auth.toolbox.add-ideas.de/
The same immutable release can be served there, top-level, with RP ID `auth.toolbox.add-ideas.de`. The RP ID is never widened to `add-ideas.de`, and arbitrary RP IDs can only be inspected offline.
-Raw CTAP/token administration is not claimed: browsers expose ordinary WebAuthn but block the FIDO HID usage page from WebHID. Camera and USB permissions are not requested. QR images can be selected locally when the browser implements `BarcodeDetector`; provisioning text can always be pasted.
+Raw CTAP/token administration is not claimed: browsers expose ordinary WebAuthn but block the FIDO HID usage page from WebHID. Camera and USB permissions are not requested. QR images can be selected locally in current browsers; provisioning text can always be pasted.
See [SECURITY.md](SECURITY.md) for the threat model and limitations.
@@ -45,7 +50,7 @@ The Vite base is relative, so both `/` and nested paths work. `npm run toolbox:c
## Static deployment
-Serve `dist/` or the contents of `release/auth-tools-0.1.0.zip` over HTTPS. Recommended response headers:
+Serve `dist/` or the contents of `release/auth-tools-0.2.0.zip` over HTTPS. Recommended response headers:
```text
Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; worker-src 'self' blob:; manifest-src 'self'
@@ -62,9 +67,9 @@ For Portal integration, pin the immutable Gitea release ZIP and SHA-256 in `tool
- This is an engineering and interoperability workbench, not a certified authenticator, relying-party server, password manager, FIDO certification tool or recovery system.
- Live credentials are forgotten on reload and cannot be exported by WebAuthn design.
-- Attestation structures are decoded, but 0.1.0 does not establish attestation trust or silently download FIDO Metadata Service data. Assertion signatures are verified only with the explicitly supplied/created credential key.
-- Google multi-QR batches must all be supplied; the current UI reviews one payload at a time. Google migration export and encrypted PSKC decryption are not claimed.
-- CSV and URI exports contain raw OTP seeds. There is no encrypted vault format in this app.
+- Attestation cryptography and metadata status are evidence, not automatic device trust. No trust root or policy is bundled, and FIDO metadata is never downloaded silently.
+- All parts of a Google multi-QR batch must be supplied. Google migration export, Aegis password-vault decryption, FreeOTP 2.x encrypted XML and encrypted PSKC decryption are not claimed.
+- CSV and URI exports contain raw OTP seeds. The encrypted export is a portable backup file, not a persistent browser vault or recovery service.
- QR generation supports byte-mode error-correction M through version 10. Larger provisioning records remain available as text exports.
## Licence
diff --git a/SECURITY.md b/SECURITY.md
index c8bb1df..2f81840 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,14 +4,14 @@
All inputs are processed in the browser tab. There are no application `fetch`, WebSocket, beacon, analytics, service-worker, credential-storage or remote-metadata paths. OTP secrets, OCRA PIN input, imported files, WebAuthn responses and live test credential metadata are React/session memory and disappear on reload or **Clear session**.
-Downloads and clipboard writes require a user action. Exports are not encrypted. The UI masks OTP secrets and provisioning URIs by default, but masking is not memory protection.
+Downloads and clipboard writes require a user action. URI/CSV exports are not encrypted; the dedicated encrypted format uses an authenticated cipher and a user-supplied password. The UI masks OTP secrets and provisioning URIs by default, but masking is not memory protection.
## Trust boundaries
- The static release and its hosting origin are trusted code. A compromised host can alter JavaScript and steal subsequently entered material; verify the release SHA-256 when this matters.
- Imported URIs, CSV, XML, protobuf, JSON, Base64url and CBOR are untrusted. Size/depth/count limits are applied before or during decoding. Imported text is rendered by React, never as markup. The only generated markup insertion is the project-owned QR SVG serializer, which receives an already serialized provisioning URI and emits path coordinates only.
- WebAuthn client data is verified as exact strings/bytes. Origins and RP IDs are not suffix-matched. The expected challenge is caller-supplied ceremony state; the tool cannot prove that a server generated or consumed it once.
-- Signature verification establishes consistency with the supplied COSE public key, not account ownership or attestation trust.
+- Assertion signatures establish consistency with the supplied COSE public key. Attestation checks establish format-specific cryptographic bindings; certificate-chain trust and authenticator policy remain separate. Imported FIDO metadata has its JWS signer checked but does not silently install a trust root.
## Origin isolation
@@ -19,22 +19,25 @@ Downloads and clipboard writes require a user action. Exports are not encrypted.
## Cryptography
-HMAC, digest, random generation, public-key import and signature verification use the browser Web Cryptography API. No custom cryptographic primitive is implemented. OTP dynamic truncation and OCRA data-input assembly are project code covered by RFC vectors.
+HMAC, digest, random generation, PBKDF2 key derivation, AES-GCM authenticated encryption, public-key import and signature verification use the browser Web Cryptography API. No custom cryptographic primitive is implemented. OTP dynamic truncation, OCRA data-input assembly and bounded DER/TPM structure interpretation are project code covered by tests.
+
+The encrypted backup format uses a 16-byte random salt, 600,000 PBKDF2-HMAC-SHA-256 iterations, a 256-bit AES-GCM key, a 96-bit random IV, a 128-bit authentication tag and authenticated version/KDF/cipher metadata. Decryption failures do not expose partial plaintext. It is an export format, not persistent storage.
SHA-1 remains available only where HOTP/TOTP/OCRA interoperability standards require it; it is used inside HMAC or as an explicitly selected OCRA PIN digest, not as a collision-resistant document signature.
## Parser limits
- Provisioning URI: 16 KiB.
-- Migration/CSV/PSKC input: 4 MiB.
+- Migration/CSV/PSKC input: 4 MiB; vendor/encrypted backup input: 16 MiB.
- Google protobuf: bounded input, varints at most 10 bytes, supported wire types only.
- CBOR: 4 MiB, depth 32, 10,000 items, definite lengths only, duplicate map keys rejected.
- OTP secret: 1 KiB; random generation: 16–1,024 bytes.
-- Verification windows: TOTP 100 steps maximum; HOTP 10,000 counters maximum.
-- QR encoder: version 10 maximum.
+- Verification windows: routine TOTP 100 steps maximum; explicit drift search 10,000 periods; HOTP 10,000 counters maximum.
+- QR encoder: version 10 maximum. QR decoder: 16 MiB, 4096 px per side and 16 megapixels.
+- FIDO Metadata BLOB: 32 MiB, 100,000 entries and 20 signer certificates maximum.
-## Not a vault or identity provider
+## Not persistent storage or an identity provider
-Do not use this app as the only copy of a credential. It does not offer encrypted persistence, recovery codes, account recovery, server-side challenge state, rate limiting, audit logging, device attestation policy, FIDO certification, or phishing protection outside normal browser WebAuthn behavior.
+Do not use this app as the only copy of a credential. It does not offer browser persistence, recovery codes, account recovery, server-side challenge state, rate limiting, audit logging, a preconfigured device-attestation trust policy, FIDO certification, or phishing protection outside normal browser WebAuthn behavior.
Report vulnerabilities through the repository issue tracker without including real secrets or production assertions.
diff --git a/SOURCE.md b/SOURCE.md
index 2901bf2..2dd2b8a 100644
--- a/SOURCE.md
+++ b/SOURCE.md
@@ -1,8 +1,8 @@
# Corresponding source and provenance
-The corresponding source for OTP & Passkey Tools 0.1.0 will be published at:
+The corresponding source for OTP & Passkey Tools 0.2.0 is published at:
-https://git.add-ideas.de/lotobo/auth-tools/src/tag/v0.1.0
+https://git.add-ideas.de/lotobo/auth-tools/src/tag/v0.2.0
Build that tag with Node.js 22 and the exact `package-lock.json`:
@@ -18,14 +18,17 @@ No generated bundle is the preferred source form. No runtime code, metadata or c
| Source | Revision | Use |
| -------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------- |
| Toolbox SDK | `ef2dab4b46c61812c9a877d8a19fe497b4a4630a`, packages 0.2.3 | manifest, context, shell and build checks |
-| Toolbox Portal | `5ed7134d42f0b563bc47a1572107ea94994dfe3c`, tag v0.10.0 | release and UX integration contract |
+| Toolbox Portal | tag v0.12.0 | release and UX integration contract |
| RFC 4226 | December 2005 | HOTP semantics and vectors |
| RFC 6238 | May 2011 | TOTP semantics and vectors |
| RFC 6287 | June 2011 | OCRA suite grammar, semantics and vectors |
| RFC 6030 | October 2010 | bounded plain-secret PSKC import |
| Google Authenticator migration protobuf | observed public interchange schema | local import only; unknown fields are skipped safely |
+| Aegis vault specification/importer sources | upstream `master`, accessed 19 August 2026 | bounded plaintext Aegis, andOTP, 2FAS and FreeOTP migration |
| Web Authentication | W3C WebAuthn Level 3 Recommendation, 13 January 2026 | client/authenticator structures and ceremony expectations |
+| FIDO Metadata Service | v3.1 Proposed Standard, 21 May 2025 | explicit offline Metadata BLOB import and status interpretation |
| RFC 8949 / RFC 9052 / RFC 8152 registrations | published versions | bounded CBOR and COSE key interpretation |
| QR Code for JavaScript | Kazuhiko Arase, 2009 | QR construction algorithm rewritten in TypeScript under MIT terms |
+| jsQR | 1.4.0 | bundled cross-browser QR image decoder under Apache-2.0 |
The OCRA implementation was authored from the normative RFC definition and tested with its published interoperability values; the RFC Java reference implementation is not included. The QR module is an acknowledged clean TypeScript rewrite of the MIT-licensed construction algorithm, with deliberately bounded version support.
diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md
index 36278cb..bb54595 100644
--- a/THIRD_PARTY_NOTICES.md
+++ b/THIRD_PARTY_NOTICES.md
@@ -8,10 +8,11 @@ The release preparation step collates licence files for the exact locked runtime
| -------------------------------- | ------- | ---------- | ------------------------------- | ------------------------------------------- |
| `@add-ideas/toolbox-contract` | 0.2.3 | Apache-2.0 | manifest and context contract | https://git.add-ideas.de/lotobo/toolbox-sdk |
| `@add-ideas/toolbox-shell-react` | 0.2.3 | Apache-2.0 | shared shell, theme and actions | https://git.add-ideas.de/lotobo/toolbox-sdk |
+| `jsqr` | 1.4.0 | Apache-2.0 | local QR image decoding | https://github.com/cozmo/jsQR |
| `react` | 19.2.6 | MIT | application UI | https://github.com/facebook/react |
| `react-dom` | 19.2.6 | MIT | browser rendering | https://github.com/facebook/react |
-`scheduler`, distributed by the React project under MIT, is the only transitive runtime package.
+`scheduler`, distributed by the React project under MIT, is the only transitive runtime package. Exact licence texts, including jsQR's Apache-2.0 terms, are collated from the locked install into the release.
## QR construction
diff --git a/package-lock.json b/package-lock.json
index 8dd7222..3a277ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,16 +1,17 @@
{
"name": "auth-tools",
- "version": "0.1.0",
+ "version": "0.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "auth-tools",
- "version": "0.1.0",
+ "version": "0.2.0",
"license": "GPL-3.0-or-later",
"dependencies": {
"@add-ideas/toolbox-contract": "0.2.3",
"@add-ideas/toolbox-shell-react": "0.2.3",
+ "jsqr": "1.4.0",
"react": "19.2.6",
"react-dom": "19.2.6"
},
@@ -2662,6 +2663,12 @@
"node": ">=6"
}
},
+ "node_modules/jsqr": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz",
+ "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==",
+ "license": "Apache-2.0"
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -3047,9 +3054,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.16",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
- "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"dev": true,
"funding": [
{
diff --git a/package.json b/package.json
index 16f3828..2d2b699 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "auth-tools",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "Inspect and test OTP and WebAuthn authentication locally in the browser.",
"license": "GPL-3.0-or-later",
"author": "Albrecht Degering",
@@ -41,9 +41,13 @@
"dependencies": {
"@add-ideas/toolbox-contract": "0.2.3",
"@add-ideas/toolbox-shell-react": "0.2.3",
+ "jsqr": "1.4.0",
"react": "19.2.6",
"react-dom": "19.2.6"
},
+ "overrides": {
+ "nanoid": "3.3.18"
+ },
"devDependencies": {
"@add-ideas/toolbox-testkit": "0.2.3",
"@eslint/js": "10.0.1",
diff --git a/public/CHANGELOG.md b/public/CHANGELOG.md
index 433205c..29b0b95 100644
--- a/public/CHANGELOG.md
+++ b/public/CHANGELOG.md
@@ -4,8 +4,18 @@ All notable changes are documented here.
## Unreleased
+## 0.2.0 - 2026-08-19
+
- Added auditable TOTP time travel using live time, bounded positive or negative period offsets, or a frozen local date/time interpreted in an explicit IANA timezone.
- Added DST gap rejection and earlier/later disambiguation for repeated wall-clock times, with effective local time, UTC instant, Unix seconds and TOTP counter diagnostics.
+- Added an OTP timeline, bounded clock-drift search, JSON interoperability vectors, and custom RFC 6238 T0 support with provisioning-portability warnings.
+- Added complete Google Authenticator multi-QR batch assembly and explicit Aegis, 2FAS, andOTP and legacy FreeOTP JSON importers.
+- Added the Apache-2.0 jsQR decoder as a bundled fallback when `BarcodeDetector` is missing or cannot decode an image.
+- Added collection health reports for reused secrets, duplicate labels, short secrets and non-default timing.
+- Added a versioned encrypted-backup format using PBKDF2-HMAC-SHA-256 and authenticated AES-256-GCM, with no persistent browser storage.
+- Added layered WebAuthn registration verification for none, packed/self, FIDO U2F, TPM 2.0, Android Key and Apple anonymous attestation statements.
+- Added explicit local import and JWS verification of FIDO Metadata Service v3 snapshots, while keeping signer-chain trust separate and unestablished by default.
+- Updated the transitive `nanoid` build dependency to 3.3.18; `npm audit` reports no known vulnerabilities.
## 0.1.0 - 2026-08-19
diff --git a/public/LICENSES/README.md b/public/LICENSES/README.md
index 8e2172e..8149bb1 100644
--- a/public/LICENSES/README.md
+++ b/public/LICENSES/README.md
@@ -2,4 +2,4 @@
OTP & Passkey Tools is `GPL-3.0-or-later`; the full project licence is at `../LICENSE`.
-`THIRD_PARTY_NOTICES.md` identifies shipped packages and adapted algorithms. Release preparation collates the exact installed runtime package licence files into `npm-runtime-licenses.txt`. `QRCode-MIT.txt` preserves the licence for the QR construction algorithm rewritten in this project.
+`THIRD_PARTY_NOTICES.md` identifies shipped packages and adapted algorithms. Release preparation collates the exact installed runtime package licence files, including jsQR's Apache-2.0 licence, into `npm-runtime-licenses.txt`. `QRCode-MIT.txt` preserves the licence for the QR construction algorithm rewritten in this project.
diff --git a/public/LICENSES/npm-runtime-licenses.txt b/public/LICENSES/npm-runtime-licenses.txt
index 709ea6d..7381b77 100644
--- a/public/LICENSES/npm-runtime-licenses.txt
+++ b/public/LICENSES/npm-runtime-licenses.txt
@@ -398,6 +398,216 @@ Installed from: node_modules/@add-ideas/toolbox-shell-react
limitations under the License.
+==============================================================================
+jsqr@1.4.0
+Declared licence: Apache-2.0
+Installed from: node_modules/jsqr
+==============================================================================
+--- LICENSE ---
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
==============================================================================
react@19.2.6
Declared licence: MIT
diff --git a/public/README.md b/public/README.md
index b59f18c..5c8cc15 100644
--- a/public/README.md
+++ b/public/README.md
@@ -9,11 +9,16 @@ Authentication material stays in the active tab. The application has no backend,
- RFC 4226 HOTP and RFC 6238 TOTP generation and bounded diagnostic verification using SHA-1, SHA-256 or SHA-512, with exact 64-bit counters and preserved leading zeroes.
- Strict `otpauth://` parsing/serialization, random secret generation, masked values, interoperability findings, live period display and a project-owned QR encoder.
- Auditable TOTP time travel using positive/negative period offsets or a frozen local date/time in an explicit IANA timezone, including DST-gap rejection and repeated-time disambiguation.
+- Bounded clock-drift search, past/current/future OTP timelines, downloadable interoperability vectors and custom RFC 6238 T0 diagnostics.
- RFC 6287 OCRA-1 suite parsing and computation for counter, numeric/alphanumeric/hex challenge, PIN/password hash, session and timestamp inputs. Official RFC interoperability vectors cover SHA-1, SHA-256 and SHA-512 paths.
-- Import of line-delimited provisioning URIs, Google Authenticator migration QR payloads, the documented CSV shape and RFC 6030 PSKC files containing plain secrets. Encrypted PSKC is rejected rather than guessed.
-- Explicit URI-list and CSV export with an unencrypted-secret warning.
+- Import of line-delimited provisioning URIs, complete Google Authenticator multi-QR batches, Aegis plaintext JSON, 2FAS JSON, andOTP plaintext JSON, legacy FreeOTP JSON, the documented CSV shape and RFC 6030 PSKC files containing plain secrets. Unsupported encrypted vendor formats are rejected rather than guessed.
+- Cross-browser QR image decoding through native `BarcodeDetector` when available and a bundled jsQR fallback everywhere else.
+- Credential-collection health reports for duplicated secrets/labels, weak secret lengths and non-default timing.
+- Explicit URI-list and CSV export with an unencrypted-secret warning, plus a versioned authenticated encrypted backup using PBKDF2-SHA-256 and AES-256-GCM.
- Bounded CBOR, `clientDataJSON`, authenticator-data and attestation-object inspection, including flags, RP ID hash, counter, AAGUID, credential ID, COSE key and extensions.
- Layered assertion verification for challenge, origin, cross-origin state, RP ID hash, user presence/verification, signature counter, and ES256, RS256, PS256 or Ed25519 signatures.
+- Layered registration verification for none, packed/self, FIDO U2F, TPM 2.0, Android Key and Apple anonymous attestation, including certificate signatures and format-specific credential/challenge bindings.
+- Explicit offline FIDO Metadata Service v3 JWT snapshot import, signer verification, AAGUID matching and authenticator status display. Imported metadata never silently establishes a trust root.
- Serializable registration/request option examples, browser capability diagnostics and an ephemeral in-memory live ceremony lab.
## Security boundary
@@ -26,7 +31,7 @@ https://auth.toolbox.add-ideas.de/
The same immutable release can be served there, top-level, with RP ID `auth.toolbox.add-ideas.de`. The RP ID is never widened to `add-ideas.de`, and arbitrary RP IDs can only be inspected offline.
-Raw CTAP/token administration is not claimed: browsers expose ordinary WebAuthn but block the FIDO HID usage page from WebHID. Camera and USB permissions are not requested. QR images can be selected locally when the browser implements `BarcodeDetector`; provisioning text can always be pasted.
+Raw CTAP/token administration is not claimed: browsers expose ordinary WebAuthn but block the FIDO HID usage page from WebHID. Camera and USB permissions are not requested. QR images can be selected locally in current browsers; provisioning text can always be pasted.
See [SECURITY.md](SECURITY.md) for the threat model and limitations.
@@ -45,7 +50,7 @@ The Vite base is relative, so both `/` and nested paths work. `npm run toolbox:c
## Static deployment
-Serve `dist/` or the contents of `release/auth-tools-0.1.0.zip` over HTTPS. Recommended response headers:
+Serve `dist/` or the contents of `release/auth-tools-0.2.0.zip` over HTTPS. Recommended response headers:
```text
Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; worker-src 'self' blob:; manifest-src 'self'
@@ -62,9 +67,9 @@ For Portal integration, pin the immutable Gitea release ZIP and SHA-256 in `tool
- This is an engineering and interoperability workbench, not a certified authenticator, relying-party server, password manager, FIDO certification tool or recovery system.
- Live credentials are forgotten on reload and cannot be exported by WebAuthn design.
-- Attestation structures are decoded, but 0.1.0 does not establish attestation trust or silently download FIDO Metadata Service data. Assertion signatures are verified only with the explicitly supplied/created credential key.
-- Google multi-QR batches must all be supplied; the current UI reviews one payload at a time. Google migration export and encrypted PSKC decryption are not claimed.
-- CSV and URI exports contain raw OTP seeds. There is no encrypted vault format in this app.
+- Attestation cryptography and metadata status are evidence, not automatic device trust. No trust root or policy is bundled, and FIDO metadata is never downloaded silently.
+- All parts of a Google multi-QR batch must be supplied. Google migration export, Aegis password-vault decryption, FreeOTP 2.x encrypted XML and encrypted PSKC decryption are not claimed.
+- CSV and URI exports contain raw OTP seeds. The encrypted export is a portable backup file, not a persistent browser vault or recovery service.
- QR generation supports byte-mode error-correction M through version 10. Larger provisioning records remain available as text exports.
## Licence
diff --git a/public/SECURITY.md b/public/SECURITY.md
index c8bb1df..2f81840 100644
--- a/public/SECURITY.md
+++ b/public/SECURITY.md
@@ -4,14 +4,14 @@
All inputs are processed in the browser tab. There are no application `fetch`, WebSocket, beacon, analytics, service-worker, credential-storage or remote-metadata paths. OTP secrets, OCRA PIN input, imported files, WebAuthn responses and live test credential metadata are React/session memory and disappear on reload or **Clear session**.
-Downloads and clipboard writes require a user action. Exports are not encrypted. The UI masks OTP secrets and provisioning URIs by default, but masking is not memory protection.
+Downloads and clipboard writes require a user action. URI/CSV exports are not encrypted; the dedicated encrypted format uses an authenticated cipher and a user-supplied password. The UI masks OTP secrets and provisioning URIs by default, but masking is not memory protection.
## Trust boundaries
- The static release and its hosting origin are trusted code. A compromised host can alter JavaScript and steal subsequently entered material; verify the release SHA-256 when this matters.
- Imported URIs, CSV, XML, protobuf, JSON, Base64url and CBOR are untrusted. Size/depth/count limits are applied before or during decoding. Imported text is rendered by React, never as markup. The only generated markup insertion is the project-owned QR SVG serializer, which receives an already serialized provisioning URI and emits path coordinates only.
- WebAuthn client data is verified as exact strings/bytes. Origins and RP IDs are not suffix-matched. The expected challenge is caller-supplied ceremony state; the tool cannot prove that a server generated or consumed it once.
-- Signature verification establishes consistency with the supplied COSE public key, not account ownership or attestation trust.
+- Assertion signatures establish consistency with the supplied COSE public key. Attestation checks establish format-specific cryptographic bindings; certificate-chain trust and authenticator policy remain separate. Imported FIDO metadata has its JWS signer checked but does not silently install a trust root.
## Origin isolation
@@ -19,22 +19,25 @@ Downloads and clipboard writes require a user action. Exports are not encrypted.
## Cryptography
-HMAC, digest, random generation, public-key import and signature verification use the browser Web Cryptography API. No custom cryptographic primitive is implemented. OTP dynamic truncation and OCRA data-input assembly are project code covered by RFC vectors.
+HMAC, digest, random generation, PBKDF2 key derivation, AES-GCM authenticated encryption, public-key import and signature verification use the browser Web Cryptography API. No custom cryptographic primitive is implemented. OTP dynamic truncation, OCRA data-input assembly and bounded DER/TPM structure interpretation are project code covered by tests.
+
+The encrypted backup format uses a 16-byte random salt, 600,000 PBKDF2-HMAC-SHA-256 iterations, a 256-bit AES-GCM key, a 96-bit random IV, a 128-bit authentication tag and authenticated version/KDF/cipher metadata. Decryption failures do not expose partial plaintext. It is an export format, not persistent storage.
SHA-1 remains available only where HOTP/TOTP/OCRA interoperability standards require it; it is used inside HMAC or as an explicitly selected OCRA PIN digest, not as a collision-resistant document signature.
## Parser limits
- Provisioning URI: 16 KiB.
-- Migration/CSV/PSKC input: 4 MiB.
+- Migration/CSV/PSKC input: 4 MiB; vendor/encrypted backup input: 16 MiB.
- Google protobuf: bounded input, varints at most 10 bytes, supported wire types only.
- CBOR: 4 MiB, depth 32, 10,000 items, definite lengths only, duplicate map keys rejected.
- OTP secret: 1 KiB; random generation: 16–1,024 bytes.
-- Verification windows: TOTP 100 steps maximum; HOTP 10,000 counters maximum.
-- QR encoder: version 10 maximum.
+- Verification windows: routine TOTP 100 steps maximum; explicit drift search 10,000 periods; HOTP 10,000 counters maximum.
+- QR encoder: version 10 maximum. QR decoder: 16 MiB, 4096 px per side and 16 megapixels.
+- FIDO Metadata BLOB: 32 MiB, 100,000 entries and 20 signer certificates maximum.
-## Not a vault or identity provider
+## Not persistent storage or an identity provider
-Do not use this app as the only copy of a credential. It does not offer encrypted persistence, recovery codes, account recovery, server-side challenge state, rate limiting, audit logging, device attestation policy, FIDO certification, or phishing protection outside normal browser WebAuthn behavior.
+Do not use this app as the only copy of a credential. It does not offer browser persistence, recovery codes, account recovery, server-side challenge state, rate limiting, audit logging, a preconfigured device-attestation trust policy, FIDO certification, or phishing protection outside normal browser WebAuthn behavior.
Report vulnerabilities through the repository issue tracker without including real secrets or production assertions.
diff --git a/public/SOURCE.md b/public/SOURCE.md
index 2901bf2..2dd2b8a 100644
--- a/public/SOURCE.md
+++ b/public/SOURCE.md
@@ -1,8 +1,8 @@
# Corresponding source and provenance
-The corresponding source for OTP & Passkey Tools 0.1.0 will be published at:
+The corresponding source for OTP & Passkey Tools 0.2.0 is published at:
-https://git.add-ideas.de/lotobo/auth-tools/src/tag/v0.1.0
+https://git.add-ideas.de/lotobo/auth-tools/src/tag/v0.2.0
Build that tag with Node.js 22 and the exact `package-lock.json`:
@@ -18,14 +18,17 @@ No generated bundle is the preferred source form. No runtime code, metadata or c
| Source | Revision | Use |
| -------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------- |
| Toolbox SDK | `ef2dab4b46c61812c9a877d8a19fe497b4a4630a`, packages 0.2.3 | manifest, context, shell and build checks |
-| Toolbox Portal | `5ed7134d42f0b563bc47a1572107ea94994dfe3c`, tag v0.10.0 | release and UX integration contract |
+| Toolbox Portal | tag v0.12.0 | release and UX integration contract |
| RFC 4226 | December 2005 | HOTP semantics and vectors |
| RFC 6238 | May 2011 | TOTP semantics and vectors |
| RFC 6287 | June 2011 | OCRA suite grammar, semantics and vectors |
| RFC 6030 | October 2010 | bounded plain-secret PSKC import |
| Google Authenticator migration protobuf | observed public interchange schema | local import only; unknown fields are skipped safely |
+| Aegis vault specification/importer sources | upstream `master`, accessed 19 August 2026 | bounded plaintext Aegis, andOTP, 2FAS and FreeOTP migration |
| Web Authentication | W3C WebAuthn Level 3 Recommendation, 13 January 2026 | client/authenticator structures and ceremony expectations |
+| FIDO Metadata Service | v3.1 Proposed Standard, 21 May 2025 | explicit offline Metadata BLOB import and status interpretation |
| RFC 8949 / RFC 9052 / RFC 8152 registrations | published versions | bounded CBOR and COSE key interpretation |
| QR Code for JavaScript | Kazuhiko Arase, 2009 | QR construction algorithm rewritten in TypeScript under MIT terms |
+| jsQR | 1.4.0 | bundled cross-browser QR image decoder under Apache-2.0 |
The OCRA implementation was authored from the normative RFC definition and tested with its published interoperability values; the RFC Java reference implementation is not included. The QR module is an acknowledged clean TypeScript rewrite of the MIT-licensed construction algorithm, with deliberately bounded version support.
diff --git a/public/THIRD_PARTY_NOTICES.md b/public/THIRD_PARTY_NOTICES.md
index 36278cb..bb54595 100644
--- a/public/THIRD_PARTY_NOTICES.md
+++ b/public/THIRD_PARTY_NOTICES.md
@@ -8,10 +8,11 @@ The release preparation step collates licence files for the exact locked runtime
| -------------------------------- | ------- | ---------- | ------------------------------- | ------------------------------------------- |
| `@add-ideas/toolbox-contract` | 0.2.3 | Apache-2.0 | manifest and context contract | https://git.add-ideas.de/lotobo/toolbox-sdk |
| `@add-ideas/toolbox-shell-react` | 0.2.3 | Apache-2.0 | shared shell, theme and actions | https://git.add-ideas.de/lotobo/toolbox-sdk |
+| `jsqr` | 1.4.0 | Apache-2.0 | local QR image decoding | https://github.com/cozmo/jsQR |
| `react` | 19.2.6 | MIT | application UI | https://github.com/facebook/react |
| `react-dom` | 19.2.6 | MIT | browser rendering | https://github.com/facebook/react |
-`scheduler`, distributed by the React project under MIT, is the only transitive runtime package.
+`scheduler`, distributed by the React project under MIT, is the only transitive runtime package. Exact licence texts, including jsQR's Apache-2.0 terms, are collated from the locked install into the release.
## QR construction
diff --git a/public/toolbox-app.json b/public/toolbox-app.json
index d836155..84a53a2 100644
--- a/public/toolbox-app.json
+++ b/public/toolbox-app.json
@@ -3,7 +3,7 @@
"schemaVersion": 1,
"id": "de.add-ideas.auth-tools",
"name": "OTP & Passkey Tools",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "Generate, inspect and verify OTP credentials and test WebAuthn/passkey ceremonies locally in the browser.",
"entry": "./",
"icon": "./favicon.svg",
diff --git a/src/components/HelpDialog.tsx b/src/components/HelpDialog.tsx
index 80c9e61..9d40c92 100644
--- a/src/components/HelpDialog.tsx
+++ b/src/components/HelpDialog.tsx
@@ -35,21 +35,24 @@ export function HelpDialog({
OTP seeds are equivalent to a second-factor credential. This app keeps
them in memory only, masks them by default and clears them on reload.
- Exports are explicit and unencrypted; move them only through a secure
- channel.
+ Plain URI/CSV exports are explicit and unencrypted. The encrypted
+ backup option authenticates its contents with AES-GCM and a password;
+ it is still not a recovery service or persistent browser vault.
OTP clock and counters
TOTP is computed from this device’s clock. A rejected valid-looking
- value commonly means clock drift, a different period, or the wrong
- hash/digit profile. HOTP counters must remain synchronized.
+ value commonly means clock drift, a different T0/period, or the wrong
+ hash/digit profile. The timeline and drift finder are diagnostics;
+ HOTP counters must remain synchronized.
Passkey inspection
Inspection is offline. Verification is layered: client-data
expectations, RP ID hash, authenticator flags, counter and
- cryptographic signature are reported separately. Metadata is never
- fetched silently.
+ cryptographic signature are reported separately. Attestation signature
+ validity, metadata status and trust are distinct results. Metadata is
+ imported explicitly and never fetched silently.
+ No imported metadata entry matches this AAGUID.
+
+ );
+ })()}
+ >
+ )}
+
+
+
+
+
+
Explicit offline import
+
FIDO Metadata BLOB
+
+
+
+
+ Paste a compact MDS3 JWT snapshot. Its JWS is verified locally;
+ signer-chain trust remains explicitly unestablished until a
+ trust root policy is configured.
+