ANP 1.1 is the default latest version. ANP 1.0 remains available as an archive.
A.1 Scope of application
This appendix defines the k1_ path binding profile for compatibility with the wallet ecosystem and existing secp256k1 implementation. k1_ does not belong to the default scheme of the main specification. New deployments SHOULD give priority to using the e1_ profile of the main specification.
A.2 k1_ path syntax
When an implementation enables this appendix, the last path segment of a path-type DID can be used:
k1_<fingerprint>The ABNF extension of Appendix A is as follows:
k1-fingerprint = "k1_" 43base64url-char
wba-k1-path-did = "did:wba:" domain-name 1*(":" path-segment) ":" k1-fingerprintExample:
did:wba:example.com:user:alice:k1_<fingerprint>
did:wba:example.com%3A3000:user:alice:k1_<fingerprint>A.3 k1_ Fingerprint generation method
The k1_ fingerprint is used to associate the path DID with the secp256k1 bound public key. The generation method is as follows:
Select a DID binding key. The binding key MUST meet the following conditions:
- is a secp256k1 public key;
- Represented as
publicKeyJwkin DID documents; - Authorized by the
authenticationrelationship of the DID document.
Get the JWK public key object corresponding to the binding key and retain only the necessary fields required by RFC 7638:
{
"crv": "secp256k1",
"kty": "EC",
"x": "...",
"y": "..."
}Generate JWK Thumbprint input according to the rules of RFC 7638:
- Only keep necessary fields;
- Field names are sorted lexicographically;
- Use JSON strings without extra whitespace;
- Use UTF-8 encoding.
Perform a SHA-256 hash on the UTF-8 byte sequence obtained in step 3 to obtain a 32-byte digest value.
Base64url encode the 32-byte digest value and remove the trailing
=padding. The encoding result length is fixed at 43 characters.Add the
k1_prefix in front of the encoding result to get the final path segment.
A.4 k1_ DID Document constraint
When DID uses k1_ profile, the DID Document must at least meet:
idis exactly the same as the requested DID;- There is at least one secp256k1
publicKeyJwkinverificationMethodas a binding key; - The binding key MUST be authorized by the
authenticationrelationship; - The RFC 7638 thumbprint of the binding key MUST be exactly the same as the last
k1_fingerprint segment of the DID path.
The recommended k1 binding verification method shape is as follows:
{
"id": "did:wba:example.com:user:alice:k1_<fingerprint>#key-1",
"type": "EcdsaSecp256k1VerificationKey2019",
"controller": "did:wba:example.com:user:alice:k1_<fingerprint>",
"publicKeyJwk": {
"crv": "secp256k1",
"kty": "EC",
"x": "...",
"y": "...",
"kid": "<fingerprint>"
}
}A.5 DID Document proof of k1_ (compatible extension)
For DIDs using the k1_ profile, this appendix defines a non-standard, optional secp256k1 DID Document proof profile to provide DID Document integrity proof capabilities in the wallet ecosystem or existing secp256k1 implementation.
This proof profile does not fall within the scope of W3C standards interoperability defined by the mainline of this specification. If the implementation chooses to support this section, it should generate and verify the k1_ DID Document proof according to the rules of this section; implementations that do not support this section may (MAY) ignore the proof field in the k1_ DID Document.
A.5.1 proof object field
When the k1_ DID Document contains the top-level proof field, the proof object contains the following fields:
type: required field. Fixed toDataIntegrityProofcryptosuite: required field. Fixed todidwba-jcs-ecdsa-secp256k1-2025created: required field. Proof creation time, in XML Schema datetime formatverificationMethod: required field. Full DID URL pointing to the secp256k1 verification method in the DID Document used to generate the proofproofPurpose: required field. Fixed toassertionMethodproofValue: required field. Signature value, encoding rules see later in this sectiondomain: optional fieldchallenge: optional field
Additional constraints:
- It is recommended (SHOULD) to directly use the
k1_binding key asproof.verificationMethodto unify DID binding and document integrity certification; - The verification method pointed to by
proof.verificationMethodmust correspond one-to-one with the private key actually used to generateproofValue.
A.5.2 proof generation process
Implementations that use k1_ profile and need to generate DID Document proof should follow the following process:
- Copy the DID Document to be signed and remove the top-level
prooffield to getunsecuredDocument; - Construct a proof options object, including:
typecryptosuitecreatedverificationMethodproofPurpose- Optional
domain - Optional
challenge
- Perform JCS standardization on DID Document and proof options respectively;
- Calculate the SHA-256 hash values of both;
- Splice
hash(proofOptions) || hash(document)to obtain the byte string to be signed; - Use the secp256k1 private key pointed to by
verificationMethodto perform ECDSA + SHA-256 signature on the byte string to obtain a DER encoded signature; - Convert the DER encoded signature to a fixed-length 64-byte
R || S; - Encode
R || Swith base64url (without padding) and writeproofValue; - Add the generated
proofobject back to the top level of the DID Document.
A.5.3 proof verification process
If you use k1_ profile and need to verify the implementation of DID Document proof, you should follow the following process:
- Read the top level
proofof DID Document; - Check whether the following fields exist:
typecryptosuitecreatedverificationMethodproofPurposeproofValue
- Check:
- Whether
typeisDataIntegrityProof - Whether
cryptosuiteisdidwba-jcs-ecdsa-secp256k1-2025 - Whether
proofPurposeisassertionMethod
- Whether
- Remove
prooffrom the DID Document to obtain the document to be verified; - Remove
proofValuefromproofto get proof options; - Perform JCS normalization on documents and proof options respectively;
- Calculate the SHA-256 hashes separately and concatenate them into:
hash(proofOptions) || hash(document)
- Parse the secp256k1 public key pointed to by
verificationMethod; - Decode
proofValuewith base64url and restore 64 bytesR || S; - Convert
R || Sinto a signature representation acceptable for ECDSA signature verification; - Use the corresponding secp256k1 public key to perform ECDSA + SHA-256 signature verification on the spliced byte string to be verified;
- If the signature verification is successful, the proof verification passes; otherwise, the verification fails.
A.5.4 Parsing strategy
For k1_ DID, proof verification is an optional enhanced integrity check by default; but once the local policy enables proof verification, proof verification and DID binding verification must be completed simultaneously with the secp256k1 public key corresponding to proof.verificationMethod.
Implementations MAY choose one of two modes:
- Relaxed mode: If the DID Document does not contain
proof, parsing can still continue; - Strict mode: If the local policy requires that the
k1_document must carry proof, then the DID Document missingproofMUST be regarded as a verification failure.
If the implementation enables strict proof checking, it MUST additionally check:
- The verification method type pointed to by
proof.verificationMethodisEcdsaSecp256k1VerificationKey2019; - Use the secp256k1 public key corresponding to this verification method to recalculate the RFC 7638 thumbprint. The result must be completely consistent with the last
k1_fingerprint segment of the DID path; - Other secp256k1 keys in the DID Document that have not participated in the proof must not be used in place of
proof.verificationMethodto complete the binding verification.
If an implementation does not declare support for didwba-jcs-ecdsa-secp256k1-2025, it MAY ignore this proof in the k1_ DID Document.
Note: The k1_ DID Document proof defined in this appendix is a compatible extension of did:wba and is used to support document integrity proof in the secp256k1 binding key scenario. This proof profile does not belong to the W3C standard interoperability proof. The standard proof scheme recommended by the main specification is still DataIntegrityProof + eddsa-jcs-2022 under the e1_ profile.
A.6 k1_ Identity Authentication
When an implementation enables this appendix, the k1_ DID can be used in the cross-platform HTTP authentication flow defined in Chapter 3.
Certification requirements are as follows:
- By default, the client SHOULD use the secp256k1 binding key bound to the
k1_path for signing; keyidMUST point to the secp256k1 binding verification method in the DID document;- The signature algorithm is ECDSA + SHA-256 on the secp256k1 curve;
- The signature output uses fixed-length
r || sbyte string encoding; - When verifying, the server must (MUST) check at the same time:
- The verification method pointed to by
keyidexists; - This verification method is located in
authentication; - The thumbprint of this verification method is consistent with the
k1_fingerprint segment.
- The verification method pointed to by
A.7 k1_ DID Document proof Interoperability instructions
This appendix defines did:wba's own k1_ compatible proof profile (see A.5), which is used to provide optional DID Document integrity proof capability in the secp256k1 binding scenario. It is not the W3C standard eddsa-jcs-2022 mainline proof, but a compatible extension of did:wba.
Therefore:
k1_DID Document MAY not contain top-levelproof;- If the implementation enables proof verification, it should be executed according to the
didwba-jcs-ecdsa-secp256k1-2025rules of A.5; - If the implementation does not enable proof verification, you MAY ignore the proof in the
k1_document; - Once proof verification is enabled, other secp256k1 keys in the DID Document that are not involved in proof must not be used instead of
proof.verificationMethodto complete binding verification.
A.8 k1_ creation, parsing and updating
- Create: generate secp256k1 binding key, calculate
k1_fingerprint segment, and storedid.jsonunder the corresponding path; - Parsing: In addition to the general parsing process of the main specification, the
k1_binding relationship is also verified according to A.3 and A.4; - Update: As long as the
k1_binding key remains unchanged, the DID itself remains unchanged; if the binding key changes, the DID MUST change; - Decommissioning: Rotation can be accomplished by deactivating the old DID and creating a new one; stable reference relationships are maintained by the upper-layer name service.