A header-only C++ library for verification of did:x509 identifiers. The method is registered within the W3C DID Extensions registry and listed in the W3C DID Extensions Methods registry.
- C++20.
- OpenSSL 3.3 or newer, including development headers and
libcrypto. Older OpenSSL versions are not supported. - CMake 3.18 or newer for CMake-based builds.
For a non-system OpenSSL installation, pass -DOPENSSL_ROOT_DIR=<prefix> when
configuring CMake.
#include <didx509cpp.h>
std::string pem_chain = ...;
std::string did = "did:x509:0:sha256:WE4P5dd8DnLHSkyHaIjhp4udlkF9LqoKwCvu9gl38jk::eku:1.3.6.1.4.1.311.10.3.13";
try {
std::string doc = resolve(pem_chain, did);
} catch (...)
{...}
// Or when resolving a historical did, for example for audit purposes
try {
std::string doc = resolve(pem_chain, did, true /* Ignore time */));
} catch (...)
{...}The method-version-0 fulcio predicate selects a registered standalone
Fulcio extension on the leaf certificate. For Issuer V2 (1.3.6.1.4.1.57264.1.8),
use the full percent-encoded issuer, including its scheme:
::fulcio:issuer:https%3A%2F%2Ftoken.actions.githubusercontent.com
All 17 registered fields
are supported, including source/build metadata, deployment-environment, and
token-subject. Each predicate requires exactly one literal field and one
nonempty percent-encoded UTF-8 value. Multiple predicates are ANDed.
Fulcio username identities use the registered OtherName type inside the SAN extension, independently of standalone Fulcio extensions:
::san:othername:1.3.6.1.4.1.57264.1.7:alice%21example.com
The type OID must be literal, and the complete username SAN (alice!example.com
here) is compared exactly, not reconstructed from token-subject. Scalar values
are decoded once, without case folding, URI rewriting, or Unicode normalization.
The existing fulcio-issuer predicate still selects only the legacy raw UTF-8
extension .1, with https:// omitted from the predicate value. It never falls
back to .8, and fulcio:issuer never falls back to .1. DID URL fragments
are excluded from predicate matching and document IDs; percent-escape spelling
in the DID is preserved.
DID URL paths and queries are rejected. Slash and question-mark characters in
identity values must be percent-encoded; they remain permitted inside fragments.
All scalar predicates, including existing SAN, subject, and legacy issuer forms,
require nonempty, correctly percent-encoded UTF-8 values. The eku predicate
value must be a canonical dotted-decimal OID. Subject names that repeat an
attribute type are not supported by the specification's certificate model and
are rejected rather than matched against any one of their values.
Registered OtherName values and standalone .8-.24 extensions require a
complete, minimally encoded DER UTF8String. Malformed or unsupported SAN entries
and malformed registered Fulcio extensions fail resolution even when unselected
or present on a CA certificate. Standalone Fulcio extensions must be noncritical;
normal certificate path validation is not bypassed.
Email, DNS, and URI SANs must contain valid ASCII IA5Strings. The supplied
certificates must match the verified leaf-first chain exactly, so path building
cannot silently discard malformed or duplicate evidence.
Resolution produces the DID document defined by the specification: the
@context is https://www.w3.org/ns/cid/v1, the single verification method
<DID>#0 has type JsonWebKey, and verification relationships are derived
from the leaf certificate's Key Usage as described below. This only affects
callers of resolve() that read @context or type from the document, which
previously used JsonWebKey2020 with the DID Core and JWS 2020 contexts. The
JWK itself, and therefore resolve_jwk(), is unchanged.
The resolver exports RSA, EC (P-256, P-384, and P-521), and Ed25519 public keys.
Ed25519 keys are exported as an
RFC 8037 JWK with kty: "OKP",
crv: "Ed25519", and the base64url-encoded 32-byte public key in x. The
encoding must be canonical per
RFC 8032 section 5.1.3:
a key whose y-coordinate is not less than the field prime is rejected, even
though OpenSSL accepts it.
Ed25519 keys are signing-only: the DID document includes authentication and
assertionMethod, never keyAgreement. If the leaf certificate has a Key
Usage extension, it must include digitalSignature and, following
RFC 8410 section 5, must
not include keyAgreement, keyEncipherment, dataEncipherment,
encipherOnly, or decipherOnly. Without Key Usage, the key is still treated
as signing-only.
RSA and EC keys include authentication and assertionMethod when Key Usage
is absent or includes digitalSignature, and keyAgreement when Key Usage is
absent or includes keyAgreement. A Key Usage extension with neither is
rejected.
To run clang-tidy locally, configure with Clang 18 and enable the opt-in target:
cmake -S . -B build/clang-tidy \
-DCMAKE_CXX_COMPILER=clang++-18 \
-DCLANG_TIDY=ON \
-DTESTS=ON
cmake --build build/clang-tidy --target clang-tidyThis project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.