Open question, deliberately not scheduled. Recorded so the answer is found rather than re-derived, and so nobody adds a second curve by accident while writing a mapper.
Recorded in an internal architecture decision record, 2026-07-31.
Where this stands
We sign with Ed25519/EdDSA only. is_allowed_alg is a one-element allowlist by design (crates/dpp-crypto/src/jws/algorithm.rs), which makes JWS algorithm confusion impossible by construction.
Checked against primary sources on 2026-07-31, nothing we are building requires P-256:
| Source |
Requirement |
| UNTP Verifiable Credentials profile |
MUST use enveloping VC-JOSE-COSE with JOSE; MUST implement did:web. No algorithm named |
draft-ietf-oauth-sd-jwt-vc-17 |
No algorithm mandated. ES256 appears in examples only |
| W3C Data Integrity |
eddsa-jcs-2022 / eddsa-rdfc-2022 are the Ed25519 cryptosuites. The embedded form does not force P-256 |
| OpenID4VC HAIP |
MUST support P-256/ES256 — but scoped to wallet-based issuance and presentation flows |
| EUDI Wallet ARF |
ES256/384/512 — same wallet ecosystem |
Every hard ES256 requirement sits in the wallet ecosystem. Nothing in the doors we are building does.
The trigger that reopens this
We commit to the EUDI wallet / OpenID4VC ecosystem — issuing into a wallet over OpenID4VCI, or accepting OpenID4VP presentations. That is a product decision about which ecosystem we sell into, not a cryptographic one.
Weaker secondary trigger: an integrator presents a verifier that is ES256-only and will not change. That is a data point, not a mandate — the response might be a hosted verification endpoint rather than a second curve.
The one risk not retired
🔶 We never measured how many real VC verifiers accept EdDSA. "Much of the ecosystem is ES256" is asserted in two planning docs and neither cites anything. EdDSA is RFC 8037 and mainstream JOSE libraries implement it, so the expectation is that this is fine — but it is an expectation, not a measurement, and it is the single thing that could make that record wrong.
Cheap way to retire it: the UNTP plan's merge gate already requires verifying our credential with an off-the-shelf JOSE library, not our own verifier. Do that check on day one of that work rather than at the end. One afternoon, and it either confirms the decision or fires the trigger before anything is built on top of it.
What must be true before this is picked up
The algorithm-agile key shape (the key-shape work) has to land first, and it is breaking:
KeyEntry (crates/dpp-crypto/src/keystore/entry.rs) is a pub struct of concrete ed25519_dalek types
PublicKeyInfo (crates/dpp-crypto/src/keystore/store.rs) carries no algorithm, so dpp-vc's DID builder cannot know which JWK shape to emit
The persisted format is already agile — KeyRecord::algorithm exists with a serde default for pre-agility stores — so the keystore data migration is not a concern. Once the shape lands, adding a curve is genuinely additive and this issue becomes a normal feature.
What it will cost when the trigger fires
- Algorithm confusion becomes reachable. Mitigated by binding
alg to KeyRecord::algorithm, never the JWS header — which is part of the shape work, not this
- Signature length stops discriminating — a P-256 JOSE signature is also 64 bytes (
r‖s), same as Ed25519, so the [u8; 64] check silently stops being a type check
- No
verify_strict analogue — Ed25519's RFC 8032 §8 strictness has no P-256 equivalent; ECDSA needs low-s normalisation instead, separately written and tested
- Cross-curve rotation is undefined, and
did:web documents would carry mixed-curve verification methods
- A
p256 dependency on the crate a recent crate-boundary decision just made a zero-workspace-dependency leaf
Out of scope in any case: dpp-rules's JwsVerify::verify_eddsa. Plugin-bundle signing is a separate trust domain and can stay Ed25519-only indefinitely; generalising it needs its own reason.
Open question, deliberately not scheduled. Recorded so the answer is found rather than re-derived, and so nobody adds a second curve by accident while writing a mapper.
Recorded in an internal architecture decision record, 2026-07-31.
Where this stands
We sign with Ed25519/EdDSA only.
is_allowed_algis a one-element allowlist by design (crates/dpp-crypto/src/jws/algorithm.rs), which makes JWS algorithm confusion impossible by construction.Checked against primary sources on 2026-07-31, nothing we are building requires P-256:
did:web. No algorithm nameddraft-ietf-oauth-sd-jwt-vc-17eddsa-jcs-2022/eddsa-rdfc-2022are the Ed25519 cryptosuites. The embedded form does not force P-256Every hard ES256 requirement sits in the wallet ecosystem. Nothing in the doors we are building does.
The trigger that reopens this
We commit to the EUDI wallet / OpenID4VC ecosystem — issuing into a wallet over OpenID4VCI, or accepting OpenID4VP presentations. That is a product decision about which ecosystem we sell into, not a cryptographic one.
Weaker secondary trigger: an integrator presents a verifier that is ES256-only and will not change. That is a data point, not a mandate — the response might be a hosted verification endpoint rather than a second curve.
The one risk not retired
🔶 We never measured how many real VC verifiers accept EdDSA. "Much of the ecosystem is ES256" is asserted in two planning docs and neither cites anything. EdDSA is RFC 8037 and mainstream JOSE libraries implement it, so the expectation is that this is fine — but it is an expectation, not a measurement, and it is the single thing that could make that record wrong.
Cheap way to retire it: the UNTP plan's merge gate already requires verifying our credential with an off-the-shelf JOSE library, not our own verifier. Do that check on day one of that work rather than at the end. One afternoon, and it either confirms the decision or fires the trigger before anything is built on top of it.
What must be true before this is picked up
The algorithm-agile key shape (the key-shape work) has to land first, and it is breaking:
KeyEntry(crates/dpp-crypto/src/keystore/entry.rs) is apubstruct of concreteed25519_dalektypesPublicKeyInfo(crates/dpp-crypto/src/keystore/store.rs) carries no algorithm, sodpp-vc's DID builder cannot know which JWK shape to emitThe persisted format is already agile —
KeyRecord::algorithmexists with a serde default for pre-agility stores — so the keystore data migration is not a concern. Once the shape lands, adding a curve is genuinely additive and this issue becomes a normal feature.What it will cost when the trigger fires
algtoKeyRecord::algorithm, never the JWS header — which is part of the shape work, not thisr‖s), same as Ed25519, so the[u8; 64]check silently stops being a type checkverify_strictanalogue — Ed25519's RFC 8032 §8 strictness has no P-256 equivalent; ECDSA needs low-s normalisation instead, separately written and testeddid:webdocuments would carry mixed-curve verification methodsp256dependency on the crate a recent crate-boundary decision just made a zero-workspace-dependency leafOut of scope in any case:
dpp-rules'sJwsVerify::verify_eddsa. Plugin-bundle signing is a separate trust domain and can stay Ed25519-only indefinitely; generalising it needs its own reason.