EdDSA cryptographic suite for linked data files. The interface is compatible with the W3C specification of JSON-LD, Verifiable Credentials, Verifiable Credential Data Integrity and EdDSA Cryptosuite.
EdDSA cryptosuite can be used to provide integrity and authenticity guarantees for linked data files. This package is designed to provide the EdDSA cryptographic suite. This suite SHOULD be used with the vc-data-integrity framework.
To use this package within your own Deno project, run:
deno add jsr:@herculas/vc-suite-eddsa
Initialize an Ed25519 keypair instance, and generate a keypair.
const keypair = new Ed25519Keypair()
keypair.controller = "did:example:1145141919810"
await keypair.initialize()
Export an Ed25519 keypair instance to a verification method, which could further be encapsulated in a controlled identifier document (e.g., a DID document).
const method = await keypair.export({ type: "JsonWebKey", flag: "private" })
The export()
method accepts an options
object as parameter, which should contain type
and flag
fields. The
type
field specifies the key format in the exported verification method, offering two options: Multikey
or
JsonWebKey
. The flag
parameter specifies whether to export the private or public key-if the specified key is not
present in the current keypair instance, an error will be raised. Notably, when flag
is set to private
and the
keypair instance contains both public and private keys, the system automatically exports the public key alongside the
private key.
Here is an example of the exported verification method:
{
"id": "did:example:1145141919810#eE700u33DYIS0Gnm8UUNNwxnMhknV53I7piF2ciBZDM",
"type": "JsonWebKey",
"controller": "did:example:1145141919810",
"secretKeyJwk": {
"kty": "OKP",
"use": "sig",
"key_ops": ["sign"],
"alg": "Ed25519",
"ext": true,
"crv": "Ed25519",
"x": "38sLe-pQmQF-Bn7XPdP9LlWQIxhUCuE0HqFYHBFoX74",
"y": "",
"d": "jsKu-dEUpTmXAKLRoJbUd4EsIEbm0sNICbN4tjUTmXs"
},
"publicKeyJwk": {
"kty": "OKP",
"use": "sig",
"key_ops": ["verify"],
"alg": "Ed25519",
"ext": true,
"crv": "Ed25519",
"x": "38sLe-pQmQF-Bn7XPdP9LlWQIxhUCuE0HqFYHBFoX74",
"y": ""
}
}
Externally obtained verification methods can also be imported into keypair instances:
const recoveredKeypair = await Ed25519Keypair.import(method)
The import()
method accepts an optional options
parameter, containing three optional fields:
checkContext
: aboolean
indicating whether to check the@context
field of the imported document. Defaults tofalse
.checkExpired
: aboolean
indicating whether to check if the imported document has expired. Defaults tofalse
.checkRevoked
: aboolean
indicating whether to check if the keys contained in the imported document have been revoked. Defaults tofalse
.
The exported verification method could be encapsulated in a controlled identifier document (e.g., a DID document), which
could further be used for proof generation and verification. The verification method can either be directly wrapped to
generate a new document, or added to an existing document by passing the document as the second parameter of
encapsulateVerificationMethod
function.
import { document } from "@herculas/vc-data-integrity"
const cidDocument = document.encapsulateVerificationMethod(
method,
undefined,
new Set(["assertionMethod"]),
)
The third parameter of the function specifies the verification relationship, please refer to Controlled Identifiers. The generated controlled identifier document looks like:
{
"@context": "https://www.w3.org/ns/cid/v1",
"id": "did:example:1145141919810",
"verificationMethod": [
{
"id": "did:example:1145141919810#eE700u33DYIS0Gnm8UUNNwxnMhknV53I7piF2ciBZDM",
"type": "JsonWebKey",
"controller": "did:example:1145141919810",
"secretKeyJwk": {
"kty": "OKP",
"use": "sig",
"key_ops": ["sign"],
"alg": "Ed25519",
"ext": true,
"crv": "Ed25519",
"x": "38sLe-pQmQF-Bn7XPdP9LlWQIxhUCuE0HqFYHBFoX74",
"y": "",
"d": "jsKu-dEUpTmXAKLRoJbUd4EsIEbm0sNICbN4tjUTmXs"
},
"publicKeyJwk": {
"kty": "OKP",
"use": "sig",
"key_ops": ["verify"],
"alg": "Ed25519",
"ext": true,
"crv": "Ed25519",
"x": "38sLe-pQmQF-Bn7XPdP9LlWQIxhUCuE0HqFYHBFoX74",
"y": ""
}
}
],
"assertionMethod": [
"did:example:1145141919810#eE700u33DYIS0Gnm8UUNNwxnMhknV53I7piF2ciBZDM"
]
}
Compatible with the EdDSA Cryptosuite specification, this library provides two
cryptographic suites: eddsa-rdfc-2022
and eddsa-jcs-2022
. Next, we use eddsa-rdfc-2022
as a demonstration example,
as operations with eddsa-jcs-2022
are essentially the same.
The following is the document that needs to be proven:
const unsecuredCredential: Credential = {
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2",
],
"id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
"type": ["VerifiableCredential", "AlumniCredential"],
"name": "Alumni Credential",
"description": "A minimum viable example of an Alumni Credential.",
"issuer": "https://vc.example/issuers/5678",
"validFrom": "2023-01-01T00:00:00Z",
"credentialSubject": {
"id": "did:example:abcdefgh",
"alumniOf": "The School of Examples",
},
}
To prove this, first construct a proofOptions
object that contains some metadata for generating the proof. Please note
that the verificationMethod
in the proofOptions
should be a valid URL or DID, which will be used to index the
verification method for generating and validating proofs.
const proofOptions: Proof = {
"@context": [
"https://www.w3.org/ns/credentials/v2",
],
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-rdfc-2022",
"created": "2025-01-24T23:36:38Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:example:1145141919810#eE700u33DYIS0Gnm8UUNNwxnMhknV53I7piF2ciBZDM"
}
Next, a proof is generated for the given unsecuredDocument
and proofOptions
. Note that the createProof()
method
accepts a documentLoader
function as a parameter, which loads external files needed for proof generation—including
JSON-LD Context files and the verification method containing key materials.
const proof = await EddsaRdfc2022.createProof(
unsecuredCredential,
{
proof: proofOptions,
documentLoader: testLoader,
},
)
The resulting proof
is:
{
"@context": [
"https://www.w3.org/ns/credentials/v2"
],
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-rdfc-2022",
"created": "2025-01-24T23:36:38Z",
"verificationMethod": "did:example:1145141919810#eE700u33DYIS0Gnm8UUNNwxnMhknV53I7piF2ciBZDM",
"proofPurpose": "assertionMethod",
"proofValue": "z2YwC8z3ap7yx1nZYCg4L3j3ApHsF8kgPdSb5xoS1VR7vPG3F561B52hYnQF9iseabecm3ijx4K1FBTQsCZahKZme"
}
The following is a document secured by a data integrity proof.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
"type": ["VerifiableCredential", "AlumniCredential"],
"name": "Alumni Credential",
"description": "A minimum viable example of an Alumni Credential.",
"issuer": "https://vc.example/issuers/5678",
"validFrom": "2023-01-01T00:00:00Z",
"credentialSubject": {
"id": "did:example:abcdefgh",
"alumniOf": "The School of Examples"
},
"proof": {
"@context": [
"https://www.w3.org/ns/credentials/v2"
],
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-rdfc-2022",
"created": "2025-01-24T23:36:38Z",
"verificationMethod": "did:example:1145141919810#eE700u33DYIS0Gnm8UUNNwxnMhknV53I7piF2ciBZDM",
"proofPurpose": "assertionMethod",
"proofValue": "z2YwC8z3ap7yx1nZYCg4L3j3ApHsF8kgPdSb5xoS1VR7vPG3F561B52hYnQF9iseabecm3ijx4K1FBTQsCZahKZme"
}
}
The following verifyProof
method verifies whether the proof
field contained in the above document ensures the
document's authenticity and integrity.
const result = await EddsaRdfc2022.verifyProof(securedCredential, { documentLoader: testLoader })
The result
should be:
{
"verified": true,
"verifiedDocument": {
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
"type": ["VerifiableCredential", "AlumniCredential"],
"name": "Alumni Credential",
"description": "A minimum viable example of an Alumni Credential.",
"issuer": "https://vc.example/issuers/5678",
"validFrom": "2023-01-01T00:00:00Z",
"credentialSubject": {
"id": "did:example:abcdefgh",
"alumniOf": "The School of Examples"
}
}
}