feat(fido2): WebAuthn previewSign extension (ARKG-P256)#468
feat(fido2): WebAuthn previewSign extension (ARKG-P256)#468DennisDyallo wants to merge 15 commits intodevelopfrom
Conversation
1cf9541 to
9960876
Compare
Test Results: Windows 2 files 2 suites 41s ⏱️ Results for commit a3da940. ♻️ This comment has been updated with latest results. |
Test Results: Ubuntu 2 files 2 suites 1m 12s ⏱️ Results for commit a3da940. ♻️ This comment has been updated with latest results. |
Test Results: MacOS 4 files 4 suites 50s ⏱️ Results for commit a3da940. ♻️ This comment has been updated with latest results. |
| <PackageReference Include="System.Memory" Version="4.6.3" /> | ||
| <PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" /> | ||
| <PackageReference Include="Yubico.NativeShims" Version="1.16.0" /> | ||
| <PackageReference Include="Yubico.NativeShims" Version="1.16.1-prerelease.20260428.1" /> |
There was a problem hiding this comment.
Pull request overview
Adds support for the WebAuthn previewSign extension to the FIDO2 surface area of Yubico.NET.SDK, including ARKG-P256 offline public-key derivation and sign-by-credential plumbing, plus associated cryptographic/native support and tests.
Changes:
- Introduces
previewSignextension APIs for MakeCredential (generate key) and GetAssertion (sign by derived credential), plus parsing of signed/unsigned extension outputs. - Adds ARKG-P256 primitives (OpenSSL-backed via NativeShims) and wires them through
CryptographyProviders. - Adds unit/integration tests for previewSign + ARKG, and a test-only cache warmup workaround for a macOS device-listener race.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Yubico.YubiKey/tests/utilities/Yubico/YubiKey/TestUtilities/IntegrationTestDeviceEnumeration.cs | Updates allow-list path documentation for macOS/Linux. |
| Yubico.YubiKey/tests/utilities/Yubico/YubiKey/TestUtilities/DeviceListenerCacheWarmup.cs | Adds test utility to wait for initial device enumeration to populate. |
| Yubico.YubiKey/tests/unit/Yubico/YubiKey/Fido2/PreviewSignExtensionTests.cs | Unit tests for previewSign CBOR encoding/decoding and regression scenarios. |
| Yubico.YubiKey/tests/unit/Yubico/YubiKey/Fido2/Arkg/ArkgP256Tests.cs | Known-answer tests for ARKG-P256 derivation behavior. |
| Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/HkdfUtilitiesTests.cs | Updates HKDF tests to reference the moved HKDF utility. |
| Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/PreviewSignTests.cs | Adds end-to-end integration tests for previewSign generate/derive/sign/verify. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/PreviewSignGeneratedKey.cs | New public type representing generated key material and offline derivation entrypoint. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/PreviewSignExtension.cs | Implements CBOR encoder/decoder for previewSign extension input/output. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/PreviewSignDerivedKey.cs | New public type representing derived key material and signature verification helper. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/MakeCredentialParameters.cs | Adds API to request previewSign key generation during registration. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/MakeCredentialData.cs | Adds parsing of CTAP unsigned extension outputs and accessor for generated key. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/GetAssertionParameters.cs | Adds API to request previewSign signing-by-credential during assertions. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/Extensions.cs | Adds previewSign extension identifier constant. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/Cose/CoseAlgorithmIdentifier.cs | Adds previewSign-related COSE algorithm identifiers (Esp256, ArkgP256Esp256). |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/AuthenticatorInfo.cs | Updates imports to use the relocated HKDF utility. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/AuthenticatorData.cs | Adds accessor to extract previewSign signature from signed extension outputs. |
| Yubico.YubiKey/src/Yubico/YubiKey/Fido2/Arkg/ArkgP256.cs | Adds ARKG-P256 wrapper to route derivation through Core primitives. |
| Yubico.YubiKey/src/Yubico/YubiKey/Cryptography/CryptographyProviders.cs | Adds ArkgPrimitivesCreator delegate to allow swapping ARKG primitive implementation. |
| Yubico.NativeShims/ssl.ecpoint.c | Exposes EC_POINT_is_on_curve via NativeShims for on-curve validation. |
| Yubico.NativeShims/exports.msvc | Exports new Native_EC_POINT_is_on_curve symbol on Windows (MSVC). |
| Yubico.NativeShims/exports.llvm | Exports new symbol for LLVM toolchains. |
| Yubico.NativeShims/exports.gnu | Exports new symbol for GNU toolchains. |
| Yubico.Core/tests/unit/Yubico/Core/Cryptography/ArkgPrimitivesTests.cs | Adds Core-level tests for on-curve validation and ECDH behavior. |
| Yubico.Core/src/Yubico/PlatformInterop/Desktop/Cryptography/EcPoint.Interop.cs | Adds P/Invoke wrapper for Native_EC_POINT_is_on_curve. |
| Yubico.Core/src/Yubico/Core/Cryptography/IArkgPrimitives.cs | Introduces interface contract for ARKG primitives (validation, ECDH, derive). |
| Yubico.Core/src/Yubico/Core/Cryptography/HkdfUtilities.cs | Moves/renames HKDF utility into Core and updates implementation details. |
| Yubico.Core/src/Yubico/Core/Cryptography/ArkgPrimitivesOpenSsl.cs | Implements ARKG-P256 primitives and derivation using OpenSSL via NativeShims. |
| Yubico.Core/src/Yubico/Core/Cryptography/ArkgPrimitives.cs | Adds factory for default ARKG primitives implementation. |
| Yubico.Core/src/Yubico.Core.csproj | Updates NativeShims package dependency version for the new export. |
Comments suppressed due to low confidence (2)
Yubico.Core/src/Yubico/Core/Cryptography/HkdfUtilities.cs:74
- HkdfExtract creates temporary byte[] copies of both the salt and the input keying material via ToArray(). Since IKM can be secret material, these temporary arrays should be zeroed after ComputeHash to avoid extending the lifetime of sensitive data in memory.
Yubico.Core/src/Yubico/Core/Cryptography/HkdfUtilities.cs:87 - HkdfExpand currently calls pseudoRandomKey.ToArray() to build the HMAC instance, which creates an extra copy of the PRK. Since DeriveKey already zeroes the original PRK, this additional copy will remain in memory unless explicitly cleared. Consider avoiding the extra copy (e.g., accept byte[] and pass it through) and/or ensuring any extra key buffer is zeroed when no longer needed.
3a99633 to
9c68ea2
Compare
1d36eaf to
dd829ec
Compare
Phase 1 of the previewSign port establishes the test-first behavioral
spec. All public API stubs throw NotImplementedException; tests compile
and fail at runtime. Subsequent phases turn red tests green:
Phase 2 — NativeShims native additions
Phase 3 — Managed P/Invoke + ArkgPrimitivesOpenSsl
Phase 4 — ARKG-P256 algorithm port (from Yubico Rust reference)
Phase 5 — Fido2 extension wiring (CBOR encoders, parsers)
Phase 6 — Doc pass + final green-test verification
Includes two required regression tests:
- ParseGenerateKeyFromUnsignedExtensions_KeyAt6 — locks CTAP key 6
(matches yubikit-swift release/1.3.0, Java, Python; v2 .NET uses 8
and is the outlier — separate bug report queued)
- AddPreviewSignByCredential_ThrowsWhenExtensionUnsupported — guards
against a missing-validation bug found in the upstream PoC
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the OpenSSL-backed ARKG primitives needed by the previewSign WebAuthn extension: SEC1 on-curve validation via the new EcPointIsOnCurve P/Invoke wrapper, and ECDH shared-secret computation that rejects invalid-curve inputs before any scalar multiplication. Wires a CryptographyProviders factory delegate following the EcdhPrimitivesCreator pattern. IArkgPrimitives is exposed publicly to mirror the existing IEcdhPrimitives contract; making it internal would require a Yubico.YubiKey InternalsVisibleTo entry that collides with the Nullable polyfill. Phase 3 of the previewSign port. Phase 4 (ArkgP256 algorithm) and Phase 5 (extension wiring) tests remain RED with NotImplementedException. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements draft-bradleylundberg-cfrg-arkg-09 derivation entirely in managed code, with point arithmetic via Yubico.NativeShims and scalar reduction via System.Numerics.BigInteger. The full algorithm body lives in ArkgPrimitivesOpenSsl.Derive (Yubico.Core) so it can use the internal OpenSSL P/Invoke surface that is not visible from Yubico.YubiKey; ArkgP256.cs (Yubico.YubiKey) becomes a thin wrapper that routes through CryptographyProviders.ArkgPrimitivesCreator. Adds three KAT vectors generated from cnh-authenticator-rs-extension's arkg.rs reference. Vector A reproduces the embedded Rust unit-test expected output byte-for-byte; vectors B/C exercise distinct-IKM and distinct-ctx paths with bit-exact expected derived public keys. Phase 4 of the previewSign port. Phase 5 (extension wiring) tests remain RED with NotImplementedException. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces all Phase 1 stubs with real implementations:
- New PreviewSignExtension (internal) — CBOR encoder/decoder using
per-context enums (MakeCredentialKey {3,4,7}, GetAssertionKey {2,6,7})
to keep the deliberately reused integers readable.
- AddPreviewSignGenerateKeyExtension and AddPreviewSignByCredentialExtension
both call IsExtensionSupported (the second was Alan's bug — guarded by a
named regression test).
- MakeCredentialData parses UnsignedExtensionOutputs at CTAP response
key 6 (NOT 8 — verified against yubikit-swift release/1.3.0; explicit
regression test asserts the value).
- AuthenticatorData.GetPreviewSignSignature pulls the DER-encoded ECDSA
signature from authData.extensions["previewSign"] map key 6.
- PreviewSignGeneratedKey.DerivePublicKey routes to ArkgP256.
- PreviewSignDerivedKey.VerifySignature uses the existing EcdsaVerify
helper for portability across netstandard2.0/2.1/net472.
Flags rule: requireUv -> 0b101 (RequireUserVerification), else 0b001
(RequireUserPresence). Derived from the AddExtension call argument, never
a user knob.
Phase 5 of the previewSign port. All 9 PreviewSignExtensionTests pass,
including ParseGenerateKeyFromUnsignedExtensions_KeyAt6 and
AddPreviewSignByCredential_ThrowsWhenExtensionUnsupported.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Added comprehensive XML documentation for all public APIs in the previewSign WebAuthn extension implementation: - Enhanced CoseAlgorithmIdentifier.Esp256/ArkgP256Esp256 docs to clarify usage distinction (Esp256 for signing, ArkgP256Esp256 for key generation requests) - Expanded IArkgPrimitives.Derive with algorithm details and cross-references to usage contexts - Added class and method remarks to PreviewSignGeneratedKey and PreviewSignDerivedKey with workflow guidance - Enhanced MakeCredentialParameters.AddPreviewSignGenerateKeyExtension and GetAssertionParameters.AddPreviewSignByCredentialExtension with usage flows and cross-references - Documented ArkgPrimitives.Create factory method All docs follow existing SDK patterns from CredBlob extension. DocFX build clean (0 warnings, 0 errors). Test suites green (Core: 488 PASS, YubiKey: 3587 PASS). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the 3 Phase 1 NotImplementedException stubs in PreviewSignTests.cs with real test bodies exercising the public previewSign API surface landed in Phases 3-6: - MakeCredentialWithPreviewSign_ReturnsGeneratedKey: registers a credential with previewSign and validates the returned PreviewSignGeneratedKey shape (KeyHandle non-empty, BlindingPublicKey + KemPublicKey are 65-byte SEC1 uncompressed P-256 points starting with 0x04). - FullCeremony_RegisterDeriveSignVerify_RoundTrip: full Step A->B->C->D ceremony — register with previewSign, derive public key offline with deterministic ikm/ctx, sign a fixed message with the derived credential, verify the signature offline. - MakeCredentialWithUnsupportedAlgorithm_Fails: registers with ES256 instead of ArkgP256Esp256, asserts hardware rejects it. Pivoted from the original GetAssertion-with-unsupported-alg framing because the production AddPreviewSignGenerateKeyExtension does no client-side algorithm filtering, so device rejection is the meaningful test. Tests use [SkippableFact(typeof(DeviceNotFoundException))] + Skip.IfNot(IsExtensionSupported(Extensions.PreviewSign)) so they skip cleanly without a YubiKey 5.8.0-beta+ present. Helpers (GetMakeCredentialParams / GetGetAssertionParams / GetPinToken) follow the HmacSecretTests integration pattern. Reviewed via /DevTeam Ship — Engineer wrote, Reviewer approved CLEAN PASS on logic correctness without execution. Tests can only be run by a human with physical YK + user touch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…scovery The previous implementation inherited SimpleIntegrationTestConnection, which calls IntegrationTestDeviceEnumeration.GetTestDevice() EAGERLY in its constructor. On macOS the YubiKeyDeviceListener populates its device cache asynchronously, so FindByTransport(All) returned empty before the cache was populated, throwing DeviceNotFoundException and silently skipping every test even when a supported YubiKey was plugged in and present in the allow-list. Refactor to inherit FidoSessionIntegrationTestBase (the same base class used by MakeCredentialBlobTests, HmacSecretTests, MinPinLenTests). That base exposes Device / Session / Connection as LAZY properties accessed only when the test method runs, by which time the device listener has populated its cache. Side benefits of the rebase: - No private constructor needed; base handles PIN setup via TestPin1 - Removes 3 helper methods; base provides MakeCredentialParameters / GetAssertionParameters templates and a TestKeyCollector - Higher-level Session.MakeCredential / Session.GetAssertions API instead of Connection.SendCommand(...) - File moved from Fido2/Commands/ to Fido2/ to match the location convention of other FidoSessionIntegrationTestBase-using tests Hardware behavior unchanged. Skip semantics preserved: still uses [SkippableFact(typeof(DeviceNotFoundException))] + Skip.IfNot(Session.AuthenticatorInfo.IsExtensionSupported(...)) on every test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Companion to 312991d (which captured only the file rename). This commit carries the actual refactor: change of base class to FidoSessionIntegrationTestBase, removal of the eager constructor and helper methods, switch to Session-level Fido2Session API for the 3 test bodies. See 312991d commit message for full rationale. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FidoSessionIntegrationTestBase's constructor calls GetSession() to
clean up stale credentials, which eagerly resolves Device through
IntegrationTestDeviceEnumeration.GetTestDevice(). On macOS the
YubiKeyDeviceListener populates its device cache asynchronously, so
the Device lookup races the listener and throws
DeviceNotFoundException ("Could not find any connected Yubikeys")
even when a supported YubiKey is plugged in and present in the
allow-list.
Working FIDO2 tests (MakeCredentialBlobTests, etc.) only avoid this
by happenstance: an earlier test class in the same xunit run calls
YubiKeyDevice.FindAll() (which triggers a synchronous poll) and
warms the cache for subsequent FindByTransport(All) lookups. When
PreviewSignTests is the first class to instantiate, the warm-up
never happens.
Add a static constructor to PreviewSignTests that calls
YubiKeyDevice.FindAll().ToList() once per AppDomain, before any
instance constructor runs. The synchronous enumeration populates
the cache that FindByTransport(All) reads, eliminating the race.
Self-contained fix — does not modify shared TestUtilities, does not
affect other test classes. The deeper cache-discrepancy bug between
FindAll and FindByTransport on macOS is worth filing separately
against the SDK team.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two issues surfaced during the first hardware run on macOS with YubiKey 103 (firmware 5.8.0.beta.0): 1. Race condition: FidoSessionIntegrationTestBase's constructor eagerly resolves Device through IntegrationTestDeviceEnumeration .GetTestDevice -> YubiKeyDevice.FindByTransport(All), which reads the YubiKeyDeviceListener's _internalCache. On macOS that cache is populated asynchronously via background USB notifications, so the first test class to instantiate races the listener and gets an empty result -> DeviceNotFoundException -> tests skip with "Could not find any connected Yubikeys (Transport: All)" even when the device is plugged in and present in the allow-list. Fix: poll YubiKeyDevice.FindAll() in a static constructor (runs once per AppDomain before any instance constructor) until at least one device appears or 5 seconds elapse. The loop is harmless when the cache is already populated and only adds wall time when the device is missing (in which case the test would skip anyway). 2. Wrong exception type: Fido2Session.MakeCredential wraps the underlying CTAP error code in a Fido2Exception, not a Ctap2DataException as the test originally expected. The test path (ES256 rejected by 5.8.0-beta firmware) does fire the exception correctly; only the assertion type was wrong. Fix: assert Fido2Exception in MakeCredentialWithUnsupportedAlgorithm _Fails. Verified on hardware: MakeCredentialWithUnsupportedAlgorithm_Fails passes (779ms, no touch required since the YK rejects ES256 before requesting user presence). Note: the IntegrationTestDeviceEnumeration source docstring claims the allow-list file lives at ~/.local/share/Yubico/...txt on macOS, but Environment.SpecialFolder.LocalApplicationData on .NET 8 macOS actually resolves to ~/Library/Application Support/. The docstring should be updated upstream. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two stacked bugs were preventing FullCeremony_RegisterDeriveSignVerify_RoundTrip from passing against YK 103 firmware 5.8.0-beta. Both fixed: 1) GetAssertionParameters.EncodeArkgSignArgs wrote -9 (Esp256) at key 3 of the COSE_Sign_Args map. Firmware rejects everything but ArkgP256Esp256 (-65539) at protocol-decode time. Verified across four independent reference implementations: - cnh-authenticator-rs-extension/native/crates/hid-test/src/main.rs:28 - cnh-authenticator-rs-extension/scripts/arkg_p256.py:339 - cnh-authenticator-rs-extension/test-page/index.html:555 - python-fido2/fido2/cose.py:391+459 2) PreviewSignTests omitted GetAssertionParameters.AllowCredential() before AddPreviewSignByCredentialExtension(). python-fido2's reference implementation (extensions.py:788-789) explicitly enforces this precondition; firmware enforces the same rule and rejects with "option or extension is unsupported or invalid" when the allow-list is missing. Test now mirrors the upstream demo's call sequence. CoseAlgorithmIdentifier XML docs rewritten so future readers cannot misapply Esp256 in sign-args contexts (the misleading guidance in the original docs is what produced bug #1). Verification on YK 103, FW 5.8.0.beta.0, macOS arm64: PreviewSignTests integration suite: 3/3 PASS - MakeCredentialWithUnsupportedAlgorithm_Fails - MakeCredentialWithPreviewSign_ReturnsGeneratedKey - FullCeremony_RegisterDeriveSignVerify_RoundTrip Yubico.YubiKey.UnitTests: 3587/3587 PASS (baseline match) Yubico.Core.UnitTests: 488/488 PASS, 21 SKIP (baseline match) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ceEnumeration Environment.SpecialFolder.LocalApplicationData on .NET 8 macOS resolves to ~/Library/Application Support, not the XDG-style ~/.local/share documented previously. Add a Linux row for completeness and cite SpecialFolder so future readers can verify the resolution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…elper The PreviewSignTests static ctor's polling block defeats a YubiKeyDeviceListener startup race specific to macOS (the IOKit run loop arms on a background thread and Update() can return before the first arrival callback fires). The same race will affect any other Fido2/Hid integration test class whose base constructor enumerates devices, so promote the workaround into DeviceListenerCacheWarmup.WaitForFirstDevice() in TestUtilities. PreviewSignTests now calls the helper from its static ctor; behavior is unchanged. Other test classes can adopt the helper as needed. Underlying SDK race remains unfixed and tracked separately — a real fix needs to drive synchronous initial enumeration through MacOSHidDeviceListener or have YubiKeyDeviceListener.Update() wait for the first callback pass, both of which are larger than this PR's scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three audit fixes plus a regression test for the new precondition guard. All four are concrete, well-scoped changes from Plans/codeaudit-previewsign-port.md. 1. Crypto leak (HIGH): ArkgPrimitivesOpenSsl.BlBlindPublicKey now wraps its body in try/finally and zeroes the blinding scalar tauBytes via CryptographicOperations.ZeroMemory. Brings tauBytes in line with the other secret-bearing arrays in the same file (ephSkBytes, kPrime, mk, ikmTau, prk, full) which were already zeroed. 2. API footgun (HIGH): GetAssertionParameters.AddPreviewSignByCredentialExtension now throws InvalidOperationException with an actionable message when the parent's allow-list is null/empty. Without this guard, customers got a cryptic firmware "option or extension invalid" error from the YubiKey. The required precondition is enforced at the protocol level by the firmware (and documented in python-fido2's reference impl); the SDK should fail fast and explain how to fix the call site. 3. Documentation lies (LOW): MakeCredentialData.GetPreviewSignGeneratedKey and AuthenticatorData.GetPreviewSignSignature each had stale <exception cref="NotImplementedException"> tags inherited from a draft that were no longer accurate. Deleted. 4. Regression test: PreviewSignExtensionTests now asserts AddPreviewSignByCredentialExtension throws InvalidOperationException with "AllowCredential" in the message when the allow-list is empty. New helper BuildAuthenticatorInfoWithPreviewSign supports the test without hardware. Verification: Yubico.YubiKey.UnitTests: 3588 PASS (3587 baseline + 1 new test) Yubico.Core.UnitTests: 488 PASS / 21 SKIP (baseline match) Build: 0 warnings, 0 errors 3 ARKG NativeShims tests still fail with EntryPointNotFoundException for Native_EC_POINT_is_on_curve — expected interim state until the Yubico.NativeShims 1.16.1-prerelease.20260428.1 NuGet package lands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the private HkdfSha256 method from ArkgPrimitivesOpenSsl that existed solely as a workaround because HkdfUtilities lived in the wrong assembly (Yubico.YubiKey, unreachable from Core). Now that HkdfUtilities is in Yubico.Core, ARKG can call the shared canonical implementation. 44 lines of duplicated cryptographic code removed. ARKG KAT vectors verify byte-for-byte equivalence with the previous local copy. The .ToArray() calls at lines 271 + 291 are forced by downstream code expecting byte[] (mk fed to HMACSHA256 ctor, shared returned as byte[]). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dd829ec to
bc25944
Compare
Summary
Adds the previewSign WebAuthn extension to the v1 SDK (ARKG-P256 key generation, offline derivation, sign-by-credential, offline signature verification) targeting YubiKey 5.8.0-beta firmware. Ported from yubikit-swift
release/1.3.0, cross-verified againstpython-fido2, the Rustcnh-authenticator-rs-extensionreference, and the upstreamYubico/5-8-hello-worldquickstart.ARKG-P256 (RFC draft
bradleylundberg-cfrg-arkg-09) implemented inYubico.Core.Cryptography.ArkgPrimitivesOpenSslvia OpenSSL P/Invoke throughYubico.NativeShims. No BouncyCastle dependency.Stacking: depends on #472. Merge #472 first — this branch consumes its new
Native_EC_POINT_is_on_curveexport, theYubico.NativeShims 1.16.1-prerelease.20260428.1version bump, and the relocatedHkdfUtilities.Verification
Yubico.YubiKey.UnitTestsYubico.Core.UnitTestsArkgP256Tests+ArkgPrimitivesTests)PreviewSignTests(3 tests)/t:DocFXBuildwarnings-as-errorsCI note
submit-nugetwill fail untilYubico.NativeShims 1.16.1-prerelease.20260428.1is reachable from the public NuGet feed (currently published only to Yubico's internal feed). All other CI checks green across Windows/Linux/macOS.In-branch design docs
Plans/preview-sign-v1-port-plan.md(design),codeaudit-previewsign-port.md(vslsp + crypto audit),python-fido2-reference-findings.md(cross-impl archaeology),previewsign-followups.md(deferred cleanup with suggested PR sequence). Untracked — intentionally kept out of this PR's tree.