Skip to content
Open
Show file tree
Hide file tree
Changes from 98 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
d6d6e5c
feat(webauthn): scaffold Yubico.YubiKit.WebAuthn module + test project
DennisDyallo Apr 22, 2026
5ee4f95
feat(webauthn): add WebAuthn data-model records + preference enums
DennisDyallo Apr 22, 2026
962a029
feat(webauthn): add COSE primitives (CoseAlgorithm, CoseKey, Aaguid) …
DennisDyallo Apr 22, 2026
be80a9b
fix(fido2): capture raw CBOR slice for AttestationStatement.RawData
DennisDyallo Apr 22, 2026
9f3e4ad
feat(webauthn): add WebAuthnOrigin parser with PSL + enterprise predi…
DennisDyallo Apr 22, 2026
b11a8ac
feat(webauthn): add WebAuthnClientData with hand-built JSON (byte-par…
DennisDyallo Apr 22, 2026
5d55c15
feat(webauthn): add AttestationObject, AttestationStatement variants,…
DennisDyallo Apr 22, 2026
06589a6
feat(webauthn): add WebAuthnClientError + error code enum
DennisDyallo Apr 22, 2026
4442624
feat(webauthn): add IWebAuthnBackend abstraction + FidoSessionWebAuth…
DennisDyallo Apr 22, 2026
59e7a4f
feat(webauthn): add RegistrationOptions and RegistrationResponse types
DennisDyallo Apr 22, 2026
0546dd8
feat(webauthn): add RpIdValidator + UvDecision
DennisDyallo Apr 22, 2026
b4671dc
feat(webauthn): add WebAuthnClient.MakeCredentialAsync (terminal flow…
DennisDyallo Apr 22, 2026
ae2994f
test(webauthn): add WebAuthnClient.MakeCredentialAsync unit tests wit…
DennisDyallo Apr 22, 2026
4188c3d
feat(webauthn): add AuthenticationOptions, AuthenticationResponse, Ma…
DennisDyallo Apr 22, 2026
8193101
feat(webauthn): add CredentialMatcher (allow-list + discoverable enum…
DennisDyallo Apr 22, 2026
25e6ae4
feat(webauthn): wire GetAssertion in FidoSessionWebAuthnBackend
DennisDyallo Apr 22, 2026
547e64a
feat(webauthn): add WebAuthnClient.GetAssertionAsync with deferred Ma…
DennisDyallo Apr 22, 2026
fe37532
test(webauthn): add WebAuthnClient.GetAssertionAsync unit tests
DennisDyallo Apr 22, 2026
e803ede
feat(webauthn): add WebAuthnStatus discriminated record + StatusChann…
DennisDyallo Apr 22, 2026
67c0235
feat(webauthn): add streaming WebAuthn APIs with PIN/UV interaction
DennisDyallo Apr 22, 2026
01d468a
test(webauthn): add streaming + drain-convenience unit tests (5 tests)
DennisDyallo Apr 22, 2026
c8d1033
fix(webauthn): cancel PIN/UV TCS when drain helper has no credentials…
DennisDyallo Apr 22, 2026
3c64c74
feat(webauthn): add extension input/output records (CredProtect, Cred…
DennisDyallo Apr 22, 2026
4baefe0
feat(webauthn): add per-extension adapters dispatching to Fido2 Exten…
DennisDyallo Apr 22, 2026
d943ab6
feat(webauthn): add ExtensionPipeline orchestration (build CBOR, pars…
DennisDyallo Apr 22, 2026
74b5853
feat(webauthn): wire ExtensionPipeline into WebAuthnClient registrati…
DennisDyallo Apr 22, 2026
2ceefe0
test(webauthn): add ExtensionPipeline + adapter unit tests
DennisDyallo Apr 22, 2026
46e5233
fix(webauthn): H-3 remove dangerous PinAuthInvalid retry loop + add c…
DennisDyallo Apr 22, 2026
f7ae5cb
fix(webauthn): H-2 link stream producer cancellation to iterator disp…
DennisDyallo Apr 22, 2026
897d97e
fix(webauthn): H-4 honor CancellationToken in MatchedCredential.Selec…
DennisDyallo Apr 22, 2026
8e31e73
fix(webauthn): H-1 standardize PIN buffer zeroing on whole rented block
DennisDyallo Apr 22, 2026
6400698
fix(webauthn): M-1/M-3/L-7 wrap CBOR errors as WebAuthnClientError
DennisDyallo Apr 22, 2026
58e6024
fix(webauthn): M-2 validate CredBlob assertion output length (1-32 by…
DennisDyallo Apr 22, 2026
11088ae
fix(webauthn): M-4 reject ambiguous PRF evalByCredential matches
DennisDyallo Apr 22, 2026
510ced7
fix(webauthn): M-5/M-6 LargeBlob honest no-op (throws NotSupported un…
DennisDyallo Apr 22, 2026
1f78c46
docs(webauthn): L-2 document Aaguid struct safety rationale
DennisDyallo Apr 22, 2026
fe59e4f
docs(webauthn): append Gate 1 resolutions table to audit
DennisDyallo Apr 22, 2026
10a94b7
fix(webauthn): correct WebAuthnClientError namespace references
DennisDyallo Apr 22, 2026
a5b6781
feat(webauthn/previewSign): add PreviewSignFlags enum + validation ex…
DennisDyallo Apr 22, 2026
77deea7
feat(webauthn/previewSign): add registration input/output + Generated…
DennisDyallo Apr 22, 2026
c123d7c
feat(webauthn/previewSign): add authentication input/output + signing…
DennisDyallo Apr 22, 2026
6de96b1
feat(webauthn/previewSign): add PreviewSignCbor encode/decode helpers…
DennisDyallo Apr 22, 2026
73c201a
feat(webauthn/previewSign): add CTAP error → WebAuthnClientError mapping
DennisDyallo Apr 22, 2026
aece974
test(webauthn/previewSign): add 9 unit tests covering CBOR encoding, …
DennisDyallo Apr 22, 2026
0a62af1
feat(webauthn/previewSign): extend RegistrationExtensionInputs/Output…
DennisDyallo Apr 22, 2026
eff5741
feat(webauthn/previewSign): add PreviewSignAdapter (registration + au…
DennisDyallo Apr 22, 2026
1c47328
feat(webauthn/previewSign): wire PreviewSignAdapter into ExtensionPip…
DennisDyallo Apr 22, 2026
947cbd7
feat(webauthn/previewSign): thread RegistrationOptions into Extension…
DennisDyallo Apr 22, 2026
205400a
docs(fido2): note WebAuthn-layer previewSign location in extensions t…
DennisDyallo Apr 22, 2026
81890f3
test(webauthn/previewSign): add 7 PreviewSignAdapter tests (validatio…
DennisDyallo Apr 22, 2026
3bfb0b0
fix(webauthn): H-2 use CTAP2 canonical (length-then-lex) sort when me…
DennisDyallo Apr 22, 2026
8c1b9ef
fix(webauthn): H-4 ByteArrayKeyComparer uses full-content HashCode.Ad…
DennisDyallo Apr 22, 2026
04ef8be
fix(webauthn): H-3 PreviewSignAuthenticationInput defensively normali…
DennisDyallo Apr 22, 2026
5ca187b
fix(webauthn): M-2 derive previewSign flags from UserVerification onl…
DennisDyallo Apr 22, 2026
6fd4acc
fix(webauthn): C-3 remove dead DecodeSignedRegistrationOutput (always…
DennisDyallo Apr 22, 2026
3364ed1
fix(fido2): C-2-prep capture unsignedExtensionOutputs from MakeCreden…
DennisDyallo Apr 22, 2026
0ae08cf
fix(webauthn): C-2 read previewSign attestation from unsignedExtensio…
DennisDyallo Apr 22, 2026
f142504
fix(webauthn): C-1 encode previewSign auth as flat single-credential …
DennisDyallo Apr 22, 2026
297ca13
fix(webauthn): H-1 wire PreviewSignErrors.MapCtapError at registratio…
DennisDyallo Apr 22, 2026
4a13e72
test(webauthn): M-1 lock down auth CBOR key set (defense-in-depth)
DennisDyallo Apr 22, 2026
950468c
fix(webauthn): M-3 wrap nested attestation parse errors as WebAuthnCl…
DennisDyallo Apr 22, 2026
a2d1b62
fix(webauthn): M-4 validate previewSign AdditionalArgs is well-formed…
DennisDyallo Apr 22, 2026
3ec93ff
docs(webauthn): append Gate-2 audit resolutions table
DennisDyallo Apr 22, 2026
9aa0cca
test(webauthn): fix previewSign tests after Gate-2 wire format changes
DennisDyallo Apr 22, 2026
3780fd5
docs(webauthn): update CLAUDE.md with SDK rewrite details
DennisDyallo Apr 22, 2026
97a502d
docs: clarify --project + --filter usage for targeted test runs
DennisDyallo Apr 22, 2026
95abc0c
fix(webauthn): wire extension passthrough and fix previewSign parser
DennisDyallo Apr 22, 2026
fbe45bc
docs(webauthn): add module CLAUDE.md
DennisDyallo Apr 22, 2026
f90bbc8
test(webauthn): add DeleteAllCredentialsForRpAsync helper
DennisDyallo Apr 22, 2026
63adea3
refactor(webauthn): split PreviewSignCbor key constants into scoped c…
DennisDyallo Apr 22, 2026
eadb8fc
test(webauthn): fix xUnit1051 warnings and CS8625 in GetAssertionTests
DennisDyallo Apr 22, 2026
5f7ab70
docs: correct LoggingFactory→YubiKitLogging in root CLAUDE.md
DennisDyallo Apr 22, 2026
56dfbd5
docs(webauthn): land Phase 9 plan + libfido2/android parity reports +…
DennisDyallo Apr 23, 2026
0b6fa31
docs(webauthn): pivot Phase 9.2 to path 2A — Rust upstream is hardwar…
DennisDyallo Apr 23, 2026
36c9868
test(webauthn): add byte-level CBOR encoding tests for previewSign au…
DennisDyallo Apr 23, 2026
3983cc9
refactor(webauthn): update multi-credential NotSupported message to r…
DennisDyallo Apr 23, 2026
d669174
fix(webauthn): enable previewSign auth test with non-ARKG algorithms
DennisDyallo Apr 23, 2026
b26ef2a
test(webauthn): drop validation-only previewSign test per repo test-p…
DennisDyallo Apr 23, 2026
b54bc0c
test(webauthn): re-skip previewSign auth integration test — ARKG is g…
DennisDyallo Apr 23, 2026
197e0dd
test(webauthn): use [SkippableTheory] so xunit.SkippableFact catches …
DennisDyallo Apr 23, 2026
bd4e0fd
docs(webauthn): record Phase 9.3 hardware verification results
DennisDyallo Apr 23, 2026
5b67f7d
docs(fido2): file Phase 9.4 tracker for canonical extension coverage …
DennisDyallo Apr 23, 2026
728a117
docs(webauthn): handoff for Phase 9 close + PR #466
DennisDyallo Apr 23, 2026
e94e6ff
test(fido2): add canonical previewSign registration and PIN error tests
DennisDyallo Apr 23, 2026
06eb7fc
feat(fido2): add PreviewSignExtension types and encoder
DennisDyallo Apr 23, 2026
95205be
feat(fido2): add WithPreviewSign builder methods
DennisDyallo Apr 23, 2026
c4dcdef
refactor(webauthn): delegate previewSign encoding to Fido2
DennisDyallo Apr 23, 2026
49c75f6
test(fido2): migrate previewSign tests to canonical Fido2 layer
DennisDyallo Apr 23, 2026
57e7733
docs(fido2,webauthn): update CLAUDE.md with architectural truth
DennisDyallo Apr 23, 2026
2df7745
refactor(webauthn): eliminate DRY in attestation-object encoding
DennisDyallo Apr 23, 2026
5c73229
refactor(webauthn): route PreviewSignAdapter through ExtensionBuilder
DennisDyallo Apr 23, 2026
5620dc5
docs(webauthn): handoff capturing architectural cleanup phases 9.5/9.…
DennisDyallo Apr 23, 2026
01f6ed7
refactor(tests): add cancellation token to MakeCredentialStreamAsync …
DennisDyallo Apr 23, 2026
2823809
test(fido2): add Phase 9.4 extension coverage tests
DennisDyallo Apr 23, 2026
46e1061
docs(fido2): mark Phase 9.4 done + file Phase 9.6 credBlob validation…
DennisDyallo Apr 23, 2026
e7624e4
docs(webauthn): final session handoff — Phase 9.4 shipped, Phase 9.6 …
DennisDyallo Apr 23, 2026
b470a5f
refactor(webauthn,fido2): consolidate duplicated behavior to Fido2 (P…
DennisDyallo Apr 24, 2026
3214535
refactor(fido2,webauthn): consolidate AttestationStatement to typed h…
DennisDyallo Apr 24, 2026
4529e8c
refactor(tests): replace Theory with SkippableTheory in test classes
DennisDyallo Apr 27, 2026
d4b9503
docs: trim CLAUDE.md 50% via JIT extraction to discoverable domain docs
DennisDyallo Apr 27, 2026
3107bd5
fix(fido2): parse previewSign unsignedExtensionOutputs at CTAP key 6 …
DennisDyallo Apr 27, 2026
43ea328
fix(fido2,test): re-mint pinUvAuthToken between GetAssertion calls in…
DennisDyallo Apr 27, 2026
37ff02f
fix(fido2,test): guard FidoNfcTests against NotSupportedException on …
DennisDyallo Apr 27, 2026
f62c7c4
feat(webauthn): add client-layer excludeList pre-flight (Java parity)
DennisDyallo Apr 27, 2026
dc2ed14
fix(webauthn): re-mint pinUvAuthToken between excludeList preflight a…
DennisDyallo Apr 27, 2026
a0070db
fix(webauthn): address 4 critical CodeAudit findings (token hygiene, …
DennisDyallo Apr 27, 2026
cfea6e1
docs(handoff): 2026-04-28 — ExcludeList preflight token re-mint + 4 C…
DennisDyallo Apr 27, 2026
489c853
chore(webauthn): remove dead CreateUvRequest + _uvResponseTcs from St…
DennisDyallo Apr 27, 2026
f547fca
fix(fido2,test): add missing 'using Xunit;' to FidoNfcTests for Skip …
DennisDyallo Apr 27, 2026
2b1b085
chore(webauthn): Tier A audit cleanup — typed cancellation + remove d…
DennisDyallo Apr 27, 2026
66fe7bc
docs(handoff): 2026-04-28 — 6-commit cleanup wave (ExcludeList fix + …
DennisDyallo Apr 27, 2026
6ecbae3
fix(fido2,test): port previewSign -9 → -65539 alg fix from Legacy fe8…
DennisDyallo Apr 28, 2026
adcff79
feat(fido2,webauthn): typed CoseSignArgs builder for previewSign ARKG…
DennisDyallo Apr 28, 2026
0fbeb9c
fix(webauthn): decode CTAP-shaped inner attestation object in preview…
DennisDyallo Apr 28, 2026
1865c8b
docs(handoff,plans): 2026-04-28 afternoon — Phase 10 §3 ship + previe…
DennisDyallo Apr 28, 2026
e66e539
fix(claude): remove redundant skill entry from guidance
DennisDyallo Apr 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# CLAUDE.md

This file provides guidance to AI agents when working with code in this repository.
This is a complete rewrite of the .NET SDK in the `develop` and `main` branch. The root of the 2.0 version of this SDK is the `yubikit` branch.

**IMPORTANT:** If you are working in a subproject directory (e.g., `src/SecurityDomain/`, `src/Piv/`, etc.), you MUST also read that subproject's `CLAUDE.md` file if it exists. Subproject CLAUDE.md files contain specific patterns, test harness details, and context for that module.

Expand Down Expand Up @@ -156,6 +157,15 @@ dotnet toolchain.cs publish
### Build Script Options

```bash
# Run tests for a single module (skips building/running unrelated projects)
dotnet toolchain.cs test --project WebAuthn

# Run a specific test by name within a module
dotnet toolchain.cs test --project WebAuthn --filter "FullyQualifiedName~PreviewSign"

# Smoke test (skips Slow and RequiresUserPresence tests)
dotnet toolchain.cs test --project Piv --smoke

# Override package version
dotnet toolchain.cs pack --package-version 1.0.0-preview.2

Expand All @@ -172,6 +182,11 @@ dotnet toolchain.cs build --clean
dotnet toolchain.cs publish --nuget-feed-name MyFeed --nuget-feed-path ~/my-feed
```

**Test filtering tips:**
- Always combine `--project` with `--filter` to avoid building all projects (much faster)
- Filter syntax: `FullyQualifiedName~Substring`, `Method~Name`, `Category!=Slow`
- The toolchain auto-translates VSTest filter syntax to xUnit v3 native options

### Direct dotnet Commands (Fallback)

If you need to bypass the build script:
Expand Down Expand Up @@ -261,18 +276,20 @@ public ReadOnlySpan<byte> Data

### Logging Conventions

**Use Static LoggingFactory - NEVER inject ILogger:**
**Use Static YubiKitLogging - NEVER inject ILogger:**
```csharp
// ✅ CORRECT: Static logger from factory
// ✅ CORRECT: Static logger from YubiKitLogging
public class FidoSession
{
private static readonly ILogger Logger = LoggingFactory.CreateLogger<FidoSession>();
private static readonly ILogger Logger = YubiKitLogging.CreateLogger<FidoSession>();
}

// ❌ WRONG: Injected logger (breaks consistency)
public class FidoSession(ILogger<FidoSession> logger) { }
```

**Canonical logger factory:** `YubiKitLogging.CreateLogger<T>()` at `src/Core/src/YubiKitLogging.cs:20`.

**Log Levels:**
- `Trace` - Raw APDU/CBOR bytes, detailed protocol steps
- `Debug` - Protocol-level operations, state transitions
Expand Down
302 changes: 302 additions & 0 deletions Plans/audit-gate-1.md

Large diffs are not rendered by default.

229 changes: 229 additions & 0 deletions Plans/audit-gate-2.md

Large diffs are not rendered by default.

114 changes: 114 additions & 0 deletions Plans/cnh-authenticator-rs-previewsign-parity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# cnh-authenticator-rs-extension previewSign Parity Report

**Date:** 2026-04-23
**Investigated:** cnh-authenticator-rs-extension @ commit `c83cbce` (2026-04-09), local path `/Users/Dennis.Dyall/Code/y/cnh-authenticator-rs-extension`
**Crate:** `sign-extension-host` v0.1.0 ("Native messaging host for previewSign FIDO bridge"), edition 2021; vendored library `authenticator` under `native/deps/`
**Verdict:** **HARDWARE-PROVEN** — Registration **and** Authentication; signature is returned and printed by an interactive hardware test (`hid-test` binary)

## Findings

**Code paths:** Full implementation for both registration and authentication, with a working hardware harness that exercises the round-trip and surfaces the signature.

- **Registration (`MakeCredential` with `generateKey`):** `native/deps/authenticator/src/ctap2/commands/make_credentials.rs:66` — parses the `previewSign.generateKey` input, returns the unsigned attestation object in CBOR response key 6.

- **Authentication (`GetAssertion` with `signByCredential`):** Two layers:
- High-level parsing: `native/crates/host/src/webauthn.rs:420-457` — parses the `signByCredential` map, validates `keyHandle` / `tbs` / `additionalArgs`.
- Low-level wire encoding (the upstream reference): `native/deps/authenticator/src/ctap2/commands/get_assertion.rs:290-323`. Verbatim:
```rust
if let Some(ref sign) = self.sign {
// Build CBOR map with integer keys for each credential's signing inputs.
// Format: "previewSign" => {2: kh, 6: tbs, 7: additional_args}
// When there's one credential, it's a single map.
// For multiple, it should select based on allow_list (done in statemachine).
// For now, serialize the first entry.
use std::collections::BTreeMap;
let mut sign_map = BTreeMap::new();
if let Some(first) = sign.sign_by_credential.first() {
log::debug!(
"previewSign GetAssertion: kh={} bytes, tbs={} bytes, args={:?} bytes",
first.key_handle.len(),
first.tbs.len(),
first.additional_args.as_ref().map(|a| a.len()),
);
sign_map.insert(
serde_cbor::Value::Integer(2),
serde_cbor::Value::Bytes(first.key_handle.clone()),
);
sign_map.insert(
serde_cbor::Value::Integer(6),
serde_cbor::Value::Bytes(first.tbs.clone()),
);
if let Some(ref args) = first.additional_args {
sign_map.insert(
serde_cbor::Value::Integer(7),
serde_cbor::Value::Bytes(args.clone()),
);
}
} else {
log::warn!("previewSign GetAssertion: sign_by_credential is EMPTY");
}
map.serialize_entry("previewSign", &serde_cbor::Value::Map(sign_map))?;
}
```

**Wire-format contract (canonical, from the encoder above):**

| CBOR key | Type | Meaning |
|---|---|---|
| `2` (integer) | `bytes` | `key_handle` |
| `6` (integer) | `bytes` | `tbs` (to-be-signed; in `hid-test` this is `Sha256(raw_tbs)`, 32 bytes) |
| `7` (integer, optional) | `bytes` | `additional_args` — for ARKG, the CBOR `COSE_Sign_Args` map `{3: alg, -1: arkg_kh, -2: ctx}` |

The map is wrapped under the string key `"previewSign"` inside the GetAssertion extensions map. `BTreeMap` ordering means keys serialize in ascending integer order: 2, 6, 7. The `serde_cbor` `Value::Bytes` produces standard CBOR major-type 2 byte strings.

**Hardware tests:** ✅ **HARDWARE-PROVEN** — the `hid-test` binary calls a real YubiKey, derives an ARKG key, signs `"Hello, previewSign v4!"`, and prints the resulting signature.

- Request build: `native/crates/hid-test/src/main.rs:257-294` — constructs `signByCredential` with `key_handle = gk.key_handle`, `tbs = Sha256(b"Hello, previewSign v4!").to_vec()`, `additional_args = encode_arkg_sign_args(COSE_ALG_ESP256_ARKG, &derived.key_handle, arkg_ctx)`.
- Touch prompt: `:330-331` — `>>> Touch your YubiKey again <<<`.
- Signature receive + print: `:366-379`. Verbatim:
```rust
match result_rx2.recv() {
Ok(Ok(sign_result)) => {
println!("\n--- GetAssertion Result ---");
println!(" Signature: {} bytes", sign_result.assertion.signature.len());
println!(" Signature hex: {}", hex(&sign_result.assertion.signature));

if let Some(ref sign_out) = sign_result.extensions.sign {
if let Some(ref sig) = sign_out.signature {
println!(" previewSign signature: {} ({} bytes)", hex(sig), sig.len());
} else {
println!(" previewSign: no signature in output");
}
} else {
println!(" No sign extension outputs");
}
}
...
}
```

**Cross-platform Python harness:** `scripts/test_previewsign.py:131-138` exercises the same registration + authentication flow against `webauthn.dll` on Windows and HID transport elsewhere. Secondary reference, not required for the C# port.

**Constraints / what is NOT proven by Rust:**
- `hid-test` exercises `signByCredential` with **exactly one entry** (single-credential auth). Multi-credential probe-selection per CTAP §10.2.1 step 7 is **not** demonstrated. The encoder comment at `get_assertion.rs:294` admits: *"For multiple, it should select based on allow_list (done in statemachine). For now, serialize the first entry."* — implying the multi-credential path is unimplemented even in Rust's high-level driver.
- ARKG-specific: `additional_args` carries an ARKG `COSE_Sign_Args` payload. Use cases without ARKG would omit key 7. Both shapes are valid per the encoder.

## Citations

- `native/deps/authenticator/src/ctap2/commands/get_assertion.rs:290-323` — wire-format ground truth (integer keys 2/6/7, bytes values, BTreeMap ordering)
- `native/crates/hid-test/src/main.rs:257-294` — `signByCredential` request build (single entry, SHA-256 of TBS, ARKG `additional_args`)
- `native/crates/hid-test/src/main.rs:330-331` — user-presence prompt
- `native/crates/hid-test/src/main.rs:366-379` — signature received + printed
- `native/crates/host/src/webauthn.rs:420-457` — high-level GetAssertion previewSign parsing
- `native/deps/authenticator/src/ctap2/commands/make_credentials.rs:66` — registration parsing
- `scripts/test_previewsign.py:131-138` — Python cross-platform harness (secondary)
- Crate metadata: `Cargo.toml` for `sign-extension-host` v0.1.0, last commit `c83cbce` 2026-04-09 13:47:07 +0200

## Recommendation for Phase 9.2

**Adopts path 2A.** The Rust encoder is the upstream reference required by the principle "only ship what an upstream reference has proven works on hardware." Port the integer-keyed CBOR map structure and the SHA-256 TBS preprocessing into `PreviewSignAdapter.BuildAuthenticationCbor`.

**Note on the C# bug:** The diagnostic at `PreviewSignTests.cs:101-107` reports that C# already uses keys 2/6/7. The persisting `Invalid length (0x03)` therefore likely lives in **byte-string length headers**, **outer wrapping**, or **omission of `additional_args` for ARKG-signed inputs** — not in the key choice. Engineer must do a byte-by-byte diff against `serde_cbor`'s output for an identical input.

**Not adopted by this report:**
- Multi-credential probe (CTAP §10.2.1 step 7) — unproven by Rust as well; defers to Phase 10.
Loading
Loading